Merge branch 'v3-2-test' of git://git.samba.org/samba into v3-2-test
[nivanova/samba-autobuild/.git] / source3 / smbd / trans2.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005-2007
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 static char *store_file_unix_basic(connection_struct *conn,
38                                 char *pdata,
39                                 files_struct *fsp,
40                                 const SMB_STRUCT_STAT *psbuf);
41
42 static char *store_file_unix_basic_info2(connection_struct *conn,
43                                 char *pdata,
44                                 files_struct *fsp,
45                                 const SMB_STRUCT_STAT *psbuf);
46
47 /********************************************************************
48  Roundup a value to the nearest allocation roundup size boundary.
49  Only do this for Windows clients.
50 ********************************************************************/
51
52 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
53 {
54         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
55
56         /* Only roundup for Windows clients. */
57         enum remote_arch_types ra_type = get_remote_arch();
58         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
59                 val = SMB_ROUNDUP(val,rval);
60         }
61         return val;
62 }
63
64 /********************************************************************
65  Given a stat buffer return the allocated size on disk, taking into
66  account sparse files.
67 ********************************************************************/
68
69 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
70 {
71         SMB_BIG_UINT ret;
72
73         if(S_ISDIR(sbuf->st_mode)) {
74                 return 0;
75         }
76
77 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
78         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
79 #else
80         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 #endif
82
83         if (fsp && fsp->initial_allocation_size)
84                 ret = MAX(ret,fsp->initial_allocation_size);
85
86         return smb_roundup(conn, ret);
87 }
88
89 /****************************************************************************
90  Utility functions for dealing with extended attributes.
91 ****************************************************************************/
92
93 /****************************************************************************
94  Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
96
97 static bool samba_private_attr_name(const char *unix_ea_name)
98 {
99         static const char *prohibited_ea_names[] = {
100                 SAMBA_POSIX_INHERITANCE_EA_NAME,
101                 SAMBA_XATTR_DOS_ATTRIB,
102                 NULL
103         };
104
105         int i;
106
107         for (i = 0; prohibited_ea_names[i]; i++) {
108                 if (strequal( prohibited_ea_names[i], unix_ea_name))
109                         return True;
110         }
111         return False;
112 }
113
114 /****************************************************************************
115  Get one EA value. Fill in a struct ea_struct.
116 ****************************************************************************/
117
118 static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
119                                 const char *fname, char *ea_name, struct ea_struct *pea)
120 {
121         /* Get the value of this xattr. Max size is 64k. */
122         size_t attr_size = 256;
123         char *val = NULL;
124         ssize_t sizeret;
125
126  again:
127
128         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
129         if (!val) {
130                 return False;
131         }
132
133         if (fsp && fsp->fh->fd != -1) {
134                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
135         } else {
136                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
137         }
138
139         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
140                 attr_size = 65536;
141                 goto again;
142         }
143
144         if (sizeret == -1) {
145                 return False;
146         }
147
148         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
149         dump_data(10, (uint8 *)val, sizeret);
150
151         pea->flags = 0;
152         if (strnequal(ea_name, "user.", 5)) {
153                 pea->name = &ea_name[5];
154         } else {
155                 pea->name = ea_name;
156         }
157         pea->value.data = (unsigned char *)val;
158         pea->value.length = (size_t)sizeret;
159         return True;
160 }
161
162 /****************************************************************************
163  Return a linked list of the total EA's. Plus the total size
164 ****************************************************************************/
165
166 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
167                                         const char *fname, size_t *pea_total_len)
168 {
169         /* Get a list of all xattrs. Max namesize is 64k. */
170         size_t ea_namelist_size = 1024;
171         char *ea_namelist;
172         char *p;
173         ssize_t sizeret;
174         int i;
175         struct ea_list *ea_list_head = NULL;
176
177         *pea_total_len = 0;
178
179         if (!lp_ea_support(SNUM(conn))) {
180                 return NULL;
181         }
182
183         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
184              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
185
186                 if (!ea_namelist) {
187                         return NULL;
188                 }
189
190                 if (fsp && fsp->fh->fd != -1) {
191                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
192                 } else {
193                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
194                 }
195
196                 if (sizeret == -1 && errno == ERANGE) {
197                         ea_namelist_size *= 2;
198                 } else {
199                         break;
200                 }
201         }
202
203         if (sizeret == -1)
204                 return NULL;
205
206         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
207
208         if (sizeret) {
209                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
210                         struct ea_list *listp;
211
212                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
213                                 continue;
214
215                         listp = TALLOC_P(mem_ctx, struct ea_list);
216                         if (!listp)
217                                 return NULL;
218
219                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
220                                 return NULL;
221                         }
222
223                         {
224                                 fstring dos_ea_name;
225                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
226                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
227                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
228                                         (unsigned int)*pea_total_len, dos_ea_name,
229                                         (unsigned int)listp->ea.value.length ));
230                         }
231                         DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
232                 }
233                 /* Add on 4 for total length. */
234                 if (*pea_total_len) {
235                         *pea_total_len += 4;
236                 }
237         }
238
239         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
240         return ea_list_head;
241 }
242
243 /****************************************************************************
244  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
245  that was filled.
246 ****************************************************************************/
247
248 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
249         connection_struct *conn, struct ea_list *ea_list)
250 {
251         unsigned int ret_data_size = 4;
252         char *p = pdata;
253
254         SMB_ASSERT(total_data_size >= 4);
255
256         if (!lp_ea_support(SNUM(conn))) {
257                 SIVAL(pdata,4,0);
258                 return 4;
259         }
260
261         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
262                 size_t dos_namelen;
263                 fstring dos_ea_name;
264                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
265                 dos_namelen = strlen(dos_ea_name);
266                 if (dos_namelen > 255 || dos_namelen == 0) {
267                         break;
268                 }
269                 if (ea_list->ea.value.length > 65535) {
270                         break;
271                 }
272                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
273                         break;
274                 }
275
276                 /* We know we have room. */
277                 SCVAL(p,0,ea_list->ea.flags);
278                 SCVAL(p,1,dos_namelen);
279                 SSVAL(p,2,ea_list->ea.value.length);
280                 fstrcpy(p+4, dos_ea_name);
281                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
282
283                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
284                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
285         }
286
287         ret_data_size = PTR_DIFF(p, pdata);
288         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
289         SIVAL(pdata,0,ret_data_size);
290         return ret_data_size;
291 }
292
293 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
294 {
295         size_t total_ea_len = 0;
296         TALLOC_CTX *mem_ctx = NULL;
297
298         if (!lp_ea_support(SNUM(conn))) {
299                 return 0;
300         }
301         mem_ctx = talloc_init("estimate_ea_size");
302         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
303         talloc_destroy(mem_ctx);
304         return total_ea_len;
305 }
306
307 /****************************************************************************
308  Ensure the EA name is case insensitive by matching any existing EA name.
309 ****************************************************************************/
310
311 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
312 {
313         size_t total_ea_len;
314         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
315         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
316
317         for (; ea_list; ea_list = ea_list->next) {
318                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
319                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
320                                 &unix_ea_name[5], ea_list->ea.name));
321                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
322                         break;
323                 }
324         }
325         talloc_destroy(mem_ctx);
326 }
327
328 /****************************************************************************
329  Set or delete an extended attribute.
330 ****************************************************************************/
331
332 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
333 {
334         if (!lp_ea_support(SNUM(conn))) {
335                 return NT_STATUS_EAS_NOT_SUPPORTED;
336         }
337
338         for (;ea_list; ea_list = ea_list->next) {
339                 int ret;
340                 fstring unix_ea_name;
341
342                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
343                 fstrcat(unix_ea_name, ea_list->ea.name);
344
345                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
346
347                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
348
349                 if (samba_private_attr_name(unix_ea_name)) {
350                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
351                         return NT_STATUS_ACCESS_DENIED;
352                 }
353
354                 if (ea_list->ea.value.length == 0) {
355                         /* Remove the attribute. */
356                         if (fsp && (fsp->fh->fd != -1)) {
357                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
358                                         unix_ea_name, fsp->fsp_name));
359                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
360                         } else {
361                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
362                                         unix_ea_name, fname));
363                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
364                         }
365 #ifdef ENOATTR
366                         /* Removing a non existent attribute always succeeds. */
367                         if (ret == -1 && errno == ENOATTR) {
368                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
369                                                 unix_ea_name));
370                                 ret = 0;
371                         }
372 #endif
373                 } else {
374                         if (fsp && (fsp->fh->fd != -1)) {
375                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
376                                         unix_ea_name, fsp->fsp_name));
377                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
378                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
379                         } else {
380                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
381                                         unix_ea_name, fname));
382                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
383                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
384                         }
385                 }
386
387                 if (ret == -1) {
388 #ifdef ENOTSUP
389                         if (errno == ENOTSUP) {
390                                 return NT_STATUS_EAS_NOT_SUPPORTED;
391                         }
392 #endif
393                         return map_nt_error_from_unix(errno);
394                 }
395
396         }
397         return NT_STATUS_OK;
398 }
399 /****************************************************************************
400  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
401 ****************************************************************************/
402
403 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
404 {
405         struct ea_list *ea_list_head = NULL;
406         size_t offset = 0;
407
408         while (offset + 2 < data_size) {
409                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
410                 unsigned int namelen = CVAL(pdata,offset);
411
412                 offset++; /* Go past the namelen byte. */
413
414                 /* integer wrap paranioa. */
415                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
416                                 (offset > data_size) || (namelen > data_size) ||
417                                 (offset + namelen >= data_size)) {
418                         break;
419                 }
420                 /* Ensure the name is null terminated. */
421                 if (pdata[offset + namelen] != '\0') {
422                         return NULL;
423                 }
424                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
425                 if (!eal->ea.name) {
426                         return NULL;
427                 }
428
429                 offset += (namelen + 1); /* Go past the name + terminating zero. */
430                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
431                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
432         }
433
434         return ea_list_head;
435 }
436
437 /****************************************************************************
438  Read one EA list entry from the buffer.
439 ****************************************************************************/
440
441 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
442 {
443         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
444         uint16 val_len;
445         unsigned int namelen;
446
447         if (!eal) {
448                 return NULL;
449         }
450
451         if (data_size < 6) {
452                 return NULL;
453         }
454
455         eal->ea.flags = CVAL(pdata,0);
456         namelen = CVAL(pdata,1);
457         val_len = SVAL(pdata,2);
458
459         if (4 + namelen + 1 + val_len > data_size) {
460                 return NULL;
461         }
462
463         /* Ensure the name is null terminated. */
464         if (pdata[namelen + 4] != '\0') {
465                 return NULL;
466         }
467         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
468         if (!eal->ea.name) {
469                 return NULL;
470         }
471
472         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
473         if (!eal->ea.value.data) {
474                 return NULL;
475         }
476
477         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
478
479         /* Ensure we're null terminated just in case we print the value. */
480         eal->ea.value.data[val_len] = '\0';
481         /* But don't count the null. */
482         eal->ea.value.length--;
483
484         if (pbytes_used) {
485                 *pbytes_used = 4 + namelen + 1 + val_len;
486         }
487
488         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
489         dump_data(10, eal->ea.value.data, eal->ea.value.length);
490
491         return eal;
492 }
493
494 /****************************************************************************
495  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
496 ****************************************************************************/
497
498 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
499 {
500         struct ea_list *ea_list_head = NULL;
501         size_t offset = 0;
502         size_t bytes_used = 0;
503
504         while (offset < data_size) {
505                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
506
507                 if (!eal) {
508                         return NULL;
509                 }
510
511                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
512                 offset += bytes_used;
513         }
514
515         return ea_list_head;
516 }
517
518 /****************************************************************************
519  Count the total EA size needed.
520 ****************************************************************************/
521
522 static size_t ea_list_size(struct ea_list *ealist)
523 {
524         fstring dos_ea_name;
525         struct ea_list *listp;
526         size_t ret = 0;
527
528         for (listp = ealist; listp; listp = listp->next) {
529                 push_ascii_fstring(dos_ea_name, listp->ea.name);
530                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
531         }
532         /* Add on 4 for total length. */
533         if (ret) {
534                 ret += 4;
535         }
536
537         return ret;
538 }
539
540 /****************************************************************************
541  Return a union of EA's from a file list and a list of names.
542  The TALLOC context for the two lists *MUST* be identical as we steal
543  memory from one list to add to another. JRA.
544 ****************************************************************************/
545
546 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
547 {
548         struct ea_list *nlistp, *flistp;
549
550         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
551                 for (flistp = file_list; flistp; flistp = flistp->next) {
552                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
553                                 break;
554                         }
555                 }
556
557                 if (flistp) {
558                         /* Copy the data from this entry. */
559                         nlistp->ea.flags = flistp->ea.flags;
560                         nlistp->ea.value = flistp->ea.value;
561                 } else {
562                         /* Null entry. */
563                         nlistp->ea.flags = 0;
564                         ZERO_STRUCT(nlistp->ea.value);
565                 }
566         }
567
568         *total_ea_len = ea_list_size(name_list);
569         return name_list;
570 }
571
572 /****************************************************************************
573   Send the required number of replies back.
574   We assume all fields other than the data fields are
575   set correctly for the type of call.
576   HACK ! Always assumes smb_setup field is zero.
577 ****************************************************************************/
578
579 void send_trans2_replies(struct smb_request *req,
580                          const char *params,
581                          int paramsize,
582                          const char *pdata,
583                          int datasize,
584                          int max_data_bytes)
585 {
586         /* As we are using a protocol > LANMAN1 then the max_send
587          variable must have been set in the sessetupX call.
588          This takes precedence over the max_xmit field in the
589          global struct. These different max_xmit variables should
590          be merged as this is now too confusing */
591
592         int data_to_send = datasize;
593         int params_to_send = paramsize;
594         int useable_space;
595         const char *pp = params;
596         const char *pd = pdata;
597         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
598         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
599         int data_alignment_offset = 0;
600         bool overflow = False;
601
602         /* Modify the data_to_send and datasize and set the error if
603            we're trying to send more than max_data_bytes. We still send
604            the part of the packet(s) that fit. Strange, but needed
605            for OS/2. */
606
607         if (max_data_bytes > 0 && datasize > max_data_bytes) {
608                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
609                         max_data_bytes, datasize ));
610                 datasize = data_to_send = max_data_bytes;
611                 overflow = True;
612         }
613
614         /* If there genuinely are no parameters or data to send just send the empty packet */
615
616         if(params_to_send == 0 && data_to_send == 0) {
617                 reply_outbuf(req, 10, 0);
618                 show_msg((char *)req->outbuf);
619                 return;
620         }
621
622         /* When sending params and data ensure that both are nicely aligned */
623         /* Only do this alignment when there is also data to send - else
624                 can cause NT redirector problems. */
625
626         if (((params_to_send % 4) != 0) && (data_to_send != 0))
627                 data_alignment_offset = 4 - (params_to_send % 4);
628
629         /* Space is bufsize minus Netbios over TCP header minus SMB header */
630         /* The alignment_offset is to align the param bytes on an even byte
631                 boundary. NT 4.0 Beta needs this to work correctly. */
632
633         useable_space = max_send - (smb_size
634                                     + 2 * 10 /* wct */
635                                     + alignment_offset
636                                     + data_alignment_offset);
637
638         /* useable_space can never be more than max_send minus the alignment offset. */
639
640         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
641
642         while (params_to_send || data_to_send) {
643                 /* Calculate whether we will totally or partially fill this packet */
644
645                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
646
647                 /* We can never send more than useable_space */
648                 /*
649                  * Note that 'useable_space' does not include the alignment offsets,
650                  * but we must include the alignment offsets in the calculation of
651                  * the length of the data we send over the wire, as the alignment offsets
652                  * are sent here. Fix from Marc_Jacobsen@hp.com.
653                  */
654
655                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
656
657                 reply_outbuf(req, 10, total_sent_thistime);
658
659                 /* Set total params and data to be sent */
660                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
661                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
662
663                 /* Calculate how many parameters and data we can fit into
664                  * this packet. Parameters get precedence
665                  */
666
667                 params_sent_thistime = MIN(params_to_send,useable_space);
668                 data_sent_thistime = useable_space - params_sent_thistime;
669                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
670
671                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
672
673                 /* smb_proff is the offset from the start of the SMB header to the
674                         parameter bytes, however the first 4 bytes of outbuf are
675                         the Netbios over TCP header. Thus use smb_base() to subtract
676                         them from the calculation */
677
678                 SSVAL(req->outbuf,smb_proff,
679                       ((smb_buf(req->outbuf)+alignment_offset)
680                        - smb_base(req->outbuf)));
681
682                 if(params_sent_thistime == 0)
683                         SSVAL(req->outbuf,smb_prdisp,0);
684                 else
685                         /* Absolute displacement of param bytes sent in this packet */
686                         SSVAL(req->outbuf,smb_prdisp,pp - params);
687
688                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
689                 if(data_sent_thistime == 0) {
690                         SSVAL(req->outbuf,smb_droff,0);
691                         SSVAL(req->outbuf,smb_drdisp, 0);
692                 } else {
693                         /* The offset of the data bytes is the offset of the
694                                 parameter bytes plus the number of parameters being sent this time */
695                         SSVAL(req->outbuf, smb_droff,
696                               ((smb_buf(req->outbuf)+alignment_offset)
697                                - smb_base(req->outbuf))
698                               + params_sent_thistime + data_alignment_offset);
699                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
700                 }
701
702                 /* Initialize the padding for alignment */
703
704                 if (alignment_offset != 0) {
705                         memset(smb_buf(req->outbuf), 0, alignment_offset);
706                 }
707
708                 /* Copy the param bytes into the packet */
709
710                 if(params_sent_thistime) {
711                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
712                                params_sent_thistime);
713                 }
714
715                 /* Copy in the data bytes */
716                 if(data_sent_thistime) {
717                         if (data_alignment_offset != 0) {
718                                 memset((smb_buf(req->outbuf)+alignment_offset+
719                                         params_sent_thistime), 0,
720                                        data_alignment_offset);
721                         }
722                         memcpy(smb_buf(req->outbuf)+alignment_offset
723                                +params_sent_thistime+data_alignment_offset,
724                                pd,data_sent_thistime);
725                 }
726
727                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
728                         params_sent_thistime, data_sent_thistime, useable_space));
729                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
730                         params_to_send, data_to_send, paramsize, datasize));
731
732                 if (overflow) {
733                         error_packet_set((char *)req->outbuf,
734                                          ERRDOS,ERRbufferoverflow,
735                                          STATUS_BUFFER_OVERFLOW,
736                                          __LINE__,__FILE__);
737                 }
738
739                 /* Send the packet */
740                 show_msg((char *)req->outbuf);
741                 if (!send_smb(smbd_server_fd(),(char *)req->outbuf))
742                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
743
744                 TALLOC_FREE(req->outbuf);
745
746                 pp += params_sent_thistime;
747                 pd += data_sent_thistime;
748
749                 params_to_send -= params_sent_thistime;
750                 data_to_send -= data_sent_thistime;
751
752                 /* Sanity check */
753                 if(params_to_send < 0 || data_to_send < 0) {
754                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
755                                 params_to_send, data_to_send));
756                         return;
757                 }
758         }
759
760         return;
761 }
762
763 /****************************************************************************
764  Reply to a TRANSACT2_OPEN.
765 ****************************************************************************/
766
767 static void call_trans2open(connection_struct *conn,
768                             struct smb_request *req,
769                             char **pparams, int total_params,
770                             char **ppdata, int total_data,
771                             unsigned int max_data_bytes)
772 {
773         char *params = *pparams;
774         char *pdata = *ppdata;
775         int deny_mode;
776         int32 open_attr;
777         bool oplock_request;
778 #if 0
779         bool return_additional_info;
780         int16 open_sattr;
781         time_t open_time;
782 #endif
783         int open_ofun;
784         uint32 open_size;
785         char *pname;
786         char *fname = NULL;
787         SMB_OFF_T size=0;
788         int fattr=0,mtime=0;
789         SMB_INO_T inode = 0;
790         SMB_STRUCT_STAT sbuf;
791         int smb_action = 0;
792         files_struct *fsp;
793         struct ea_list *ea_list = NULL;
794         uint16 flags = 0;
795         NTSTATUS status;
796         uint32 access_mask;
797         uint32 share_mode;
798         uint32 create_disposition;
799         uint32 create_options = 0;
800         TALLOC_CTX *ctx = talloc_tos();
801
802         /*
803          * Ensure we have enough parameters to perform the operation.
804          */
805
806         if (total_params < 29) {
807                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
808                 return;
809         }
810
811         flags = SVAL(params, 0);
812         deny_mode = SVAL(params, 2);
813         open_attr = SVAL(params,6);
814         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
815         if (oplock_request) {
816                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
817         }
818
819 #if 0
820         return_additional_info = BITSETW(params,0);
821         open_sattr = SVAL(params, 4);
822         open_time = make_unix_date3(params+8);
823 #endif
824         open_ofun = SVAL(params,12);
825         open_size = IVAL(params,14);
826         pname = &params[28];
827
828         if (IS_IPC(conn)) {
829                 reply_doserror(req, ERRSRV, ERRaccess);
830                 return;
831         }
832
833         srvstr_get_path(ctx, params, req->flags2, &fname, pname,
834                         total_params - 28, STR_TERMINATE,
835                         &status);
836         if (!NT_STATUS_IS_OK(status)) {
837                 reply_nterror(req, status);
838                 return;
839         }
840
841         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
842                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
843                 (unsigned int)open_ofun, open_size));
844
845         /* XXXX we need to handle passed times, sattr and flags */
846
847         status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
848         if (!NT_STATUS_IS_OK(status)) {
849                 reply_nterror(req, status);
850                 return;
851         }
852
853         status = check_name(conn, fname);
854         if (!NT_STATUS_IS_OK(status)) {
855                 reply_nterror(req, status);
856                 return;
857         }
858
859         if (open_ofun == 0) {
860                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
861                 return;
862         }
863
864         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
865                                 &access_mask,
866                                 &share_mode,
867                                 &create_disposition,
868                                 &create_options)) {
869                 reply_doserror(req, ERRDOS, ERRbadaccess);
870                 return;
871         }
872
873         /* Any data in this call is an EA list. */
874         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
875                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
876                 return;
877         }
878
879         if (total_data != 4) {
880                 if (total_data < 10) {
881                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
882                         return;
883                 }
884
885                 if (IVAL(pdata,0) > total_data) {
886                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
887                                 IVAL(pdata,0), (unsigned int)total_data));
888                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
889                         return;
890                 }
891
892                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
893                                        total_data - 4);
894                 if (!ea_list) {
895                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
896                         return;
897                 }
898         } else if (IVAL(pdata,0) != 4) {
899                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
900                 return;
901         }
902
903         status = open_file_ntcreate(conn, req, fname, &sbuf,
904                 access_mask,
905                 share_mode,
906                 create_disposition,
907                 create_options,
908                 open_attr,
909                 oplock_request,
910                 &smb_action, &fsp);
911
912         if (!NT_STATUS_IS_OK(status)) {
913                 if (open_was_deferred(req->mid)) {
914                         /* We have re-scheduled this call. */
915                         return;
916                 }
917                 reply_openerror(req, status);
918                 return;
919         }
920
921         size = get_file_size(sbuf);
922         fattr = dos_mode(conn,fname,&sbuf);
923         mtime = sbuf.st_mtime;
924         inode = sbuf.st_ino;
925         if (fattr & aDIR) {
926                 close_file(fsp,ERROR_CLOSE);
927                 reply_doserror(req, ERRDOS,ERRnoaccess);
928                 return;
929         }
930
931         /* Save the requested allocation size. */
932         /* Allocate space for the file if a size hint is supplied */
933         if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
934                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
935                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
936                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
937                         if (fsp->is_directory) {
938                                 close_file(fsp,ERROR_CLOSE);
939                                 /* Can't set allocation size on a directory. */
940                                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
941                                 return;
942                         }
943                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
944                                 close_file(fsp,ERROR_CLOSE);
945                                 reply_nterror(req, NT_STATUS_DISK_FULL);
946                                 return;
947                         }
948
949                         /* Adjust size here to return the right size in the reply.
950                            Windows does it this way. */
951                         size = fsp->initial_allocation_size;
952                 } else {
953                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
954                 }
955         }
956
957         if (ea_list && smb_action == FILE_WAS_CREATED) {
958                 status = set_ea(conn, fsp, fname, ea_list);
959                 if (!NT_STATUS_IS_OK(status)) {
960                         close_file(fsp,ERROR_CLOSE);
961                         reply_nterror(req, status);
962                         return;
963                 }
964         }
965
966         /* Realloc the size of parameters and data we will return */
967         *pparams = (char *)SMB_REALLOC(*pparams, 30);
968         if(*pparams == NULL ) {
969                 reply_nterror(req, NT_STATUS_NO_MEMORY);
970                 return;
971         }
972         params = *pparams;
973
974         SSVAL(params,0,fsp->fnum);
975         SSVAL(params,2,fattr);
976         srv_put_dos_date2(params,4, mtime);
977         SIVAL(params,8, (uint32)size);
978         SSVAL(params,12,deny_mode);
979         SSVAL(params,14,0); /* open_type - file or directory. */
980         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
981
982         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
983                 smb_action |= EXTENDED_OPLOCK_GRANTED;
984         }
985
986         SSVAL(params,18,smb_action);
987
988         /*
989          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
990          */
991         SIVAL(params,20,inode);
992         SSVAL(params,24,0); /* Padding. */
993         if (flags & 8) {
994                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
995                 SIVAL(params, 26, ea_size);
996         } else {
997                 SIVAL(params, 26, 0);
998         }
999
1000         /* Send the required number of replies */
1001         send_trans2_replies(req, params, 30, *ppdata, 0, max_data_bytes);
1002 }
1003
1004 /*********************************************************
1005  Routine to check if a given string matches exactly.
1006  as a special case a mask of "." does NOT match. That
1007  is required for correct wildcard semantics
1008  Case can be significant or not.
1009 **********************************************************/
1010
1011 static bool exact_match(connection_struct *conn,
1012                 const char *str,
1013                 const char *mask)
1014 {
1015         if (mask[0] == '.' && mask[1] == 0)
1016                 return False;
1017         if (conn->case_sensitive)
1018                 return strcmp(str,mask)==0;
1019         if (StrCaseCmp(str,mask) != 0) {
1020                 return False;
1021         }
1022         if (dptr_has_wild(conn->dirptr)) {
1023                 return False;
1024         }
1025         return True;
1026 }
1027
1028 /****************************************************************************
1029  Return the filetype for UNIX extensions.
1030 ****************************************************************************/
1031
1032 static uint32 unix_filetype(mode_t mode)
1033 {
1034         if(S_ISREG(mode))
1035                 return UNIX_TYPE_FILE;
1036         else if(S_ISDIR(mode))
1037                 return UNIX_TYPE_DIR;
1038 #ifdef S_ISLNK
1039         else if(S_ISLNK(mode))
1040                 return UNIX_TYPE_SYMLINK;
1041 #endif
1042 #ifdef S_ISCHR
1043         else if(S_ISCHR(mode))
1044                 return UNIX_TYPE_CHARDEV;
1045 #endif
1046 #ifdef S_ISBLK
1047         else if(S_ISBLK(mode))
1048                 return UNIX_TYPE_BLKDEV;
1049 #endif
1050 #ifdef S_ISFIFO
1051         else if(S_ISFIFO(mode))
1052                 return UNIX_TYPE_FIFO;
1053 #endif
1054 #ifdef S_ISSOCK
1055         else if(S_ISSOCK(mode))
1056                 return UNIX_TYPE_SOCKET;
1057 #endif
1058
1059         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1060         return UNIX_TYPE_UNKNOWN;
1061 }
1062
1063 /****************************************************************************
1064  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1065 ****************************************************************************/
1066
1067 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1068
1069 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1070                                 SMB_STRUCT_STAT *psbuf,
1071                                 uint32 perms,
1072                                 enum perm_type ptype,
1073                                 mode_t *ret_perms)
1074 {
1075         mode_t ret = 0;
1076
1077         if (perms == SMB_MODE_NO_CHANGE) {
1078                 if (!VALID_STAT(*psbuf)) {
1079                         return NT_STATUS_INVALID_PARAMETER;
1080                 } else {
1081                         *ret_perms = psbuf->st_mode;
1082                         return NT_STATUS_OK;
1083                 }
1084         }
1085
1086         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1087         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1088         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1089         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1090         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1091         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1092         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1093         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1094         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1095 #ifdef S_ISVTX
1096         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1097 #endif
1098 #ifdef S_ISGID
1099         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1100 #endif
1101 #ifdef S_ISUID
1102         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1103 #endif
1104
1105         switch (ptype) {
1106         case PERM_NEW_FILE:
1107                 /* Apply mode mask */
1108                 ret &= lp_create_mask(SNUM(conn));
1109                 /* Add in force bits */
1110                 ret |= lp_force_create_mode(SNUM(conn));
1111                 break;
1112         case PERM_NEW_DIR:
1113                 ret &= lp_dir_mask(SNUM(conn));
1114                 /* Add in force bits */
1115                 ret |= lp_force_dir_mode(SNUM(conn));
1116                 break;
1117         case PERM_EXISTING_FILE:
1118                 /* Apply mode mask */
1119                 ret &= lp_security_mask(SNUM(conn));
1120                 /* Add in force bits */
1121                 ret |= lp_force_security_mode(SNUM(conn));
1122                 break;
1123         case PERM_EXISTING_DIR:
1124                 /* Apply mode mask */
1125                 ret &= lp_dir_security_mask(SNUM(conn));
1126                 /* Add in force bits */
1127                 ret |= lp_force_dir_security_mode(SNUM(conn));
1128                 break;
1129         }
1130
1131         *ret_perms = ret;
1132         return NT_STATUS_OK;
1133 }
1134
1135 /****************************************************************************
1136  Get a level dependent lanman2 dir entry.
1137 ****************************************************************************/
1138
1139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1140                                 connection_struct *conn,
1141                                 uint16 flags2,
1142                                 const char *path_mask,
1143                                 uint32 dirtype,
1144                                 int info_level,
1145                                 int requires_resume_key,
1146                                 bool dont_descend,
1147                                 char **ppdata,
1148                                 char *base_data,
1149                                 char *end_data,
1150                                 int space_remaining,
1151                                 bool *out_of_space,
1152                                 bool *got_exact_match,
1153                                 int *last_entry_off,
1154                                 struct ea_list *name_list)
1155 {
1156         const char *dname;
1157         bool found = False;
1158         SMB_STRUCT_STAT sbuf;
1159         const char *mask = NULL;
1160         char *pathreal = NULL;
1161         const char *fname = NULL;
1162         char *p, *q, *pdata = *ppdata;
1163         uint32 reskey=0;
1164         long prev_dirpos=0;
1165         uint32 mode=0;
1166         SMB_OFF_T file_size = 0;
1167         SMB_BIG_UINT allocation_size = 0;
1168         uint32 len;
1169         struct timespec mdate_ts, adate_ts, create_date_ts;
1170         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1171         char *nameptr;
1172         char *last_entry_ptr;
1173         bool was_8_3;
1174         uint32 nt_extmode; /* Used for NT connections instead of mode */
1175         bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1176         bool check_mangled_names = lp_manglednames(conn->params);
1177         char mangled_name[13]; /* mangled 8.3 name. */
1178
1179         *out_of_space = False;
1180         *got_exact_match = False;
1181
1182         ZERO_STRUCT(mdate_ts);
1183         ZERO_STRUCT(adate_ts);
1184         ZERO_STRUCT(create_date_ts);
1185
1186         if (!conn->dirptr) {
1187                 return(False);
1188         }
1189
1190         p = strrchr_m(path_mask,'/');
1191         if(p != NULL) {
1192                 if(p[1] == '\0') {
1193                         mask = talloc_strdup(ctx,"*.*");
1194                 } else {
1195                         mask = p+1;
1196                 }
1197         } else {
1198                 mask = path_mask;
1199         }
1200
1201         while (!found) {
1202                 bool got_match;
1203                 bool ms_dfs_link = False;
1204
1205                 /* Needed if we run out of space */
1206                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1207                 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1208
1209                 /*
1210                  * Due to bugs in NT client redirectors we are not using
1211                  * resume keys any more - set them to zero.
1212                  * Check out the related comments in findfirst/findnext.
1213                  * JRA.
1214                  */
1215
1216                 reskey = 0;
1217
1218                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1219                         (long)conn->dirptr,curr_dirpos));
1220
1221                 if (!dname) {
1222                         return(False);
1223                 }
1224
1225                 /*
1226                  * fname may get mangled, dname is never mangled.
1227                  * Whenever we're accessing the filesystem we use
1228                  * pathreal which is composed from dname.
1229                  */
1230
1231                 pathreal = NULL;
1232                 fname = dname;
1233
1234                 /* Mangle fname if it's an illegal name. */
1235                 if (mangle_must_mangle(dname,conn->params)) {
1236                         if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1237                                 continue; /* Error - couldn't mangle. */
1238                         }
1239                         fname = mangled_name;
1240                 }
1241
1242                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1243                         got_match = mask_match(fname, mask, conn->case_sensitive);
1244                 }
1245
1246                 if(!got_match && check_mangled_names &&
1247                    !mangle_is_8_3(fname, False, conn->params)) {
1248                         /*
1249                          * It turns out that NT matches wildcards against
1250                          * both long *and* short names. This may explain some
1251                          * of the wildcard wierdness from old DOS clients
1252                          * that some people have been seeing.... JRA.
1253                          */
1254                         /* Force the mangling into 8.3. */
1255                         if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1256                                 continue; /* Error - couldn't mangle. */
1257                         }
1258
1259                         if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1260                                 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1261                         }
1262                 }
1263
1264                 if (got_match) {
1265                         bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1266
1267                         if (dont_descend && !isdots) {
1268                                 continue;
1269                         }
1270
1271                         if (needslash) {
1272                                 pathreal = NULL;
1273                                 pathreal = talloc_asprintf(ctx,
1274                                         "%s/%s",
1275                                         conn->dirpath,
1276                                         dname);
1277                         } else {
1278                                 pathreal = talloc_asprintf(ctx,
1279                                         "%s%s",
1280                                         conn->dirpath,
1281                                         dname);
1282                         }
1283
1284                         if (!pathreal) {
1285                                 return False;
1286                         }
1287
1288                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1289                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1290                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1291                                                 pathreal,strerror(errno)));
1292                                         TALLOC_FREE(pathreal);
1293                                         continue;
1294                                 }
1295                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1296                                 /* Needed to show the msdfs symlinks as
1297                                  * directories */
1298
1299                                 if(lp_host_msdfs() &&
1300                                    lp_msdfs_root(SNUM(conn)) &&
1301                                    ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {
1302                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1303                                                 "as a directory\n",
1304                                                 pathreal));
1305                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1306
1307                                 } else {
1308
1309                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1310                                                 pathreal,strerror(errno)));
1311                                         TALLOC_FREE(pathreal);
1312                                         continue;
1313                                 }
1314                         }
1315
1316                         if (ms_dfs_link) {
1317                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1318                         } else {
1319                                 mode = dos_mode(conn,pathreal,&sbuf);
1320                         }
1321
1322                         if (!dir_check_ftype(conn,mode,dirtype)) {
1323                                 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1324                                 TALLOC_FREE(pathreal);
1325                                 continue;
1326                         }
1327
1328                         if (!(mode & aDIR)) {
1329                                 file_size = get_file_size(sbuf);
1330                         }
1331                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1332
1333                         mdate_ts = get_mtimespec(&sbuf);
1334                         adate_ts = get_atimespec(&sbuf);
1335                         create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1336
1337                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1338                                 dos_filetime_timespec(&create_date_ts);
1339                                 dos_filetime_timespec(&mdate_ts);
1340                                 dos_filetime_timespec(&adate_ts);
1341                         }
1342
1343                         create_date = convert_timespec_to_time_t(create_date_ts);
1344                         mdate = convert_timespec_to_time_t(mdate_ts);
1345                         adate = convert_timespec_to_time_t(adate_ts);
1346
1347                         DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1348
1349                         found = True;
1350
1351                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1352                 }
1353         }
1354
1355         p = pdata;
1356         last_entry_ptr = p;
1357
1358         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1359
1360         switch (info_level) {
1361                 case SMB_FIND_INFO_STANDARD:
1362                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1363                         if(requires_resume_key) {
1364                                 SIVAL(p,0,reskey);
1365                                 p += 4;
1366                         }
1367                         srv_put_dos_date2(p,0,create_date);
1368                         srv_put_dos_date2(p,4,adate);
1369                         srv_put_dos_date2(p,8,mdate);
1370                         SIVAL(p,12,(uint32)file_size);
1371                         SIVAL(p,16,(uint32)allocation_size);
1372                         SSVAL(p,20,mode);
1373                         p += 23;
1374                         nameptr = p;
1375                         p += align_string(pdata, p, 0);
1376                         len = srvstr_push(base_data, flags2, p,
1377                                           fname, PTR_DIFF(end_data, p),
1378                                           STR_TERMINATE);
1379                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1380                                 if (len > 2) {
1381                                         SCVAL(nameptr, -1, len - 2);
1382                                 } else {
1383                                         SCVAL(nameptr, -1, 0);
1384                                 }
1385                         } else {
1386                                 if (len > 1) {
1387                                         SCVAL(nameptr, -1, len - 1);
1388                                 } else {
1389                                         SCVAL(nameptr, -1, 0);
1390                                 }
1391                         }
1392                         p += len;
1393                         break;
1394
1395                 case SMB_FIND_EA_SIZE:
1396                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1397                         if(requires_resume_key) {
1398                                 SIVAL(p,0,reskey);
1399                                 p += 4;
1400                         }
1401                         srv_put_dos_date2(p,0,create_date);
1402                         srv_put_dos_date2(p,4,adate);
1403                         srv_put_dos_date2(p,8,mdate);
1404                         SIVAL(p,12,(uint32)file_size);
1405                         SIVAL(p,16,(uint32)allocation_size);
1406                         SSVAL(p,20,mode);
1407                         {
1408                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1409                                 SIVAL(p,22,ea_size); /* Extended attributes */
1410                         }
1411                         p += 27;
1412                         nameptr = p - 1;
1413                         len = srvstr_push(base_data, flags2,
1414                                           p, fname, PTR_DIFF(end_data, p),
1415                                           STR_TERMINATE | STR_NOALIGN);
1416                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1417                                 if (len > 2) {
1418                                         len -= 2;
1419                                 } else {
1420                                         len = 0;
1421                                 }
1422                         } else {
1423                                 if (len > 1) {
1424                                         len -= 1;
1425                                 } else {
1426                                         len = 0;
1427                                 }
1428                         }
1429                         SCVAL(nameptr,0,len);
1430                         p += len;
1431                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1432                         break;
1433
1434                 case SMB_FIND_EA_LIST:
1435                 {
1436                         struct ea_list *file_list = NULL;
1437                         size_t ea_len = 0;
1438
1439                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1440                         if (!name_list) {
1441                                 return False;
1442                         }
1443                         if(requires_resume_key) {
1444                                 SIVAL(p,0,reskey);
1445                                 p += 4;
1446                         }
1447                         srv_put_dos_date2(p,0,create_date);
1448                         srv_put_dos_date2(p,4,adate);
1449                         srv_put_dos_date2(p,8,mdate);
1450                         SIVAL(p,12,(uint32)file_size);
1451                         SIVAL(p,16,(uint32)allocation_size);
1452                         SSVAL(p,20,mode);
1453                         p += 22; /* p now points to the EA area. */
1454
1455                         file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1456                         name_list = ea_list_union(name_list, file_list, &ea_len);
1457
1458                         /* We need to determine if this entry will fit in the space available. */
1459                         /* Max string size is 255 bytes. */
1460                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1461                                 /* Move the dirptr back to prev_dirpos */
1462                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1463                                 *out_of_space = True;
1464                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1465                                 return False; /* Not finished - just out of space */
1466                         }
1467
1468                         /* Push the ea_data followed by the name. */
1469                         p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1470                         nameptr = p;
1471                         len = srvstr_push(base_data, flags2,
1472                                           p + 1, fname, PTR_DIFF(end_data, p+1),
1473                                           STR_TERMINATE | STR_NOALIGN);
1474                         if (flags2 & FLAGS2_UNICODE_STRINGS) {
1475                                 if (len > 2) {
1476                                         len -= 2;
1477                                 } else {
1478                                         len = 0;
1479                                 }
1480                         } else {
1481                                 if (len > 1) {
1482                                         len -= 1;
1483                                 } else {
1484                                         len = 0;
1485                                 }
1486                         }
1487                         SCVAL(nameptr,0,len);
1488                         p += len + 1;
1489                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1490                         break;
1491                 }
1492
1493                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1494                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1495                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1496                         p += 4;
1497                         SIVAL(p,0,reskey); p += 4;
1498                         put_long_date_timespec(p,create_date_ts); p += 8;
1499                         put_long_date_timespec(p,adate_ts); p += 8;
1500                         put_long_date_timespec(p,mdate_ts); p += 8;
1501                         put_long_date_timespec(p,mdate_ts); p += 8;
1502                         SOFF_T(p,0,file_size); p += 8;
1503                         SOFF_T(p,0,allocation_size); p += 8;
1504                         SIVAL(p,0,nt_extmode); p += 4;
1505                         q = p; p += 4; /* q is placeholder for name length. */
1506                         {
1507                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1508                                 SIVAL(p,0,ea_size); /* Extended attributes */
1509                                 p += 4;
1510                         }
1511                         /* Clear the short name buffer. This is
1512                          * IMPORTANT as not doing so will trigger
1513                          * a Win2k client bug. JRA.
1514                          */
1515                         if (!was_8_3 && check_mangled_names) {
1516                                 if (!name_to_8_3(fname,mangled_name,True,
1517                                                    conn->params)) {
1518                                         /* Error - mangle failed ! */
1519                                         memset(mangled_name,'\0',12);
1520                                 }
1521                                 mangled_name[12] = 0;
1522                                 len = srvstr_push(base_data, flags2,
1523                                                   p+2, mangled_name, 24,
1524                                                   STR_UPPER|STR_UNICODE);
1525                                 if (len < 24) {
1526                                         memset(p + 2 + len,'\0',24 - len);
1527                                 }
1528                                 SSVAL(p, 0, len);
1529                         } else {
1530                                 memset(p,'\0',26);
1531                         }
1532                         p += 2 + 24;
1533                         len = srvstr_push(base_data, flags2, p,
1534                                           fname, PTR_DIFF(end_data, p),
1535                                           STR_TERMINATE_ASCII);
1536                         SIVAL(q,0,len);
1537                         p += len;
1538                         SIVAL(p,0,0); /* Ensure any padding is null. */
1539                         len = PTR_DIFF(p, pdata);
1540                         len = (len + 3) & ~3;
1541                         SIVAL(pdata,0,len);
1542                         p = pdata + len;
1543                         break;
1544
1545                 case SMB_FIND_FILE_DIRECTORY_INFO:
1546                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1547                         p += 4;
1548                         SIVAL(p,0,reskey); p += 4;
1549                         put_long_date_timespec(p,create_date_ts); p += 8;
1550                         put_long_date_timespec(p,adate_ts); p += 8;
1551                         put_long_date_timespec(p,mdate_ts); p += 8;
1552                         put_long_date_timespec(p,mdate_ts); p += 8;
1553                         SOFF_T(p,0,file_size); p += 8;
1554                         SOFF_T(p,0,allocation_size); p += 8;
1555                         SIVAL(p,0,nt_extmode); p += 4;
1556                         len = srvstr_push(base_data, flags2,
1557                                           p + 4, fname, PTR_DIFF(end_data, p+4),
1558                                           STR_TERMINATE_ASCII);
1559                         SIVAL(p,0,len);
1560                         p += 4 + len;
1561                         SIVAL(p,0,0); /* Ensure any padding is null. */
1562                         len = PTR_DIFF(p, pdata);
1563                         len = (len + 3) & ~3;
1564                         SIVAL(pdata,0,len);
1565                         p = pdata + len;
1566                         break;
1567
1568                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1569                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1570                         p += 4;
1571                         SIVAL(p,0,reskey); p += 4;
1572                         put_long_date_timespec(p,create_date_ts); p += 8;
1573                         put_long_date_timespec(p,adate_ts); p += 8;
1574                         put_long_date_timespec(p,mdate_ts); p += 8;
1575                         put_long_date_timespec(p,mdate_ts); p += 8;
1576                         SOFF_T(p,0,file_size); p += 8;
1577                         SOFF_T(p,0,allocation_size); p += 8;
1578                         SIVAL(p,0,nt_extmode); p += 4;
1579                         q = p; p += 4; /* q is placeholder for name length. */
1580                         {
1581                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1582                                 SIVAL(p,0,ea_size); /* Extended attributes */
1583                                 p +=4;
1584                         }
1585                         len = srvstr_push(base_data, flags2, p,
1586                                           fname, PTR_DIFF(end_data, p),
1587                                           STR_TERMINATE_ASCII);
1588                         SIVAL(q, 0, len);
1589                         p += len;
1590
1591                         SIVAL(p,0,0); /* Ensure any padding is null. */
1592                         len = PTR_DIFF(p, pdata);
1593                         len = (len + 3) & ~3;
1594                         SIVAL(pdata,0,len);
1595                         p = pdata + len;
1596                         break;
1597
1598                 case SMB_FIND_FILE_NAMES_INFO:
1599                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1600                         p += 4;
1601                         SIVAL(p,0,reskey); p += 4;
1602                         p += 4;
1603                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1604                            acl on a dir (tridge) */
1605                         len = srvstr_push(base_data, flags2, p,
1606                                           fname, PTR_DIFF(end_data, p),
1607                                           STR_TERMINATE_ASCII);
1608                         SIVAL(p, -4, len);
1609                         p += len;
1610                         SIVAL(p,0,0); /* Ensure any padding is null. */
1611                         len = PTR_DIFF(p, pdata);
1612                         len = (len + 3) & ~3;
1613                         SIVAL(pdata,0,len);
1614                         p = pdata + len;
1615                         break;
1616
1617                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1618                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1619                         p += 4;
1620                         SIVAL(p,0,reskey); p += 4;
1621                         put_long_date_timespec(p,create_date_ts); p += 8;
1622                         put_long_date_timespec(p,adate_ts); p += 8;
1623                         put_long_date_timespec(p,mdate_ts); p += 8;
1624                         put_long_date_timespec(p,mdate_ts); p += 8;
1625                         SOFF_T(p,0,file_size); p += 8;
1626                         SOFF_T(p,0,allocation_size); p += 8;
1627                         SIVAL(p,0,nt_extmode); p += 4;
1628                         q = p; p += 4; /* q is placeholder for name length. */
1629                         {
1630                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1631                                 SIVAL(p,0,ea_size); /* Extended attributes */
1632                                 p +=4;
1633                         }
1634                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1635                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1636                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1637                         len = srvstr_push(base_data, flags2, p,
1638                                           fname, PTR_DIFF(end_data, p),
1639                                           STR_TERMINATE_ASCII);
1640                         SIVAL(q, 0, len);
1641                         p += len; 
1642                         SIVAL(p,0,0); /* Ensure any padding is null. */
1643                         len = PTR_DIFF(p, pdata);
1644                         len = (len + 3) & ~3;
1645                         SIVAL(pdata,0,len);
1646                         p = pdata + len;
1647                         break;
1648
1649                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1650                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1651                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1652                         p += 4;
1653                         SIVAL(p,0,reskey); p += 4;
1654                         put_long_date_timespec(p,create_date_ts); p += 8;
1655                         put_long_date_timespec(p,adate_ts); p += 8;
1656                         put_long_date_timespec(p,mdate_ts); p += 8;
1657                         put_long_date_timespec(p,mdate_ts); p += 8;
1658                         SOFF_T(p,0,file_size); p += 8;
1659                         SOFF_T(p,0,allocation_size); p += 8;
1660                         SIVAL(p,0,nt_extmode); p += 4;
1661                         q = p; p += 4; /* q is placeholder for name length */
1662                         {
1663                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1664                                 SIVAL(p,0,ea_size); /* Extended attributes */
1665                                 p +=4;
1666                         }
1667                         /* Clear the short name buffer. This is
1668                          * IMPORTANT as not doing so will trigger
1669                          * a Win2k client bug. JRA.
1670                          */
1671                         if (!was_8_3 && check_mangled_names) {
1672                                 if (!name_to_8_3(fname,mangled_name,True,
1673                                                 conn->params)) {
1674                                         /* Error - mangle failed ! */
1675                                         memset(mangled_name,'\0',12);
1676                                 }
1677                                 mangled_name[12] = 0;
1678                                 len = srvstr_push(base_data, flags2,
1679                                                   p+2, mangled_name, 24,
1680                                                   STR_UPPER|STR_UNICODE);
1681                                 SSVAL(p, 0, len);
1682                                 if (len < 24) {
1683                                         memset(p + 2 + len,'\0',24 - len);
1684                                 }
1685                                 SSVAL(p, 0, len);
1686                         } else {
1687                                 memset(p,'\0',26);
1688                         }
1689                         p += 26;
1690                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1691                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1692                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1693                         len = srvstr_push(base_data, flags2, p,
1694                                           fname, PTR_DIFF(end_data, p),
1695                                           STR_TERMINATE_ASCII);
1696                         SIVAL(q,0,len);
1697                         p += len;
1698                         SIVAL(p,0,0); /* Ensure any padding is null. */
1699                         len = PTR_DIFF(p, pdata);
1700                         len = (len + 3) & ~3;
1701                         SIVAL(pdata,0,len);
1702                         p = pdata + len;
1703                         break;
1704
1705                 /* CIFS UNIX Extension. */
1706
1707                 case SMB_FIND_FILE_UNIX:
1708                 case SMB_FIND_FILE_UNIX_INFO2:
1709                         p+= 4;
1710                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1711
1712                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1713
1714                         if (info_level == SMB_FIND_FILE_UNIX) {
1715                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1716                                 p = store_file_unix_basic(conn, p,
1717                                                         NULL, &sbuf);
1718                                 len = srvstr_push(base_data, flags2, p,
1719                                                   fname, PTR_DIFF(end_data, p),
1720                                                   STR_TERMINATE);
1721                         } else {
1722                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1723                                 p = store_file_unix_basic_info2(conn, p,
1724                                                         NULL, &sbuf);
1725                                 nameptr = p;
1726                                 p += 4;
1727                                 len = srvstr_push(base_data, flags2, p, fname,
1728                                                   PTR_DIFF(end_data, p), 0);
1729                                 SIVAL(nameptr, 0, len);
1730                         }
1731
1732                         p += len;
1733                         SIVAL(p,0,0); /* Ensure any padding is null. */
1734
1735                         len = PTR_DIFF(p, pdata);
1736                         len = (len + 3) & ~3;
1737                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1738                         p = pdata + len;
1739                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1740
1741                         break;
1742
1743                 default:
1744                         return(False);
1745         }
1746
1747
1748         if (PTR_DIFF(p,pdata) > space_remaining) {
1749                 /* Move the dirptr back to prev_dirpos */
1750                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1751                 *out_of_space = True;
1752                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1753                 return False; /* Not finished - just out of space */
1754         }
1755
1756         /* Setup the last entry pointer, as an offset from base_data */
1757         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1758         /* Advance the data pointer to the next slot */
1759         *ppdata = p;
1760
1761         return(found);
1762 }
1763
1764 /****************************************************************************
1765  Reply to a TRANS2_FINDFIRST.
1766 ****************************************************************************/
1767
1768 static void call_trans2findfirst(connection_struct *conn,
1769                                  struct smb_request *req,
1770                                  char **pparams, int total_params,
1771                                  char **ppdata, int total_data,
1772                                  unsigned int max_data_bytes)
1773 {
1774         /* We must be careful here that we don't return more than the
1775                 allowed number of data bytes. If this means returning fewer than
1776                 maxentries then so be it. We assume that the redirector has
1777                 enough room for the fixed number of parameter bytes it has
1778                 requested. */
1779         char *params = *pparams;
1780         char *pdata = *ppdata;
1781         char *data_end;
1782         uint32 dirtype;
1783         int maxentries;
1784         uint16 findfirst_flags;
1785         bool close_after_first;
1786         bool close_if_end;
1787         bool requires_resume_key;
1788         int info_level;
1789         char *directory = NULL;
1790         const char *mask = NULL;
1791         char *p;
1792         int last_entry_off=0;
1793         int dptr_num = -1;
1794         int numentries = 0;
1795         int i;
1796         bool finished = False;
1797         bool dont_descend = False;
1798         bool out_of_space = False;
1799         int space_remaining;
1800         bool mask_contains_wcard = False;
1801         SMB_STRUCT_STAT sbuf;
1802         struct ea_list *ea_list = NULL;
1803         NTSTATUS ntstatus = NT_STATUS_OK;
1804         TALLOC_CTX *ctx = talloc_tos();
1805
1806         if (total_params < 13) {
1807                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1808                 return;
1809         }
1810
1811         dirtype = SVAL(params,0);
1812         maxentries = SVAL(params,2);
1813         findfirst_flags = SVAL(params,4);
1814         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1815         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1816         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1817         info_level = SVAL(params,6);
1818
1819         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1820 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1821                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1822                 info_level, max_data_bytes));
1823
1824         if (!maxentries) {
1825                 /* W2K3 seems to treat zero as 1. */
1826                 maxentries = 1;
1827         }
1828  
1829         switch (info_level) {
1830                 case SMB_FIND_INFO_STANDARD:
1831                 case SMB_FIND_EA_SIZE:
1832                 case SMB_FIND_EA_LIST:
1833                 case SMB_FIND_FILE_DIRECTORY_INFO:
1834                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1835                 case SMB_FIND_FILE_NAMES_INFO:
1836                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1837                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1838                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1839                         break;
1840                 case SMB_FIND_FILE_UNIX:
1841                 case SMB_FIND_FILE_UNIX_INFO2:
1842                         if (!lp_unix_extensions()) {
1843                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1844                                 return;
1845                         }
1846                         break;
1847                 default:
1848                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1849                         return;
1850         }
1851
1852         srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1853                               params+12, total_params - 12,
1854                               STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1855         if (!NT_STATUS_IS_OK(ntstatus)) {
1856                 reply_nterror(req, ntstatus);
1857                 return;
1858         }
1859
1860         ntstatus = resolve_dfspath_wcard(ctx, conn,
1861                         req->flags2 & FLAGS2_DFS_PATHNAMES,
1862                         directory,
1863                         &directory,
1864                         &mask_contains_wcard);
1865         if (!NT_STATUS_IS_OK(ntstatus)) {
1866                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1867                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1868                                         ERRSRV, ERRbadpath);
1869                         return;
1870                 }
1871                 reply_nterror(req, ntstatus);
1872                 return;
1873         }
1874
1875         ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1876         if (!NT_STATUS_IS_OK(ntstatus)) {
1877                 reply_nterror(req, ntstatus);
1878                 return;
1879         }
1880
1881         ntstatus = check_name(conn, directory);
1882         if (!NT_STATUS_IS_OK(ntstatus)) {
1883                 reply_nterror(req, ntstatus);
1884                 return;
1885         }
1886
1887         p = strrchr_m(directory,'/');
1888         if(p == NULL) {
1889                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1890                 if((directory[0] == '.') && (directory[1] == '\0')) {
1891                         mask = "*";
1892                         mask_contains_wcard = True;
1893                 } else {
1894                         mask = directory;
1895                 }
1896                 directory = talloc_strdup(talloc_tos(), "./");
1897                 if (!directory) {
1898                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1899                         return;
1900                 }
1901         } else {
1902                 mask = p+1;
1903                 *p = 0;
1904         }
1905
1906         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1907
1908         if (info_level == SMB_FIND_EA_LIST) {
1909                 uint32 ea_size;
1910
1911                 if (total_data < 4) {
1912                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913                         return;
1914                 }
1915
1916                 ea_size = IVAL(pdata,0);
1917                 if (ea_size != total_data) {
1918                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1919 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1920                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1921                         return;
1922                 }
1923
1924                 if (!lp_ea_support(SNUM(conn))) {
1925                         reply_doserror(req, ERRDOS, ERReasnotsupported);
1926                         return;
1927                 }
1928
1929                 /* Pull out the list of names. */
1930                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
1931                 if (!ea_list) {
1932                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1933                         return;
1934                 }
1935         }
1936
1937         *ppdata = (char *)SMB_REALLOC(
1938                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1939         if(*ppdata == NULL ) {
1940                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1941                 return;
1942         }
1943         pdata = *ppdata;
1944         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
1945
1946         /* Realloc the params space */
1947         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1948         if (*pparams == NULL) {
1949                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1950                 return;
1951         }
1952         params = *pparams;
1953
1954         /* Save the wildcard match and attribs we are using on this directory - 
1955                 needed as lanman2 assumes these are being saved between calls */
1956
1957         ntstatus = dptr_create(conn,
1958                                 directory,
1959                                 False,
1960                                 True,
1961                                 req->smbpid,
1962                                 mask,
1963                                 mask_contains_wcard,
1964                                 dirtype,
1965                                 &conn->dirptr);
1966
1967         if (!NT_STATUS_IS_OK(ntstatus)) {
1968                 reply_nterror(req, ntstatus);
1969                 return;
1970         }
1971
1972         dptr_num = dptr_dnum(conn->dirptr);
1973         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1974
1975         /* We don't need to check for VOL here as this is returned by
1976                 a different TRANS2 call. */
1977
1978         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1979         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1980                 dont_descend = True;
1981
1982         p = pdata;
1983         space_remaining = max_data_bytes;
1984         out_of_space = False;
1985
1986         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1987                 bool got_exact_match = False;
1988
1989                 /* this is a heuristic to avoid seeking the dirptr except when 
1990                         absolutely necessary. It allows for a filename of about 40 chars */
1991                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1992                         out_of_space = True;
1993                         finished = False;
1994                 } else {
1995                         TALLOC_CTX *sub_ctx = talloc_stackframe();
1996
1997                         finished = !get_lanman2_dir_entry(sub_ctx,
1998                                         conn,
1999                                         req->flags2,
2000                                         mask,dirtype,info_level,
2001                                         requires_resume_key,dont_descend,
2002                                         &p,pdata,data_end,
2003                                         space_remaining, &out_of_space,
2004                                         &got_exact_match,
2005                                         &last_entry_off, ea_list);
2006
2007                         TALLOC_FREE(sub_ctx);
2008                 }
2009
2010                 if (finished && out_of_space)
2011                         finished = False;
2012
2013                 if (!finished && !out_of_space)
2014                         numentries++;
2015
2016                 /*
2017                  * As an optimisation if we know we aren't looking
2018                  * for a wildcard name (ie. the name matches the wildcard exactly)
2019                  * then we can finish on any (first) match.
2020                  * This speeds up large directory searches. JRA.
2021                  */
2022
2023                 if(got_exact_match)
2024                         finished = True;
2025
2026                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2027         }
2028
2029         /* Check if we can close the dirptr */
2030         if(close_after_first || (finished && close_if_end)) {
2031                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2032                 dptr_close(&dptr_num);
2033         }
2034
2035         /*
2036          * If there are no matching entries we must return ERRDOS/ERRbadfile -
2037          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2038          * the protocol level is less than NT1. Tested with smbclient. JRA.
2039          * This should fix the OS/2 client bug #2335.
2040          */
2041
2042         if(numentries == 0) {
2043                 dptr_close(&dptr_num);
2044                 if (Protocol < PROTOCOL_NT1) {
2045                         reply_doserror(req, ERRDOS, ERRnofiles);
2046                         return;
2047                 } else {
2048                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2049                                         ERRDOS, ERRbadfile);
2050                         return;
2051                 }
2052         }
2053
2054         /* At this point pdata points to numentries directory entries. */
2055
2056         /* Set up the return parameter block */
2057         SSVAL(params,0,dptr_num);
2058         SSVAL(params,2,numentries);
2059         SSVAL(params,4,finished);
2060         SSVAL(params,6,0); /* Never an EA error */
2061         SSVAL(params,8,last_entry_off);
2062
2063         send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
2064                             max_data_bytes);
2065
2066         if ((! *directory) && dptr_path(dptr_num)) {
2067                 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2068                 if (!directory) {
2069                         reply_nterror(req, NT_STATUS_NO_MEMORY);
2070                 }
2071         }
2072
2073         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2074                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2075                 mask, directory, dirtype, numentries ) );
2076
2077         /*
2078          * Force a name mangle here to ensure that the
2079          * mask as an 8.3 name is top of the mangled cache.
2080          * The reasons for this are subtle. Don't remove
2081          * this code unless you know what you are doing
2082          * (see PR#13758). JRA.
2083          */
2084
2085         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2086                 char mangled_name[13];
2087                 name_to_8_3(mask, mangled_name, True, conn->params);
2088         }
2089
2090         return;
2091 }
2092
2093 /****************************************************************************
2094  Reply to a TRANS2_FINDNEXT.
2095 ****************************************************************************/
2096
2097 static void call_trans2findnext(connection_struct *conn,
2098                                 struct smb_request *req,
2099                                 char **pparams, int total_params,
2100                                 char **ppdata, int total_data,
2101                                 unsigned int max_data_bytes)
2102 {
2103         /* We must be careful here that we don't return more than the
2104                 allowed number of data bytes. If this means returning fewer than
2105                 maxentries then so be it. We assume that the redirector has
2106                 enough room for the fixed number of parameter bytes it has
2107                 requested. */
2108         char *params = *pparams;
2109         char *pdata = *ppdata;
2110         char *data_end;
2111         int dptr_num;
2112         int maxentries;
2113         uint16 info_level;
2114         uint32 resume_key;
2115         uint16 findnext_flags;
2116         bool close_after_request;
2117         bool close_if_end;
2118         bool requires_resume_key;
2119         bool continue_bit;
2120         bool mask_contains_wcard = False;
2121         char *resume_name = NULL;
2122         const char *mask = NULL;
2123         const char *directory = NULL;
2124         char *p = NULL;
2125         uint16 dirtype;
2126         int numentries = 0;
2127         int i, last_entry_off=0;
2128         bool finished = False;
2129         bool dont_descend = False;
2130         bool out_of_space = False;
2131         int space_remaining;
2132         struct ea_list *ea_list = NULL;
2133         NTSTATUS ntstatus = NT_STATUS_OK;
2134         TALLOC_CTX *ctx = talloc_tos();
2135
2136         if (total_params < 13) {
2137                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2138                 return;
2139         }
2140
2141         dptr_num = SVAL(params,0);
2142         maxentries = SVAL(params,2);
2143         info_level = SVAL(params,4);
2144         resume_key = IVAL(params,6);
2145         findnext_flags = SVAL(params,10);
2146         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2147         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2148         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2149         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2150
2151         srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2152                               params+12,
2153                               total_params - 12, STR_TERMINATE, &ntstatus,
2154                               &mask_contains_wcard);
2155         if (!NT_STATUS_IS_OK(ntstatus)) {
2156                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2157                    complain (it thinks we're asking for the directory above the shared
2158                    path or an invalid name). Catch this as the resume name is only compared, never used in
2159                    a file access. JRA. */
2160                 srvstr_pull_talloc(ctx, params, req->flags2,
2161                                 &resume_name, params+12,
2162                                 total_params - 12,
2163                                 STR_TERMINATE);
2164
2165                 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2166                         reply_nterror(req, ntstatus);
2167                         return;
2168                 }
2169         }
2170
2171         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2172 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2173 resume_key = %d resume name = %s continue=%d level = %d\n",
2174                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2175                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2176
2177         if (!maxentries) {
2178                 /* W2K3 seems to treat zero as 1. */
2179                 maxentries = 1;
2180         }
2181
2182         switch (info_level) {
2183                 case SMB_FIND_INFO_STANDARD:
2184                 case SMB_FIND_EA_SIZE:
2185                 case SMB_FIND_EA_LIST:
2186                 case SMB_FIND_FILE_DIRECTORY_INFO:
2187                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2188                 case SMB_FIND_FILE_NAMES_INFO:
2189                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2190                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2191                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2192                         break;
2193                 case SMB_FIND_FILE_UNIX:
2194                 case SMB_FIND_FILE_UNIX_INFO2:
2195                         if (!lp_unix_extensions()) {
2196                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2197                                 return;
2198                         }
2199                         break;
2200                 default:
2201                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2202                         return;
2203         }
2204
2205         if (info_level == SMB_FIND_EA_LIST) {
2206                 uint32 ea_size;
2207
2208                 if (total_data < 4) {
2209                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2210                         return;
2211                 }
2212
2213                 ea_size = IVAL(pdata,0);
2214                 if (ea_size != total_data) {
2215                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2216 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2217                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2218                         return;
2219                 }
2220
2221                 if (!lp_ea_support(SNUM(conn))) {
2222                         reply_doserror(req, ERRDOS, ERReasnotsupported);
2223                         return;
2224                 }
2225
2226                 /* Pull out the list of names. */
2227                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2228                 if (!ea_list) {
2229                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2230                         return;
2231                 }
2232         }
2233
2234         *ppdata = (char *)SMB_REALLOC(
2235                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2236         if(*ppdata == NULL) {
2237                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2238                 return;
2239         }
2240
2241         pdata = *ppdata;
2242         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2243
2244         /* Realloc the params space */
2245         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2246         if(*pparams == NULL ) {
2247                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2248                 return;
2249         }
2250
2251         params = *pparams;
2252
2253         /* Check that the dptr is valid */
2254         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2255                 reply_doserror(req, ERRDOS, ERRnofiles);
2256                 return;
2257         }
2258
2259         string_set(&conn->dirpath,dptr_path(dptr_num));
2260
2261         /* Get the wildcard mask from the dptr */
2262         if((p = dptr_wcard(dptr_num))== NULL) {
2263                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2264                 reply_doserror(req, ERRDOS, ERRnofiles);
2265                 return;
2266         }
2267
2268         mask = p;
2269         directory = conn->dirpath;
2270
2271         /* Get the attr mask from the dptr */
2272         dirtype = dptr_attr(dptr_num);
2273
2274         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2275                 dptr_num, mask, dirtype,
2276                 (long)conn->dirptr,
2277                 dptr_TellDir(conn->dirptr)));
2278
2279         /* We don't need to check for VOL here as this is returned by
2280                 a different TRANS2 call. */
2281
2282         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2283         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2284                 dont_descend = True;
2285
2286         p = pdata;
2287         space_remaining = max_data_bytes;
2288         out_of_space = False;
2289
2290         /*
2291          * Seek to the correct position. We no longer use the resume key but
2292          * depend on the last file name instead.
2293          */
2294
2295         if(*resume_name && !continue_bit) {
2296                 SMB_STRUCT_STAT st;
2297
2298                 long current_pos = 0;
2299                 /*
2300                  * Remember, name_to_8_3 is called by
2301                  * get_lanman2_dir_entry(), so the resume name
2302                  * could be mangled. Ensure we check the unmangled name.
2303                  */
2304
2305                 if (mangle_is_mangled(resume_name, conn->params)) {
2306                         char *new_resume_name = NULL;
2307                         mangle_lookup_name_from_8_3(ctx,
2308                                                 resume_name,
2309                                                 &new_resume_name,
2310                                                 conn->params);
2311                         if (new_resume_name) {
2312                                 resume_name = new_resume_name;
2313                         }
2314                 }
2315
2316                 /*
2317                  * Fix for NT redirector problem triggered by resume key indexes
2318                  * changing between directory scans. We now return a resume key of 0
2319                  * and instead look for the filename to continue from (also given
2320                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2321                  * findfirst/findnext (as is usual) then the directory pointer
2322                  * should already be at the correct place.
2323                  */
2324
2325                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2326         } /* end if resume_name && !continue_bit */
2327
2328         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2329                 bool got_exact_match = False;
2330
2331                 /* this is a heuristic to avoid seeking the dirptr except when 
2332                         absolutely necessary. It allows for a filename of about 40 chars */
2333                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2334                         out_of_space = True;
2335                         finished = False;
2336                 } else {
2337                         TALLOC_CTX *sub_ctx = talloc_stackframe();
2338
2339                         finished = !get_lanman2_dir_entry(sub_ctx,
2340                                                 conn,
2341                                                 req->flags2,
2342                                                 mask,dirtype,info_level,
2343                                                 requires_resume_key,dont_descend,
2344                                                 &p,pdata,data_end,
2345                                                 space_remaining, &out_of_space,
2346                                                 &got_exact_match,
2347                                                 &last_entry_off, ea_list);
2348
2349                         TALLOC_FREE(sub_ctx);
2350                 }
2351
2352                 if (finished && out_of_space)
2353                         finished = False;
2354
2355                 if (!finished && !out_of_space)
2356                         numentries++;
2357
2358                 /*
2359                  * As an optimisation if we know we aren't looking
2360                  * for a wildcard name (ie. the name matches the wildcard exactly)
2361                  * then we can finish on any (first) match.
2362                  * This speeds up large directory searches. JRA.
2363                  */
2364
2365                 if(got_exact_match)
2366                         finished = True;
2367
2368                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2369         }
2370
2371         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2372                 smb_fn_name(CVAL(req->inbuf,smb_com)),
2373                 mask, directory, dirtype, numentries ) );
2374
2375         /* Check if we can close the dirptr */
2376         if(close_after_request || (finished && close_if_end)) {
2377                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2378                 dptr_close(&dptr_num); /* This frees up the saved mask */
2379         }
2380
2381         /* Set up the return parameter block */
2382         SSVAL(params,0,numentries);
2383         SSVAL(params,2,finished);
2384         SSVAL(params,4,0); /* Never an EA error */
2385         SSVAL(params,6,last_entry_off);
2386
2387         send_trans2_replies(req, params, 8, pdata, PTR_DIFF(p,pdata),
2388                             max_data_bytes);
2389
2390         return;
2391 }
2392
2393 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2394 {
2395         E_md4hash(lp_servicename(SNUM(conn)),objid);
2396         return objid;
2397 }
2398
2399 /****************************************************************************
2400  Reply to a TRANS2_QFSINFO (query filesystem info).
2401 ****************************************************************************/
2402
2403 static void call_trans2qfsinfo(connection_struct *conn,
2404                                struct smb_request *req,
2405                                char **pparams, int total_params,
2406                                char **ppdata, int total_data,
2407                                unsigned int max_data_bytes)
2408 {
2409         char *pdata, *end_data;
2410         char *params = *pparams;
2411         uint16 info_level;
2412         int data_len, len;
2413         SMB_STRUCT_STAT st;
2414         const char *vname = volume_label(SNUM(conn));
2415         int snum = SNUM(conn);
2416         char *fstype = lp_fstype(SNUM(conn));
2417         int quota_flag = 0;
2418
2419         if (total_params < 2) {
2420                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2421                 return;
2422         }
2423
2424         info_level = SVAL(params,0);
2425
2426         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2427
2428         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2429                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2430                 reply_doserror(req, ERRSRV, ERRinvdevice);
2431                 return;
2432         }
2433
2434         *ppdata = (char *)SMB_REALLOC(
2435                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2436         if (*ppdata == NULL ) {
2437                 reply_nterror(req, NT_STATUS_NO_MEMORY);
2438                 return;
2439         }
2440
2441         pdata = *ppdata;
2442         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2443         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2444
2445         switch (info_level) {
2446                 case SMB_INFO_ALLOCATION:
2447                 {
2448                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2449                         data_len = 18;
2450                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2451                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2452                                 return;
2453                         }
2454
2455                         block_size = lp_block_size(snum);
2456                         if (bsize < block_size) {
2457                                 SMB_BIG_UINT factor = block_size/bsize;
2458                                 bsize = block_size;
2459                                 dsize /= factor;
2460                                 dfree /= factor;
2461                         }
2462                         if (bsize > block_size) {
2463                                 SMB_BIG_UINT factor = bsize/block_size;
2464                                 bsize = block_size;
2465                                 dsize *= factor;
2466                                 dfree *= factor;
2467                         }
2468                         bytes_per_sector = 512;
2469                         sectors_per_unit = bsize/bytes_per_sector;
2470
2471                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2472 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2473                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2474
2475                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2476                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2477                         SIVAL(pdata,l1_cUnit,dsize);
2478                         SIVAL(pdata,l1_cUnitAvail,dfree);
2479                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2480                         break;
2481                 }
2482
2483                 case SMB_INFO_VOLUME:
2484                         /* Return volume name */
2485                         /* 
2486                          * Add volume serial number - hash of a combination of
2487                          * the called hostname and the service name.
2488                          */
2489                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2490                         /*
2491                          * Win2k3 and previous mess this up by sending a name length
2492                          * one byte short. I believe only older clients (OS/2 Win9x) use
2493                          * this call so try fixing this by adding a terminating null to
2494                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2495                          */
2496                         len = srvstr_push(
2497                                 pdata, req->flags2,
2498                                 pdata+l2_vol_szVolLabel, vname,
2499                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2500                                 STR_NOALIGN|STR_TERMINATE);
2501                         SCVAL(pdata,l2_vol_cch,len);
2502                         data_len = l2_vol_szVolLabel + len;
2503                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2504                                 (unsigned)st.st_ctime, len, vname));
2505                         break;
2506
2507                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2508                 case SMB_FS_ATTRIBUTE_INFORMATION:
2509
2510
2511 #if defined(HAVE_SYS_QUOTAS)
2512                         quota_flag = FILE_VOLUME_QUOTAS;
2513 #endif
2514
2515                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2516                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2517                                 FILE_SUPPORTS_OBJECT_IDS|
2518                                 FILE_UNICODE_ON_DISK|
2519                                 quota_flag); /* FS ATTRIBUTES */
2520
2521                         SIVAL(pdata,4,255); /* Max filename component length */
2522                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2523                                 and will think we can't do long filenames */
2524                         len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2525                                           PTR_DIFF(end_data, pdata+12),
2526                                           STR_UNICODE);
2527                         SIVAL(pdata,8,len);
2528                         data_len = 12 + len;
2529                         break;
2530
2531                 case SMB_QUERY_FS_LABEL_INFO:
2532                 case SMB_FS_LABEL_INFORMATION:
2533                         len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2534                                           PTR_DIFF(end_data, pdata+4), 0);
2535                         data_len = 4 + len;
2536                         SIVAL(pdata,0,len);
2537                         break;
2538
2539                 case SMB_QUERY_FS_VOLUME_INFO:      
2540                 case SMB_FS_VOLUME_INFORMATION:
2541
2542                         /* 
2543                          * Add volume serial number - hash of a combination of
2544                          * the called hostname and the service name.
2545                          */
2546                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2547                                 (str_checksum(get_local_machine_name())<<16));
2548
2549                         /* Max label len is 32 characters. */
2550                         len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2551                                           PTR_DIFF(end_data, pdata+18),
2552                                           STR_UNICODE);
2553                         SIVAL(pdata,12,len);
2554                         data_len = 18+len;
2555
2556                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2557                                 (int)strlen(vname),vname, lp_servicename(snum)));
2558                         break;
2559
2560                 case SMB_QUERY_FS_SIZE_INFO:
2561                 case SMB_FS_SIZE_INFORMATION:
2562                 {
2563                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2564                         data_len = 24;
2565                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2566                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2567                                 return;
2568                         }
2569                         block_size = lp_block_size(snum);
2570                         if (bsize < block_size) {
2571                                 SMB_BIG_UINT factor = block_size/bsize;
2572                                 bsize = block_size;
2573                                 dsize /= factor;
2574                                 dfree /= factor;
2575                         }
2576                         if (bsize > block_size) {
2577                                 SMB_BIG_UINT factor = bsize/block_size;
2578                                 bsize = block_size;
2579                                 dsize *= factor;
2580                                 dfree *= factor;
2581                         }
2582                         bytes_per_sector = 512;
2583                         sectors_per_unit = bsize/bytes_per_sector;
2584                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2585 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2586                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2587                         SBIG_UINT(pdata,0,dsize);
2588                         SBIG_UINT(pdata,8,dfree);
2589                         SIVAL(pdata,16,sectors_per_unit);
2590                         SIVAL(pdata,20,bytes_per_sector);
2591                         break;
2592                 }
2593
2594                 case SMB_FS_FULL_SIZE_INFORMATION:
2595                 {
2596                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2597                         data_len = 32;
2598                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2599                                 reply_unixerror(req, ERRHRD, ERRgeneral);
2600                                 return;
2601                         }
2602                         block_size = lp_block_size(snum);
2603                         if (bsize < block_size) {
2604                                 SMB_BIG_UINT factor = block_size/bsize;
2605                                 bsize = block_size;
2606                                 dsize /= factor;
2607                                 dfree /= factor;
2608                         }
2609                         if (bsize > block_size) {
2610                                 SMB_BIG_UINT factor = bsize/block_size;
2611                                 bsize = block_size;
2612                                 dsize *= factor;
2613                                 dfree *= factor;
2614                         }
2615                         bytes_per_sector = 512;
2616                         sectors_per_unit = bsize/bytes_per_sector;
2617                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2618 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2619                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2620                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2621                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2622                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2623                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2624                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2625                         break;
2626                 }
2627
2628                 case SMB_QUERY_FS_DEVICE_INFO:
2629                 case SMB_FS_DEVICE_INFORMATION:
2630                         data_len = 8;
2631                         SIVAL(pdata,0,0); /* dev type */
2632                         SIVAL(pdata,4,0); /* characteristics */
2633                         break;
2634
2635 #ifdef HAVE_SYS_QUOTAS
2636                 case SMB_FS_QUOTA_INFORMATION:
2637                 /* 
2638                  * what we have to send --metze:
2639                  *
2640                  * Unknown1:            24 NULL bytes
2641                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2642                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2643                  * Quota Flags:         2 byte :
2644                  * Unknown3:            6 NULL bytes
2645                  *
2646                  * 48 bytes total
2647                  * 
2648                  * details for Quota Flags:
2649                  * 
2650                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2651                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2652                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2653                  * 0x0001 Enable Quotas: enable quota for this fs
2654                  *
2655                  */
2656                 {
2657                         /* we need to fake up a fsp here,
2658                          * because its not send in this call
2659                          */
2660                         files_struct fsp;
2661                         SMB_NTQUOTA_STRUCT quotas;
2662                         
2663                         ZERO_STRUCT(fsp);
2664                         ZERO_STRUCT(quotas);
2665                         
2666                         fsp.conn = conn;
2667                         fsp.fnum = -1;
2668                         
2669                         /* access check */
2670                         if (current_user.ut.uid != 0) {
2671                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2672                                         lp_servicename(SNUM(conn)),conn->user));
2673                                 reply_doserror(req, ERRDOS, ERRnoaccess);
2674                                 return;
2675                         }
2676                         
2677                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2678                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2679                                 reply_doserror(req, ERRSRV, ERRerror);
2680                                 return;
2681                         }
2682
2683                         data_len = 48;
2684
2685                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2686                 
2687                         /* Unknown1 24 NULL bytes*/
2688                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2689                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2690                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2691                 
2692                         /* Default Soft Quota 8 bytes */
2693                         SBIG_UINT(pdata,24,quotas.softlim);
2694
2695                         /* Default Hard Quota 8 bytes */
2696                         SBIG_UINT(pdata,32,quotas.hardlim);
2697         
2698                         /* Quota flag 2 bytes */
2699                         SSVAL(pdata,40,quotas.qflags);
2700                 
2701                         /* Unknown3 6 NULL bytes */
2702                         SSVAL(pdata,42,0);
2703                         SIVAL(pdata,44,0);
2704                         
2705                         break;
2706                 }
2707 #endif /* HAVE_SYS_QUOTAS */
2708                 case SMB_FS_OBJECTID_INFORMATION:
2709                 {
2710                         unsigned char objid[16];
2711                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2712                         data_len = 64;
2713                         break;
2714                 }
2715
2716                 /*
2717                  * Query the version and capabilities of the CIFS UNIX extensions
2718                  * in use.
2719                  */
2720
2721                 case SMB_QUERY_CIFS_UNIX_INFO:
2722                 {
2723                         bool large_write = lp_min_receive_file_size() &&
2724                                                 !srv_is_signing_active();
2725
2726                         if (!lp_unix_extensions()) {
2727                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2728                                 return;
2729                         }
2730                         data_len = 12;
2731                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2732                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2733                         /* We have POSIX ACLs, pathname and locking capability. */
2734                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2735                                         CIFS_UNIX_POSIX_ACLS_CAP|
2736                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2737                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2738                                         CIFS_UNIX_EXTATTR_CAP|
2739                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2740                                         CIFS_UNIX_LARGE_READ_CAP|
2741                                         (large_write ?
2742                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2743                         break;
2744                 }
2745
2746                 case SMB_QUERY_POSIX_FS_INFO:
2747                 {
2748                         int rc;
2749                         vfs_statvfs_struct svfs;
2750
2751                         if (!lp_unix_extensions()) {
2752                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2753                                 return;
2754                         }
2755
2756                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2757
2758                         if (!rc) {
2759                                 data_len = 56;
2760                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2761                                 SIVAL(pdata,4,svfs.BlockSize);
2762                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2763                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2764                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2765                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2766                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2767                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2768                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2769 #ifdef EOPNOTSUPP
2770                         } else if (rc == EOPNOTSUPP) {
2771                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2772                                 return;
2773 #endif /* EOPNOTSUPP */
2774                         } else {
2775                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2776                                 reply_doserror(req, ERRSRV, ERRerror);
2777                                 return;
2778                         }
2779                         break;
2780                 }
2781
2782                 case SMB_QUERY_POSIX_WHOAMI:
2783                 {
2784                         uint32_t flags = 0;
2785                         uint32_t sid_bytes;
2786                         int i;
2787
2788                         if (!lp_unix_extensions()) {
2789                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2790                                 return;
2791                         }
2792
2793                         if (max_data_bytes < 40) {
2794                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2795                                 return;
2796                         }
2797
2798                         /* We ARE guest if global_sid_Builtin_Guests is
2799                          * in our list of SIDs.
2800                          */
2801                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2802                                     current_user.nt_user_token)) {
2803                                 flags |= SMB_WHOAMI_GUEST;
2804                         }
2805
2806                         /* We are NOT guest if global_sid_Authenticated_Users
2807                          * is in our list of SIDs.
2808                          */
2809                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2810                                     current_user.nt_user_token)) {
2811                                 flags &= ~SMB_WHOAMI_GUEST;
2812                         }
2813
2814                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2815                          * platform size. This matches
2816                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2817                          */
2818                         data_len = 4 /* flags */
2819                             + 4 /* flag mask */
2820                             + 8 /* uid */
2821                             + 8 /* gid */
2822                             + 4 /* ngroups */
2823                             + 4 /* num_sids */
2824                             + 4 /* SID bytes */
2825                             + 4 /* pad/reserved */
2826                             + (current_user.ut.ngroups * 8)
2827                                 /* groups list */
2828                             + (current_user.nt_user_token->num_sids *
2829                                     SID_MAX_SIZE)
2830                                 /* SID list */;
2831
2832                         SIVAL(pdata, 0, flags);
2833                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2834                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2835                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2836
2837
2838                         if (data_len >= max_data_bytes) {
2839                                 /* Potential overflow, skip the GIDs and SIDs. */
2840
2841                                 SIVAL(pdata, 24, 0); /* num_groups */
2842                                 SIVAL(pdata, 28, 0); /* num_sids */
2843                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2844                                 SIVAL(pdata, 36, 0); /* reserved */
2845
2846                                 data_len = 40;
2847                                 break;
2848                         }
2849
2850                         SIVAL(pdata, 24, current_user.ut.ngroups);
2851                         SIVAL(pdata, 28,
2852                                 current_user.nt_user_token->num_sids);
2853
2854                         /* We walk the SID list twice, but this call is fairly
2855                          * infrequent, and I don't expect that it's performance
2856                          * sensitive -- jpeach
2857                          */
2858                         for (i = 0, sid_bytes = 0;
2859                             i < current_user.nt_user_token->num_sids; ++i) {
2860                                 sid_bytes +=
2861                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2862                         }
2863
2864                         /* SID list byte count */
2865                         SIVAL(pdata, 32, sid_bytes);
2866
2867                         /* 4 bytes pad/reserved - must be zero */
2868                         SIVAL(pdata, 36, 0);
2869                         data_len = 40;
2870
2871                         /* GID list */
2872                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2873                                 SBIG_UINT(pdata, data_len,
2874                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2875                                 data_len += 8;
2876                         }
2877
2878                         /* SID list */
2879                         for (i = 0;
2880                             i < current_user.nt_user_token->num_sids; ++i) {
2881                                 int sid_len =
2882                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2883
2884                                 sid_linearize(pdata + data_len, sid_len,
2885                                     &current_user.nt_user_token->user_sids[i]);
2886                                 data_len += sid_len;
2887                         }
2888
2889                         break;
2890                 }
2891
2892                 case SMB_MAC_QUERY_FS_INFO:
2893                         /*
2894                          * Thursby MAC extension... ONLY on NTFS filesystems
2895                          * once we do streams then we don't need this
2896                          */
2897                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2898                                 data_len = 88;
2899                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2900                                 break;
2901                         }
2902                         /* drop through */
2903                 default:
2904                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2905                         return;
2906         }
2907
2908
2909         send_trans2_replies(req, params, 0, pdata, data_len,
2910                             max_data_bytes);
2911
2912         DEBUG( 4, ( "%s info_level = %d\n",
2913                     smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2914
2915         return;
2916 }
2917
2918 /****************************************************************************
2919  Reply to a TRANS2_SETFSINFO (set filesystem info).
2920 ****************************************************************************/
2921
2922 static void call_trans2setfsinfo(connection_struct *conn,
2923                                  struct smb_request *req,
2924                                  char **pparams, int total_params,
2925                                  char **ppdata, int total_data,
2926                                  unsigned int max_data_bytes)
2927 {
2928         char *pdata = *ppdata;
2929         char *params = *pparams;
2930         uint16 info_level;
2931
2932         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2933
2934         /*  */
2935         if (total_params < 4) {
2936                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2937                         total_params));
2938                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2939                 return;
2940         }
2941
2942         info_level = SVAL(params,2);
2943
2944         switch(info_level) {
2945                 case SMB_SET_CIFS_UNIX_INFO:
2946                         {
2947                                 uint16 client_unix_major;
2948                                 uint16 client_unix_minor;
2949                                 uint32 client_unix_cap_low;
2950                                 uint32 client_unix_cap_high;
2951
2952                                 if (!lp_unix_extensions()) {
2953                                         reply_nterror(req,
2954                                                       NT_STATUS_INVALID_LEVEL);
2955                                         return;
2956                                 }
2957
2958                                 /* There should be 12 bytes of capabilities set. */
2959                                 if (total_data < 8) {
2960                                         reply_nterror(
2961                                                 req,
2962                                                 NT_STATUS_INVALID_PARAMETER);
2963                                         return;
2964                                 }
2965                                 client_unix_major = SVAL(pdata,0);
2966                                 client_unix_minor = SVAL(pdata,2);
2967                                 client_unix_cap_low = IVAL(pdata,4);
2968                                 client_unix_cap_high = IVAL(pdata,8);
2969                                 /* Just print these values for now. */
2970                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2971 cap_low = 0x%x, cap_high = 0x%x\n",
2972                                         (unsigned int)client_unix_major,
2973                                         (unsigned int)client_unix_minor,
2974                                         (unsigned int)client_unix_cap_low,
2975                                         (unsigned int)client_unix_cap_high ));
2976
2977                                 /* Here is where we must switch to posix pathname processing... */
2978                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2979                                         lp_set_posix_pathnames();
2980                                         mangle_change_to_posix();
2981                                 }
2982
2983                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2984                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2985                                         /* Client that knows how to do posix locks,
2986                                          * but not posix open/mkdir operations. Set a
2987                                          * default type for read/write checks. */
2988
2989                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2990
2991                                 }
2992                                 break;
2993                         }
2994                 case SMB_FS_QUOTA_INFORMATION:
2995                         {
2996                                 files_struct *fsp = NULL;
2997                                 SMB_NTQUOTA_STRUCT quotas;
2998         
2999                                 ZERO_STRUCT(quotas);
3000
3001                                 /* access check */
3002                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3003                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3004                                                 lp_servicename(SNUM(conn)),conn->user));
3005                                         reply_doserror(req, ERRSRV, ERRaccess);
3006                                         return;
3007                                 }
3008
3009                                 /* note: normaly there're 48 bytes,
3010                                  * but we didn't use the last 6 bytes for now 
3011                                  * --metze 
3012                                  */
3013                                 fsp = file_fsp(SVAL(params,0));
3014                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3015                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3016                                         reply_nterror(
3017                                                 req, NT_STATUS_INVALID_HANDLE);
3018                                         return;
3019                                 }
3020
3021                                 if (total_data < 42) {
3022                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3023                                                 total_data));
3024                                         reply_nterror(
3025                                                 req,
3026                                                 NT_STATUS_INVALID_PARAMETER);
3027                                         return;
3028                                 }
3029                         
3030                                 /* unknown_1 24 NULL bytes in pdata*/
3031                 
3032                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3033                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3034 #ifdef LARGE_SMB_OFF_T
3035                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3036 #else /* LARGE_SMB_OFF_T */
3037                                 if ((IVAL(pdata,28) != 0)&&
3038                                         ((quotas.softlim != 0xFFFFFFFF)||
3039                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3040                                         /* more than 32 bits? */
3041                                         reply_nterror(
3042                                                 req,
3043                                                 NT_STATUS_INVALID_PARAMETER);
3044                                         return;
3045                                 }
3046 #endif /* LARGE_SMB_OFF_T */
3047                 
3048                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3049                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3050 #ifdef LARGE_SMB_OFF_T
3051                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3052 #else /* LARGE_SMB_OFF_T */
3053                                 if ((IVAL(pdata,36) != 0)&&
3054                                         ((quotas.hardlim != 0xFFFFFFFF)||
3055                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3056                                         /* more than 32 bits? */
3057                                         reply_nterror(
3058                                                 req,
3059                                                 NT_STATUS_INVALID_PARAMETER);
3060                                         return;
3061                                 }
3062 #endif /* LARGE_SMB_OFF_T */
3063                 
3064                                 /* quota_flags 2 bytes **/
3065                                 quotas.qflags = SVAL(pdata,40);
3066                 
3067                                 /* unknown_2 6 NULL bytes follow*/
3068                 
3069                                 /* now set the quotas */
3070                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3071                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3072                                         reply_doserror(req, ERRSRV, ERRerror);
3073                                         return;
3074                                 }
3075                         
3076                                 break;
3077                         }
3078                 default:
3079                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3080                                 info_level));
3081                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3082                         return;
3083                         break;
3084         }
3085
3086         /* 
3087          * sending this reply works fine, 
3088          * but I'm not sure it's the same 
3089          * like windows do...
3090          * --metze
3091          */
3092         reply_outbuf(req, 10, 0);
3093 }
3094
3095 #if defined(HAVE_POSIX_ACLS)
3096 /****************************************************************************
3097  Utility function to count the number of entries in a POSIX acl.
3098 ****************************************************************************/
3099
3100 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3101 {
3102         unsigned int ace_count = 0;
3103         int entry_id = SMB_ACL_FIRST_ENTRY;
3104         SMB_ACL_ENTRY_T entry;
3105
3106         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3107                 /* get_next... */
3108                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3109                         entry_id = SMB_ACL_NEXT_ENTRY;
3110                 }
3111                 ace_count++;
3112         }
3113         return ace_count;
3114 }
3115
3116 /****************************************************************************
3117  Utility function to marshall a POSIX acl into wire format.
3118 ****************************************************************************/
3119
3120 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3121 {
3122         int entry_id = SMB_ACL_FIRST_ENTRY;
3123         SMB_ACL_ENTRY_T entry;
3124
3125         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3126                 SMB_ACL_TAG_T tagtype;
3127                 SMB_ACL_PERMSET_T permset;
3128                 unsigned char perms = 0;
3129                 unsigned int own_grp;
3130
3131                 /* get_next... */
3132                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3133                         entry_id = SMB_ACL_NEXT_ENTRY;
3134                 }
3135
3136                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3137                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3138                         return False;
3139                 }
3140
3141                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3142                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3143                         return False;
3144                 }
3145
3146                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3147                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3148                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3149
3150                 SCVAL(pdata,1,perms);
3151
3152                 switch (tagtype) {
3153                         case SMB_ACL_USER_OBJ:
3154                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3155                                 own_grp = (unsigned int)pst->st_uid;
3156                                 SIVAL(pdata,2,own_grp);
3157                                 SIVAL(pdata,6,0);
3158                                 break;
3159                         case SMB_ACL_USER:
3160                                 {
3161                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3162                                         if (!puid) {
3163                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3164                                                 return False;
3165                                         }
3166                                         own_grp = (unsigned int)*puid;
3167                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3168                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3169                                         SIVAL(pdata,2,own_grp);
3170                                         SIVAL(pdata,6,0);
3171                                         break;
3172                                 }
3173                         case SMB_ACL_GROUP_OBJ:
3174                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3175                                 own_grp = (unsigned int)pst->st_gid;
3176                                 SIVAL(pdata,2,own_grp);
3177                                 SIVAL(pdata,6,0);
3178                                 break;
3179                         case SMB_ACL_GROUP:
3180                                 {
3181                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3182                                         if (!pgid) {
3183                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3184                                                 return False;
3185                                         }
3186                                         own_grp = (unsigned int)*pgid;
3187                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3188                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3189                                         SIVAL(pdata,2,own_grp);
3190                                         SIVAL(pdata,6,0);
3191                                         break;
3192                                 }
3193                         case SMB_ACL_MASK:
3194                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3195                                 SIVAL(pdata,2,0xFFFFFFFF);
3196                                 SIVAL(pdata,6,0xFFFFFFFF);
3197                                 break;
3198                         case SMB_ACL_OTHER:
3199                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3200                                 SIVAL(pdata,2,0xFFFFFFFF);
3201                                 SIVAL(pdata,6,0xFFFFFFFF);
3202                                 break;
3203                         default:
3204                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3205                                 return False;
3206                 }
3207                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3208         }
3209
3210         return True;
3211 }
3212 #endif
3213
3214 /****************************************************************************
3215  Store the FILE_UNIX_BASIC info.
3216 ****************************************************************************/
3217
3218 static char *store_file_unix_basic(connection_struct *conn,
3219                                 char *pdata,
3220                                 files_struct *fsp,
3221                                 const SMB_STRUCT_STAT *psbuf)
3222 {
3223         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3224         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3225
3226         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3227         pdata += 8;
3228
3229         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3230         pdata += 8;
3231
3232         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3233         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3234         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3235         pdata += 24;
3236
3237         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3238         SIVAL(pdata,4,0);
3239         pdata += 8;
3240
3241         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3242         SIVAL(pdata,4,0);
3243         pdata += 8;
3244
3245         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3246         pdata += 4;
3247
3248         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3249         SIVAL(pdata,4,0);
3250         pdata += 8;
3251
3252         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3253         SIVAL(pdata,4,0);
3254         pdata += 8;
3255
3256         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3257         pdata += 8;
3258                                 
3259         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3260         SIVAL(pdata,4,0);
3261         pdata += 8;
3262
3263         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3264         SIVAL(pdata,4,0);
3265         pdata += 8;
3266
3267         return pdata;
3268 }
3269
3270 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3271  * the chflags(2) (or equivalent) flags.
3272  *
3273  * XXX: this really should be behind the VFS interface. To do this, we would
3274  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3275  * Each VFS module could then implement it's own mapping as appropriate for the
3276  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3277  */
3278 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3279         info2_flags_map[] =
3280 {
3281 #ifdef UF_NODUMP
3282     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3283 #endif
3284
3285 #ifdef UF_IMMUTABLE
3286     { UF_IMMUTABLE, EXT_IMMUTABLE },
3287 #endif
3288
3289 #ifdef UF_APPEND
3290     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3291 #endif
3292
3293 #ifdef UF_HIDDEN
3294     { UF_HIDDEN, EXT_HIDDEN },
3295 #endif
3296
3297     /* Do not remove. We need to guarantee that this array has at least one
3298      * entry to build on HP-UX.
3299      */
3300     { 0, 0 }
3301
3302 };
3303
3304 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3305                                 uint32 *smb_fflags, uint32 *smb_fmask)
3306 {
3307 #ifdef HAVE_STAT_ST_FLAGS
3308         int i;
3309
3310         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3311             *smb_fmask |= info2_flags_map[i].smb_fflag;
3312             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3313                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3314             }
3315         }
3316 #endif /* HAVE_STAT_ST_FLAGS */
3317 }
3318
3319 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3320                                 const uint32 smb_fflags,
3321                                 const uint32 smb_fmask,
3322                                 int *stat_fflags)
3323 {
3324 #ifdef HAVE_STAT_ST_FLAGS
3325         uint32 max_fmask = 0;
3326         int i;
3327
3328         *stat_fflags = psbuf->st_flags;
3329
3330         /* For each flags requested in smb_fmask, check the state of the
3331          * corresponding flag in smb_fflags and set or clear the matching
3332          * stat flag.
3333          */
3334
3335         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3336             max_fmask |= info2_flags_map[i].smb_fflag;
3337             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3338                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3339                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3340                     } else {
3341                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3342                     }
3343             }
3344         }
3345
3346         /* If smb_fmask is asking to set any bits that are not supported by
3347          * our flag mappings, we should fail.
3348          */
3349         if ((smb_fmask & max_fmask) != smb_fmask) {
3350                 return False;
3351         }
3352
3353         return True;
3354 #else
3355         return False;
3356 #endif /* HAVE_STAT_ST_FLAGS */
3357 }
3358
3359
3360 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3361  * of file flags and birth (create) time.
3362  */
3363 static char *store_file_unix_basic_info2(connection_struct *conn,
3364                                 char *pdata,
3365                                 files_struct *fsp,
3366                                 const SMB_STRUCT_STAT *psbuf)
3367 {
3368         uint32 file_flags = 0;
3369         uint32 flags_mask = 0;
3370
3371         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3372
3373         /* Create (birth) time 64 bit */
3374         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3375         pdata += 8;
3376
3377         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3378         SIVAL(pdata, 0, file_flags); /* flags */
3379         SIVAL(pdata, 4, flags_mask); /* mask */
3380         pdata += 8;
3381
3382         return pdata;
3383 }
3384
3385 /****************************************************************************
3386  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3387 ****************************************************************************/
3388
3389 static void call_trans2qpipeinfo(connection_struct *conn,
3390                                  struct smb_request *req,
3391                                  unsigned int tran_call,
3392                                  char **pparams, int total_params,
3393                                  char **ppdata, int total_data,
3394                                  unsigned int max_data_bytes)
3395 {
3396         char *params = *pparams;
3397         char *pdata = *ppdata;
3398         unsigned int data_size = 0;
3399         unsigned int param_size = 2;
3400         uint16 info_level;
3401         smb_np_struct *p_pipe = NULL;
3402
3403         if (!params) {
3404                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3405                 return;
3406         }
3407
3408         if (total_params < 4) {
3409                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3410                 return;
3411         }
3412
3413         p_pipe = get_rpc_pipe_p(SVAL(params,0));
3414         if (p_pipe == NULL) {
3415                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3416                 return;
3417         }
3418
3419         info_level = SVAL(params,2);
3420
3421         *pparams = (char *)SMB_REALLOC(*pparams,2);
3422         if (*pparams == NULL) {
3423                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3424                 return;
3425         }
3426         params = *pparams;
3427         SSVAL(params,0,0);
3428         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3429         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3430         if (*ppdata == NULL ) {
3431                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3432                 return;
3433         }
3434         pdata = *ppdata;
3435
3436         switch (info_level) {
3437                 case SMB_FILE_STANDARD_INFORMATION:
3438                         memset(pdata,0,24);
3439                         SOFF_T(pdata,0,4096LL);
3440                         SIVAL(pdata,16,1);
3441                         SIVAL(pdata,20,1);
3442                         data_size = 24;
3443                         break;
3444
3445                 default:
3446                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3447                         return;
3448         }
3449
3450         send_trans2_replies(req, params, param_size, *ppdata, data_size,
3451                             max_data_bytes);
3452
3453         return;
3454 }
3455
3456 /****************************************************************************
3457  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3458  file name or file id).
3459 ****************************************************************************/
3460
3461 static void call_trans2qfilepathinfo(connection_struct *conn,
3462                                      struct smb_request *req,
3463                                      unsigned int tran_call,
3464                                      char **pparams, int total_params,
3465                                      char **ppdata, int total_data,
3466                                      unsigned int max_data_bytes)
3467 {
3468         char *params = *pparams;
3469         char *pdata = *ppdata;
3470         char *dstart, *dend;
3471         uint16 info_level;
3472         int mode=0;
3473         int nlink;
3474         SMB_OFF_T file_size=0;
3475         SMB_BIG_UINT allocation_size=0;
3476         unsigned int data_size = 0;
3477         unsigned int param_size = 2;
3478         SMB_STRUCT_STAT sbuf;
3479         char *dos_fname = NULL;
3480         char *fname = NULL;
3481         char *fullpathname;
3482         char *base_name;
3483         char *p;
3484         SMB_OFF_T pos = 0;
3485         bool delete_pending = False;
3486         int len;
3487         time_t create_time, mtime, atime;
3488         struct timespec create_time_ts, mtime_ts, atime_ts;
3489         files_struct *fsp = NULL;
3490         struct file_id fileid;
3491         struct ea_list *ea_list = NULL;
3492         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3493         char *lock_data = NULL;
3494         TALLOC_CTX *ctx = talloc_tos();
3495
3496         if (!params) {
3497                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3498                 return;
3499         }
3500
3501         ZERO_STRUCT(sbuf);
3502
3503         if (tran_call == TRANSACT2_QFILEINFO) {
3504                 if (total_params < 4) {
3505                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3506                         return;
3507                 }
3508
3509                 if (IS_IPC(conn)) {
3510                         call_trans2qpipeinfo(conn, req, tran_call,
3511                                              pparams, total_params,
3512                                              ppdata, total_data,
3513                                              max_data_bytes);
3514                         return;
3515                 }
3516
3517                 fsp = file_fsp(SVAL(params,0));
3518                 info_level = SVAL(params,2);
3519
3520                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3521
3522                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3523                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3524                         return;
3525                 }
3526
3527                 /* Initial check for valid fsp ptr. */
3528                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3529                         return;
3530                 }
3531
3532                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3533                 if (!fname) {
3534                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3535                         return;
3536                 }
3537
3538                 if(fsp->fake_file_handle) {
3539                         /*
3540                          * This is actually for the QUOTA_FAKE_FILE --metze
3541                          */
3542
3543                         /* We know this name is ok, it's already passed the checks. */
3544
3545                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3546                         /*
3547                          * This is actually a QFILEINFO on a directory
3548                          * handle (returned from an NT SMB). NT5.0 seems
3549                          * to do this call. JRA.
3550                          */
3551
3552                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3553                                 /* Always do lstat for UNIX calls. */
3554                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3555                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3556                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3557                                         return;
3558                                 }
3559                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3560                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3561                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3562                                 return;
3563                         }
3564
3565                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3566                         delete_pending = get_delete_on_close_flag(fileid);
3567                 } else {
3568                         /*
3569                          * Original code - this is an open file.
3570                          */
3571                         if (!check_fsp(conn, req, fsp, &current_user)) {
3572                                 return;
3573                         }
3574
3575                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3576                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3577                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3578                                 return;
3579                         }
3580                         pos = fsp->fh->position_information;
3581                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3582                         delete_pending = get_delete_on_close_flag(fileid);
3583                         access_mask = fsp->access_mask;
3584                 }
3585
3586         } else {
3587                 NTSTATUS status = NT_STATUS_OK;
3588
3589                 /* qpathinfo */
3590                 if (total_params < 7) {
3591                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3592                         return;
3593                 }
3594
3595                 info_level = SVAL(params,0);
3596
3597                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3598
3599                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3600                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3601                         return;
3602                 }
3603
3604                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3605                                 total_params - 6,
3606                                 STR_TERMINATE, &status);
3607                 if (!NT_STATUS_IS_OK(status)) {
3608                         reply_nterror(req, status);
3609                         return;
3610                 }
3611
3612                 status = resolve_dfspath(ctx,
3613                                         conn,
3614                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3615                                         fname,
3616                                         &fname);
3617                 if (!NT_STATUS_IS_OK(status)) {
3618                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3619                                 reply_botherror(req,
3620                                                 NT_STATUS_PATH_NOT_COVERED,
3621                                                 ERRSRV, ERRbadpath);
3622                         }
3623                         reply_nterror(req, status);
3624                         return;
3625                 }
3626
3627                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3628                 if (!NT_STATUS_IS_OK(status)) {
3629                         reply_nterror(req, status);
3630                         return;
3631                 }
3632                 status = check_name(conn, fname);
3633                 if (!NT_STATUS_IS_OK(status)) {
3634                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3635                         reply_nterror(req, status);
3636                         return;
3637                 }
3638
3639                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3640                         /* Always do lstat for UNIX calls. */
3641                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3642                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3643                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3644                                 return;
3645                         }
3646                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3647                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3648                         reply_unixerror(req, ERRDOS, ERRbadpath);
3649                         return;
3650                 }
3651
3652                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3653                 delete_pending = get_delete_on_close_flag(fileid);
3654                 if (delete_pending) {
3655                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
3656                         return;
3657                 }
3658         }
3659
3660         nlink = sbuf.st_nlink;
3661
3662         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3663                 /* NTFS does not seem to count ".." */
3664                 nlink -= 1;
3665         }
3666
3667         if ((nlink > 0) && delete_pending) {
3668                 nlink -= 1;
3669         }
3670
3671         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3672                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3673                 return;
3674         }
3675
3676         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3677                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3678
3679         p = strrchr_m(fname,'/');
3680         if (!p)
3681                 base_name = fname;
3682         else
3683                 base_name = p+1;
3684
3685         mode = dos_mode(conn,fname,&sbuf);
3686         if (!mode)
3687                 mode = FILE_ATTRIBUTE_NORMAL;
3688
3689         fullpathname = fname;
3690         if (!(mode & aDIR))
3691                 file_size = get_file_size(sbuf);
3692
3693         /* Pull out any data sent here before we realloc. */
3694         switch (info_level) {
3695                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3696                 {
3697                         /* Pull any EA list from the data portion. */
3698                         uint32 ea_size;
3699
3700                         if (total_data < 4) {
3701                                 reply_nterror(
3702                                         req, NT_STATUS_INVALID_PARAMETER);
3703                                 return;
3704                         }
3705                         ea_size = IVAL(pdata,0);
3706
3707                         if (total_data > 0 && ea_size != total_data) {
3708                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3709 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3710                                 reply_nterror(
3711                                         req, NT_STATUS_INVALID_PARAMETER);
3712                                 return;
3713                         }
3714
3715                         if (!lp_ea_support(SNUM(conn))) {
3716                                 reply_doserror(req, ERRDOS,
3717                                                ERReasnotsupported);
3718                                 return;
3719                         }
3720
3721                         /* Pull out the list of names. */
3722                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3723                         if (!ea_list) {
3724                                 reply_nterror(
3725                                         req, NT_STATUS_INVALID_PARAMETER);
3726                                 return;
3727                         }
3728                         break;
3729                 }
3730
3731                 case SMB_QUERY_POSIX_LOCK:
3732                 {
3733                         if (fsp == NULL || fsp->fh->fd == -1) {
3734                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3735                                 return;
3736                         }
3737
3738                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3739                                 reply_nterror(
3740                                         req, NT_STATUS_INVALID_PARAMETER);
3741                                 return;
3742                         }
3743
3744                         /* Copy the lock range data. */
3745                         lock_data = (char *)TALLOC_MEMDUP(
3746                                 ctx, pdata, total_data);
3747                         if (!lock_data) {
3748                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3749                                 return;
3750                         }
3751                 }
3752                 default:
3753                         break;
3754         }
3755
3756         *pparams = (char *)SMB_REALLOC(*pparams,2);
3757         if (*pparams == NULL) {
3758                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3759                 return;
3760         }
3761         params = *pparams;
3762         SSVAL(params,0,0);
3763         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3764         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3765         if (*ppdata == NULL ) {
3766                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3767                 return;
3768         }
3769         pdata = *ppdata;
3770         dstart = pdata;
3771         dend = dstart + data_size - 1;
3772
3773         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3774         mtime_ts = get_mtimespec(&sbuf);
3775         atime_ts = get_atimespec(&sbuf);
3776
3777         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3778
3779         if (fsp) {
3780                 if (!null_timespec(fsp->pending_modtime)) {
3781                         /* the pending modtime overrides the current modtime */
3782                         mtime_ts = fsp->pending_modtime;
3783                 }
3784         } else {
3785                 files_struct *fsp1;
3786                 /* Do we have this path open ? */
3787                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3788                 fsp1 = file_find_di_first(fileid);
3789                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3790                         /* the pending modtime overrides the current modtime */
3791                         mtime_ts = fsp1->pending_modtime;
3792                 }
3793                 if (fsp1 && fsp1->initial_allocation_size) {
3794                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3795                 }
3796         }
3797
3798         if (lp_dos_filetime_resolution(SNUM(conn))) {
3799                 dos_filetime_timespec(&create_time_ts);
3800                 dos_filetime_timespec(&mtime_ts);
3801                 dos_filetime_timespec(&atime_ts);
3802         }
3803
3804         create_time = convert_timespec_to_time_t(create_time_ts);
3805         mtime = convert_timespec_to_time_t(mtime_ts);
3806         atime = convert_timespec_to_time_t(atime_ts);
3807
3808         /* NT expects the name to be in an exact form of the *full*
3809            filename. See the trans2 torture test */
3810         if (ISDOT(base_name)) {
3811                 dos_fname = talloc_strdup(ctx, "\\");
3812                 if (!dos_fname) {
3813                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3814                         return;
3815                 }
3816         } else {
3817                 dos_fname = talloc_asprintf(ctx,
3818                                 "\\%s",
3819                                 fname);
3820                 if (!dos_fname) {
3821                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3822                         return;
3823                 }
3824                 string_replace(dos_fname, '/', '\\');
3825         }
3826
3827         switch (info_level) {
3828                 case SMB_INFO_STANDARD:
3829                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3830                         data_size = 22;
3831                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3832                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3833                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3834                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3835                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3836                         SSVAL(pdata,l1_attrFile,mode);
3837                         break;
3838
3839                 case SMB_INFO_QUERY_EA_SIZE:
3840                 {
3841                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3842                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3843                         data_size = 26;
3844                         srv_put_dos_date2(pdata,0,create_time);
3845                         srv_put_dos_date2(pdata,4,atime);
3846                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3847                         SIVAL(pdata,12,(uint32)file_size);
3848                         SIVAL(pdata,16,(uint32)allocation_size);
3849                         SSVAL(pdata,20,mode);
3850                         SIVAL(pdata,22,ea_size);
3851                         break;
3852                 }
3853
3854                 case SMB_INFO_IS_NAME_VALID:
3855                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3856                         if (tran_call == TRANSACT2_QFILEINFO) {
3857                                 /* os/2 needs this ? really ?*/
3858                                 reply_doserror(req, ERRDOS, ERRbadfunc);
3859                                 return;
3860                         }
3861                         data_size = 0;
3862                         param_size = 0;
3863                         break;
3864
3865                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3866                 {
3867                         size_t total_ea_len = 0;
3868                         struct ea_list *ea_file_list = NULL;
3869
3870                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3871
3872                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3873                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3874
3875                         if (!ea_list || (total_ea_len > data_size)) {
3876                                 data_size = 4;
3877                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3878                                 break;
3879                         }
3880
3881                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3882                         break;
3883                 }
3884
3885                 case SMB_INFO_QUERY_ALL_EAS:
3886                 {
3887                         /* We have data_size bytes to put EA's into. */
3888                         size_t total_ea_len = 0;
3889
3890                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3891
3892                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3893                         if (!ea_list || (total_ea_len > data_size)) {
3894                                 data_size = 4;
3895                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3896                                 break;
3897                         }
3898
3899                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3900                         break;
3901                 }
3902
3903                 case SMB_FILE_BASIC_INFORMATION:
3904                 case SMB_QUERY_FILE_BASIC_INFO:
3905
3906                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3907                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3908                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3909                         } else {
3910                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3911                                 data_size = 40;
3912                                 SIVAL(pdata,36,0);
3913                         }
3914                         put_long_date_timespec(pdata,create_time_ts);
3915                         put_long_date_timespec(pdata+8,atime_ts);
3916                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3917                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3918                         SIVAL(pdata,32,mode);
3919
3920                         DEBUG(5,("SMB_QFBI - "));
3921                         DEBUG(5,("create: %s ", ctime(&create_time)));
3922                         DEBUG(5,("access: %s ", ctime(&atime)));
3923                         DEBUG(5,("write: %s ", ctime(&mtime)));
3924                         DEBUG(5,("change: %s ", ctime(&mtime)));
3925                         DEBUG(5,("mode: %x\n", mode));
3926                         break;
3927
3928                 case SMB_FILE_STANDARD_INFORMATION:
3929                 case SMB_QUERY_FILE_STANDARD_INFO:
3930
3931                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3932                         data_size = 24;
3933                         SOFF_T(pdata,0,allocation_size);
3934                         SOFF_T(pdata,8,file_size);
3935                         SIVAL(pdata,16,nlink);
3936                         SCVAL(pdata,20,delete_pending?1:0);
3937                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3938                         SSVAL(pdata,22,0); /* Padding. */
3939                         break;
3940
3941                 case SMB_FILE_EA_INFORMATION:
3942                 case SMB_QUERY_FILE_EA_INFO:
3943                 {
3944                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3945                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3946                         data_size = 4;
3947                         SIVAL(pdata,0,ea_size);
3948                         break;
3949                 }
3950
3951                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3952                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3953                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3954                 {
3955                         char mangled_name[13];
3956                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3957                         if (!name_to_8_3(base_name,mangled_name,
3958                                                 True,conn->params)) {
3959                                 reply_nterror(
3960                                         req,
3961                                         NT_STATUS_NO_MEMORY);
3962                         }
3963                         len = srvstr_push(dstart, req->flags2,
3964                                           pdata+4, mangled_name,
3965                                           PTR_DIFF(dend, pdata+4),
3966                                           STR_UNICODE);
3967                         data_size = 4 + len;
3968                         SIVAL(pdata,0,len);
3969                         break;
3970                 }
3971
3972                 case SMB_QUERY_FILE_NAME_INFO:
3973                         /*
3974                           this must be *exactly* right for ACLs on mapped drives to work
3975                          */
3976                         len = srvstr_push(dstart, req->flags2,
3977                                           pdata+4, dos_fname,
3978                                           PTR_DIFF(dend, pdata+4),
3979                                           STR_UNICODE);
3980                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3981                         data_size = 4 + len;
3982                         SIVAL(pdata,0,len);
3983                         break;
3984
3985                 case SMB_FILE_ALLOCATION_INFORMATION:
3986                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3987                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3988                         data_size = 8;
3989                         SOFF_T(pdata,0,allocation_size);
3990                         break;
3991
3992                 case SMB_FILE_END_OF_FILE_INFORMATION:
3993                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3994                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3995                         data_size = 8;
3996                         SOFF_T(pdata,0,file_size);
3997                         break;
3998
3999                 case SMB_QUERY_FILE_ALL_INFO:
4000                 case SMB_FILE_ALL_INFORMATION:
4001                 {
4002                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4003                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4004                         put_long_date_timespec(pdata,create_time_ts);
4005                         put_long_date_timespec(pdata+8,atime_ts);
4006                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4007                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4008                         SIVAL(pdata,32,mode);
4009                         SIVAL(pdata,36,0); /* padding. */
4010                         pdata += 40;
4011                         SOFF_T(pdata,0,allocation_size);
4012                         SOFF_T(pdata,8,file_size);
4013                         SIVAL(pdata,16,nlink);
4014                         SCVAL(pdata,20,delete_pending);
4015                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4016                         SSVAL(pdata,22,0);
4017                         pdata += 24;
4018                         SIVAL(pdata,0,ea_size);
4019                         pdata += 4; /* EA info */
4020                         len = srvstr_push(dstart, req->flags2,
4021                                           pdata+4, dos_fname,
4022                                           PTR_DIFF(dend, pdata+4),
4023                                           STR_UNICODE);
4024                         SIVAL(pdata,0,len);
4025                         pdata += 4 + len;
4026                         data_size = PTR_DIFF(pdata,(*ppdata));
4027                         break;
4028                 }
4029                 case SMB_FILE_INTERNAL_INFORMATION:
4030                         /* This should be an index number - looks like
4031                            dev/ino to me :-) 
4032
4033                            I think this causes us to fail the IFSKIT
4034                            BasicFileInformationTest. -tpot */
4035
4036                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4037                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4038                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4039                         data_size = 8;
4040                         break;
4041
4042                 case SMB_FILE_ACCESS_INFORMATION:
4043                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4044                         SIVAL(pdata,0,access_mask);
4045                         data_size = 4;
4046                         break;
4047
4048                 case SMB_FILE_NAME_INFORMATION:
4049                         /* Pathname with leading '\'. */
4050                         {
4051                                 size_t byte_len;
4052                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4053                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4054                                 SIVAL(pdata,0,byte_len);
4055                                 data_size = 4 + byte_len;
4056                                 break;
4057                         }
4058
4059                 case SMB_FILE_DISPOSITION_INFORMATION:
4060                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4061                         data_size = 1;
4062                         SCVAL(pdata,0,delete_pending);
4063                         break;
4064
4065                 case SMB_FILE_POSITION_INFORMATION:
4066                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4067                         data_size = 8;
4068                         SOFF_T(pdata,0,pos);
4069                         break;
4070
4071                 case SMB_FILE_MODE_INFORMATION:
4072                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4073                         SIVAL(pdata,0,mode);
4074                         data_size = 4;
4075                         break;
4076
4077                 case SMB_FILE_ALIGNMENT_INFORMATION:
4078                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4079                         SIVAL(pdata,0,0); /* No alignment needed. */
4080                         data_size = 4;
4081                         break;
4082
4083 #if 0
4084                 /*
4085                  * NT4 server just returns "invalid query" to this - if we try to answer
4086                  * it then NTws gets a BSOD! (tridge).
4087                  * W2K seems to want this. JRA.
4088                  */
4089                 case SMB_QUERY_FILE_STREAM_INFO:
4090 #endif
4091                 case SMB_FILE_STREAM_INFORMATION:
4092                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4093                         if (mode & aDIR) {
4094                                 data_size = 0;
4095                         } else {
4096                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4097                                 SIVAL(pdata,0,0); /* ??? */
4098                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4099                                 SOFF_T(pdata,8,file_size);
4100                                 SOFF_T(pdata,16,allocation_size);
4101                                 data_size = 24 + byte_len;
4102                         }
4103                         break;
4104
4105                 case SMB_QUERY_COMPRESSION_INFO:
4106                 case SMB_FILE_COMPRESSION_INFORMATION:
4107                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4108                         SOFF_T(pdata,0,file_size);
4109                         SIVAL(pdata,8,0); /* ??? */
4110                         SIVAL(pdata,12,0); /* ??? */
4111                         data_size = 16;
4112                         break;
4113
4114                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4115                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4116                         put_long_date_timespec(pdata,create_time_ts);
4117                         put_long_date_timespec(pdata+8,atime_ts);
4118                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4119                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4120                         SOFF_T(pdata,32,allocation_size);
4121                         SOFF_T(pdata,40,file_size);
4122                         SIVAL(pdata,48,mode);
4123                         SIVAL(pdata,52,0); /* ??? */
4124                         data_size = 56;
4125                         break;
4126
4127                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4128                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4129                         SIVAL(pdata,0,mode);
4130                         SIVAL(pdata,4,0);
4131                         data_size = 8;
4132                         break;
4133
4134                 /*
4135                  * CIFS UNIX Extensions.
4136                  */
4137
4138                 case SMB_QUERY_FILE_UNIX_BASIC:
4139
4140                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4141                         data_size = PTR_DIFF(pdata,(*ppdata));
4142
4143                         {
4144                                 int i;
4145                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4146
4147                                 for (i=0; i<100; i++)
4148                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4149                                 DEBUG(4,("\n"));
4150                         }
4151
4152                         break;
4153
4154                 case SMB_QUERY_FILE_UNIX_INFO2:
4155
4156                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4157                         data_size = PTR_DIFF(pdata,(*ppdata));
4158
4159                         {
4160                                 int i;
4161                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4162
4163                                 for (i=0; i<100; i++)
4164                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4165                                 DEBUG(4,("\n"));
4166                         }
4167
4168                         break;
4169
4170                 case SMB_QUERY_FILE_UNIX_LINK:
4171                         {
4172                                 char *buffer = TALLOC_ARRAY(ctx, char, 1024);
4173
4174                                 if (!buffer) {
4175                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4176                                         return;
4177                                 }
4178
4179                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4180 #ifdef S_ISLNK
4181                                 if(!S_ISLNK(sbuf.st_mode)) {
4182                                         reply_unixerror(req, ERRSRV,
4183                                                         ERRbadlink);
4184                                         return;
4185                                 }
4186 #else
4187                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4188                                 return;
4189 #endif
4190                                 len = SMB_VFS_READLINK(conn,fullpathname,
4191                                                 buffer, 1023);
4192                                 if (len == -1) {
4193                                         reply_unixerror(req, ERRDOS,
4194                                                         ERRnoaccess);
4195                                         return;
4196                                 }
4197                                 buffer[len] = 0;
4198                                 len = srvstr_push(dstart, req->flags2,
4199                                                   pdata, buffer,
4200                                                   PTR_DIFF(dend, pdata),
4201                                                   STR_TERMINATE);
4202                                 pdata += len;
4203                                 data_size = PTR_DIFF(pdata,(*ppdata));
4204
4205                                 break;
4206                         }
4207
4208 #if defined(HAVE_POSIX_ACLS)
4209                 case SMB_QUERY_POSIX_ACL:
4210                         {
4211                                 SMB_ACL_T file_acl = NULL;
4212                                 SMB_ACL_T def_acl = NULL;
4213                                 uint16 num_file_acls = 0;
4214                                 uint16 num_def_acls = 0;
4215
4216                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4217                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4218                                 } else {
4219                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4220                                 }
4221
4222                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4223                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4224                                                 fname ));
4225                                         reply_nterror(
4226                                                 req,
4227                                                 NT_STATUS_NOT_IMPLEMENTED);
4228                                         return;
4229                                 }
4230
4231                                 if (S_ISDIR(sbuf.st_mode)) {
4232                                         if (fsp && fsp->is_directory) {
4233                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4234                                         } else {
4235                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4236                                         }
4237                                         def_acl = free_empty_sys_acl(conn, def_acl);
4238                                 }
4239
4240                                 num_file_acls = count_acl_entries(conn, file_acl);
4241                                 num_def_acls = count_acl_entries(conn, def_acl);
4242
4243                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4244                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4245                                                 data_size,
4246                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4247                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4248                                         if (file_acl) {
4249                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4250                                         }
4251                                         if (def_acl) {
4252                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4253                                         }
4254                                         reply_nterror(
4255                                                 req,
4256                                                 NT_STATUS_BUFFER_TOO_SMALL);
4257                                         return;
4258                                 }
4259
4260                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4261                                 SSVAL(pdata,2,num_file_acls);
4262                                 SSVAL(pdata,4,num_def_acls);
4263                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4264                                         if (file_acl) {
4265                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4266                                         }
4267                                         if (def_acl) {
4268                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4269                                         }
4270                                         reply_nterror(
4271                                                 req, NT_STATUS_INTERNAL_ERROR);
4272                                         return;
4273                                 }
4274                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4275                                         if (file_acl) {
4276                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4277                                         }
4278                                         if (def_acl) {
4279                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4280                                         }
4281                                         reply_nterror(
4282                                                 req,
4283                                                 NT_STATUS_INTERNAL_ERROR);
4284                                         return;
4285                                 }
4286
4287                                 if (file_acl) {
4288                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4289                                 }
4290                                 if (def_acl) {
4291                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4292                                 }
4293                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4294                                 break;
4295                         }
4296 #endif
4297
4298
4299                 case SMB_QUERY_POSIX_LOCK:
4300                 {
4301                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4302                         SMB_BIG_UINT count;
4303                         SMB_BIG_UINT offset;
4304                         uint32 lock_pid;
4305                         enum brl_type lock_type;
4306
4307                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4308                                 reply_nterror(
4309                                         req, NT_STATUS_INVALID_PARAMETER);
4310                                 return;
4311                         }
4312
4313                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4314                                 case POSIX_LOCK_TYPE_READ:
4315                                         lock_type = READ_LOCK;
4316                                         break;
4317                                 case POSIX_LOCK_TYPE_WRITE:
4318                                         lock_type = WRITE_LOCK;
4319                                         break;
4320                                 case POSIX_LOCK_TYPE_UNLOCK:
4321                                 default:
4322                                         /* There's no point in asking for an unlock... */
4323                                         reply_nterror(
4324                                                 req,
4325                                                 NT_STATUS_INVALID_PARAMETER);
4326                                         return;
4327                         }
4328
4329                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4330 #if defined(HAVE_LONGLONG)
4331                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4332                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4333                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4334                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4335 #else /* HAVE_LONGLONG */
4336                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4337                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4338 #endif /* HAVE_LONGLONG */
4339
4340                         status = query_lock(fsp,
4341                                         &lock_pid,
4342                                         &count,
4343                                         &offset,
4344                                         &lock_type,
4345                                         POSIX_LOCK);
4346
4347                         if (ERROR_WAS_LOCK_DENIED(status)) {
4348                                 /* Here we need to report who has it locked... */
4349                                 data_size = POSIX_LOCK_DATA_SIZE;
4350
4351                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4352                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4353                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4354 #if defined(HAVE_LONGLONG)
4355                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4356                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4357                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4358                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4359 #else /* HAVE_LONGLONG */
4360                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4361                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4362 #endif /* HAVE_LONGLONG */
4363
4364                         } else if (NT_STATUS_IS_OK(status)) {
4365                                 /* For success we just return a copy of what we sent
4366                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4367                                 data_size = POSIX_LOCK_DATA_SIZE;
4368                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4369                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4370                         } else {
4371                                 reply_nterror(req, status);
4372                                 return;
4373                         }
4374                         break;
4375                 }
4376
4377                 default:
4378                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4379                         return;
4380         }
4381
4382         send_trans2_replies(req, params, param_size, *ppdata, data_size,
4383                             max_data_bytes);
4384
4385         return;
4386 }
4387
4388 /****************************************************************************
4389  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4390  code.
4391 ****************************************************************************/
4392
4393 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4394                 connection_struct *conn,
4395                 const char *oldname_in,
4396                 const char *newname_in)
4397 {
4398         SMB_STRUCT_STAT sbuf1, sbuf2;
4399         char *last_component_oldname = NULL;
4400         char *last_component_newname = NULL;
4401         char *oldname = NULL;
4402         char *newname = NULL;
4403         NTSTATUS status = NT_STATUS_OK;
4404
4405         ZERO_STRUCT(sbuf1);
4406         ZERO_STRUCT(sbuf2);
4407
4408         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4409                         &last_component_oldname, &sbuf1);
4410         if (!NT_STATUS_IS_OK(status)) {
4411                 return status;
4412         }
4413
4414         status = check_name(conn, oldname);
4415         if (!NT_STATUS_IS_OK(status)) {
4416                 return status;
4417         }
4418
4419         /* source must already exist. */
4420         if (!VALID_STAT(sbuf1)) {
4421                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4422         }
4423
4424         status = unix_convert(ctx, conn, newname_in, False, &newname,
4425                         &last_component_newname, &sbuf2);
4426         if (!NT_STATUS_IS_OK(status)) {
4427                 return status;
4428         }
4429
4430         status = check_name(conn, newname);
4431         if (!NT_STATUS_IS_OK(status)) {
4432                 return status;
4433         }
4434
4435         /* Disallow if newname already exists. */
4436         if (VALID_STAT(sbuf2)) {
4437                 return NT_STATUS_OBJECT_NAME_COLLISION;
4438         }
4439
4440         /* No links from a directory. */
4441         if (S_ISDIR(sbuf1.st_mode)) {
4442                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4443         }
4444
4445         /* Ensure this is within the share. */
4446         status = check_reduced_name(conn, oldname);
4447         if (!NT_STATUS_IS_OK(status)) {
4448                 return status;
4449         }
4450
4451         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4452
4453         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4454                 status = map_nt_error_from_unix(errno);
4455                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4456                                 nt_errstr(status), newname, oldname));
4457         }
4458
4459         return status;
4460 }
4461
4462 /****************************************************************************
4463  Deal with setting the time from any of the setfilepathinfo functions.
4464 ****************************************************************************/
4465
4466 static NTSTATUS smb_set_file_time(connection_struct *conn,
4467                                 files_struct *fsp,
4468                                 const char *fname,
4469                                 const SMB_STRUCT_STAT *psbuf,
4470                                 struct timespec ts[2],
4471                                 bool setting_write_time)
4472 {
4473         uint32 action =
4474                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4475                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4476
4477         if (!VALID_STAT(*psbuf)) {
4478                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4479         }
4480
4481         /* get some defaults (no modifications) if any info is zero or -1. */
4482         if (null_timespec(ts[0])) {
4483                 ts[0] = get_atimespec(psbuf);
4484                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4485         }
4486
4487         if (null_timespec(ts[1])) {
4488                 ts[1] = get_mtimespec(psbuf);
4489                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4490         }
4491
4492         if (!setting_write_time) {
4493                 /* ts[1] comes from change time, not write time. */
4494                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4495         }
4496
4497         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4498         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4499
4500         /*
4501          * Try and set the times of this file if
4502          * they are different from the current values.
4503          */
4504
4505         {
4506                 struct timespec mts = get_mtimespec(psbuf);
4507                 struct timespec ats = get_atimespec(psbuf);
4508                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4509                         return NT_STATUS_OK;
4510                 }
4511         }
4512
4513         if(fsp != NULL) {
4514                 /*
4515                  * This was a setfileinfo on an open file.
4516                  * NT does this a lot. We also need to 
4517                  * set the time here, as it can be read by 
4518                  * FindFirst/FindNext and with the patch for bug #2045
4519                  * in smbd/fileio.c it ensures that this timestamp is
4520                  * kept sticky even after a write. We save the request
4521                  * away and will set it on file close and after a write. JRA.
4522                  */
4523
4524                 if (!null_timespec(ts[1])) {
4525                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4526                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4527                         fsp_set_pending_modtime(fsp, ts[1]);
4528                 }
4529
4530         }
4531         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4532
4533         if(file_ntimes(conn, fname, ts)!=0) {
4534                 return map_nt_error_from_unix(errno);
4535         }
4536         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4537
4538         return NT_STATUS_OK;
4539 }
4540
4541 /****************************************************************************
4542  Deal with setting the dosmode from any of the setfilepathinfo functions.
4543 ****************************************************************************/
4544
4545 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4546                                 const char *fname,
4547                                 SMB_STRUCT_STAT *psbuf,
4548                                 uint32 dosmode)
4549 {
4550         if (!VALID_STAT(*psbuf)) {
4551                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4552         }
4553
4554         if (dosmode) {
4555                 if (S_ISDIR(psbuf->st_mode)) {
4556                         dosmode |= aDIR;
4557                 } else {
4558                         dosmode &= ~aDIR;
4559                 }
4560         }
4561
4562         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4563
4564         /* check the mode isn't different, before changing it */
4565         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4566
4567                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4568                                         fname, (unsigned int)dosmode ));
4569
4570                 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4571                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4572                                                 fname, strerror(errno)));
4573                         return map_nt_error_from_unix(errno);
4574                 }
4575         }
4576         return NT_STATUS_OK;
4577 }
4578
4579 /****************************************************************************
4580  Deal with setting the size from any of the setfilepathinfo functions.
4581 ****************************************************************************/
4582
4583 static NTSTATUS smb_set_file_size(connection_struct *conn,
4584                                   struct smb_request *req,
4585                                 files_struct *fsp,
4586                                 const char *fname,
4587                                 SMB_STRUCT_STAT *psbuf,
4588                                 SMB_OFF_T size)
4589 {
4590         NTSTATUS status = NT_STATUS_OK;
4591         files_struct *new_fsp = NULL;
4592
4593         if (!VALID_STAT(*psbuf)) {
4594                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4595         }
4596
4597         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4598
4599         if (size == get_file_size(*psbuf)) {
4600                 return NT_STATUS_OK;
4601         }
4602
4603         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4604                 fname, (double)size ));
4605
4606         if (fsp && fsp->fh->fd != -1) {
4607                 /* Handle based call. */
4608                 if (vfs_set_filelen(fsp, size) == -1) {
4609                         return map_nt_error_from_unix(errno);
4610                 }
4611                 return NT_STATUS_OK;
4612         }
4613
4614         status = open_file_ntcreate(conn, req, fname, psbuf,
4615                                 FILE_WRITE_DATA,
4616                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4617                                 FILE_OPEN,
4618                                 0,
4619                                 FILE_ATTRIBUTE_NORMAL,
4620                                 FORCE_OPLOCK_BREAK_TO_NONE,
4621                                 NULL, &new_fsp);
4622         
4623         if (!NT_STATUS_IS_OK(status)) {
4624                 /* NB. We check for open_was_deferred in the caller. */
4625                 return status;
4626         }
4627
4628         if (vfs_set_filelen(new_fsp, size) == -1) {
4629                 status = map_nt_error_from_unix(errno);
4630                 close_file(new_fsp,NORMAL_CLOSE);
4631                 return status;
4632         }
4633
4634         close_file(new_fsp,NORMAL_CLOSE);
4635         return NT_STATUS_OK;
4636 }
4637
4638 /****************************************************************************
4639  Deal with SMB_INFO_SET_EA.
4640 ****************************************************************************/
4641
4642 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4643                                 const char *pdata,
4644                                 int total_data,
4645                                 files_struct *fsp,
4646                                 const char *fname)
4647 {
4648         struct ea_list *ea_list = NULL;
4649         TALLOC_CTX *ctx = NULL;
4650         NTSTATUS status = NT_STATUS_OK;
4651
4652         if (total_data < 10) {
4653
4654                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4655                    length. They seem to have no effect. Bug #3212. JRA */
4656
4657                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4658                         /* We're done. We only get EA info in this call. */
4659                         return NT_STATUS_OK;
4660                 }
4661
4662                 return NT_STATUS_INVALID_PARAMETER;
4663         }
4664
4665         if (IVAL(pdata,0) > total_data) {
4666                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4667                         IVAL(pdata,0), (unsigned int)total_data));
4668                 return NT_STATUS_INVALID_PARAMETER;
4669         }
4670
4671         ctx = talloc_init("SMB_INFO_SET_EA");
4672         if (!ctx) {
4673                 return NT_STATUS_NO_MEMORY;
4674         }
4675         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4676         if (!ea_list) {
4677                 talloc_destroy(ctx);
4678                 return NT_STATUS_INVALID_PARAMETER;
4679         }
4680         status = set_ea(conn, fsp, fname, ea_list);
4681         talloc_destroy(ctx);
4682
4683         return status;
4684 }
4685
4686 /****************************************************************************
4687  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4688 ****************************************************************************/
4689
4690 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4691                                 const char *pdata,
4692                                 int total_data,
4693                                 files_struct *fsp,
4694                                 const char *fname,
4695                                 SMB_STRUCT_STAT *psbuf)
4696 {
4697         NTSTATUS status = NT_STATUS_OK;
4698         bool delete_on_close;
4699         uint32 dosmode = 0;
4700
4701         if (total_data < 1) {
4702                 return NT_STATUS_INVALID_PARAMETER;
4703         }
4704
4705         if (fsp == NULL) {
4706                 return NT_STATUS_INVALID_HANDLE;
4707         }
4708
4709         delete_on_close = (CVAL(pdata,0) ? True : False);
4710         dosmode = dos_mode(conn, fname, psbuf);
4711
4712         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4713                 "delete_on_close = %u\n",
4714                 fsp->fsp_name,
4715                 (unsigned int)dosmode,
4716                 (unsigned int)delete_on_close ));
4717
4718         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4719  
4720         if (!NT_STATUS_IS_OK(status)) {
4721                 return status;
4722         }
4723
4724         /* The set is across all open files on this dev/inode pair. */
4725         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4726                 return NT_STATUS_ACCESS_DENIED;
4727         }
4728         return NT_STATUS_OK;
4729 }
4730
4731 /****************************************************************************
4732  Deal with SMB_FILE_POSITION_INFORMATION.
4733 ****************************************************************************/
4734
4735 static NTSTATUS smb_file_position_information(connection_struct *conn,
4736                                 const char *pdata,
4737                                 int total_data,
4738                                 files_struct *fsp)
4739 {
4740         SMB_BIG_UINT position_information;
4741
4742         if (total_data < 8) {
4743                 return NT_STATUS_INVALID_PARAMETER;
4744         }
4745
4746         if (fsp == NULL) {
4747                 /* Ignore on pathname based set. */
4748                 return NT_STATUS_OK;
4749         }
4750
4751         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4752 #ifdef LARGE_SMB_OFF_T
4753         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4754 #else /* LARGE_SMB_OFF_T */
4755         if (IVAL(pdata,4) != 0) {
4756                 /* more than 32 bits? */
4757                 return NT_STATUS_INVALID_PARAMETER;
4758         }
4759 #endif /* LARGE_SMB_OFF_T */
4760
4761         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4762                 fsp->fsp_name, (double)position_information ));
4763         fsp->fh->position_information = position_information;
4764         return NT_STATUS_OK;
4765 }
4766
4767 /****************************************************************************
4768  Deal with SMB_FILE_MODE_INFORMATION.
4769 ****************************************************************************/
4770
4771 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4772                                 const char *pdata,
4773                                 int total_data)
4774 {
4775         uint32 mode;
4776
4777         if (total_data < 4) {
4778                 return NT_STATUS_INVALID_PARAMETER;
4779         }
4780         mode = IVAL(pdata,0);
4781         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4782                 return NT_STATUS_INVALID_PARAMETER;
4783         }
4784         return NT_STATUS_OK;
4785 }
4786
4787 /****************************************************************************
4788  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4789 ****************************************************************************/
4790
4791 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4792                                        struct smb_request *req,
4793                                        const char *pdata,
4794                                        int total_data,
4795                                        const char *fname)
4796 {
4797         char *link_target = NULL;
4798         const char *newname = fname;
4799         NTSTATUS status = NT_STATUS_OK;
4800         TALLOC_CTX *ctx = talloc_tos();
4801
4802         /* Set a symbolic link. */
4803         /* Don't allow this if follow links is false. */
4804
4805         if (total_data == 0) {
4806                 return NT_STATUS_INVALID_PARAMETER;
4807         }
4808
4809         if (!lp_symlinks(SNUM(conn))) {
4810                 return NT_STATUS_ACCESS_DENIED;
4811         }
4812
4813         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4814                     total_data, STR_TERMINATE);
4815
4816         if (!link_target) {
4817                 return NT_STATUS_INVALID_PARAMETER;
4818         }
4819
4820         /* !widelinks forces the target path to be within the share. */
4821         /* This means we can interpret the target as a pathname. */
4822         if (!lp_widelinks(SNUM(conn))) {
4823                 char *rel_name = NULL;
4824                 char *last_dirp = NULL;
4825
4826                 if (*link_target == '/') {
4827                         /* No absolute paths allowed. */
4828                         return NT_STATUS_ACCESS_DENIED;
4829                 }
4830                 rel_name = talloc_strdup(ctx,newname);
4831                 if (!rel_name) {
4832                         return NT_STATUS_NO_MEMORY;
4833                 }
4834                 last_dirp = strrchr_m(rel_name, '/');
4835                 if (last_dirp) {
4836                         last_dirp[1] = '\0';
4837                 } else {
4838                         rel_name = talloc_strdup(ctx,"./");
4839                         if (!rel_name) {
4840                                 return NT_STATUS_NO_MEMORY;
4841                         }
4842                 }
4843                 rel_name = talloc_asprintf_append(rel_name,
4844                                 "%s",
4845                                 link_target);
4846                 if (!rel_name) {
4847                         return NT_STATUS_NO_MEMORY;
4848                 }
4849
4850                 status = check_name(conn, rel_name);
4851                 if (!NT_STATUS_IS_OK(status)) {
4852                         return status;
4853                 }
4854         }
4855
4856         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4857                         newname, link_target ));
4858
4859         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4860                 return map_nt_error_from_unix(errno);
4861         }
4862
4863         return NT_STATUS_OK;
4864 }
4865
4866 /****************************************************************************
4867  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4868 ****************************************************************************/
4869
4870 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4871                                         struct smb_request *req,
4872                                         const char *pdata, int total_data,
4873                                         const char *fname)
4874 {
4875         char *oldname = NULL;
4876         TALLOC_CTX *ctx = talloc_tos();
4877         NTSTATUS status = NT_STATUS_OK;
4878
4879         /* Set a hard link. */
4880         if (total_data == 0) {
4881                 return NT_STATUS_INVALID_PARAMETER;
4882         }
4883
4884         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4885                         total_data, STR_TERMINATE, &status);
4886         if (!NT_STATUS_IS_OK(status)) {
4887                 return status;
4888         }
4889
4890         status = resolve_dfspath(ctx, conn,
4891                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
4892                                 oldname,
4893                                 &oldname);
4894         if (!NT_STATUS_IS_OK(status)) {
4895                 return status;
4896         }
4897
4898         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4899                 fname, oldname));
4900
4901         return hardlink_internals(ctx, conn, oldname, fname);
4902 }
4903
4904 /****************************************************************************
4905  Deal with SMB_FILE_RENAME_INFORMATION.
4906 ****************************************************************************/
4907
4908 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4909                                             struct smb_request *req,
4910                                             const char *pdata,
4911                                             int total_data,
4912                                             files_struct *fsp,
4913                                             const char *fname)
4914 {
4915         bool overwrite;
4916         uint32 root_fid;
4917         uint32 len;
4918         char *newname = NULL;
4919         char *base_name = NULL;
4920         bool dest_has_wcard = False;
4921         NTSTATUS status = NT_STATUS_OK;
4922         char *p;
4923         TALLOC_CTX *ctx = talloc_tos();
4924
4925         if (total_data < 13) {
4926                 return NT_STATUS_INVALID_PARAMETER;
4927         }
4928
4929         overwrite = (CVAL(pdata,0) ? True : False);
4930         root_fid = IVAL(pdata,4);
4931         len = IVAL(pdata,8);
4932
4933         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4934                 return NT_STATUS_INVALID_PARAMETER;
4935         }
4936
4937         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4938                               len, 0, &status,
4939                               &dest_has_wcard);
4940         if (!NT_STATUS_IS_OK(status)) {
4941                 return status;
4942         }
4943
4944         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4945                                 newname));
4946
4947         status = resolve_dfspath_wcard(ctx, conn,
4948                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
4949                                        newname,
4950                                        &newname,
4951                                        &dest_has_wcard);
4952         if (!NT_STATUS_IS_OK(status)) {
4953                 return status;
4954         }
4955
4956         /* Check the new name has no '/' characters. */
4957         if (strchr_m(newname, '/')) {
4958                 return NT_STATUS_NOT_SUPPORTED;
4959         }
4960
4961         /* Create the base directory. */
4962         base_name = talloc_strdup(ctx, fname);
4963         if (!base_name) {
4964                 return NT_STATUS_NO_MEMORY;
4965         }
4966         p = strrchr_m(base_name, '/');
4967         if (p) {
4968                 p[1] = '\0';
4969         } else {
4970                 base_name = talloc_strdup(ctx, "./");
4971                 if (!base_name) {
4972                         return NT_STATUS_NO_MEMORY;
4973                 }
4974         }
4975         /* Append the new name. */
4976         base_name = talloc_asprintf_append(base_name,
4977                         "%s",
4978                         newname);
4979         if (!base_name) {
4980                 return NT_STATUS_NO_MEMORY;
4981         }
4982
4983         if (fsp) {
4984                 SMB_STRUCT_STAT sbuf;
4985                 char *newname_last_component = NULL;
4986
4987                 ZERO_STRUCT(sbuf);
4988
4989                 status = unix_convert(ctx, conn, newname, False,
4990                                         &newname,
4991                                         &newname_last_component,
4992                                         &sbuf);
4993
4994                 /* If an error we expect this to be
4995                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
4996
4997                 if (!NT_STATUS_IS_OK(status)
4998                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
4999                                         status)) {
5000                         return status;
5001                 }
5002
5003                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5004                         fsp->fnum, fsp->fsp_name, base_name ));
5005                 status = rename_internals_fsp(conn, fsp, base_name,
5006                                               newname_last_component, 0,
5007                                               overwrite);
5008         } else {
5009                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5010                         fname, base_name ));
5011                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5012                                           overwrite, False, dest_has_wcard);
5013         }
5014
5015         return status;
5016 }
5017
5018 /****************************************************************************
5019  Deal with SMB_SET_POSIX_ACL.
5020 ****************************************************************************/
5021
5022 #if defined(HAVE_POSIX_ACLS)
5023 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5024                                 const char *pdata,
5025                                 int total_data,
5026                                 files_struct *fsp,
5027                                 const char *fname,
5028                                 SMB_STRUCT_STAT *psbuf)
5029 {
5030         uint16 posix_acl_version;
5031         uint16 num_file_acls;
5032         uint16 num_def_acls;
5033         bool valid_file_acls = True;
5034         bool valid_def_acls = True;
5035
5036         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5037                 return NT_STATUS_INVALID_PARAMETER;
5038         }
5039         posix_acl_version = SVAL(pdata,0);
5040         num_file_acls = SVAL(pdata,2);
5041         num_def_acls = SVAL(pdata,4);
5042
5043         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5044                 valid_file_acls = False;
5045                 num_file_acls = 0;
5046         }
5047
5048         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5049                 valid_def_acls = False;
5050                 num_def_acls = 0;
5051         }
5052
5053         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5054                 return NT_STATUS_INVALID_PARAMETER;
5055         }
5056
5057         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5058                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5059                 return NT_STATUS_INVALID_PARAMETER;
5060         }
5061
5062         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5063                 fname ? fname : fsp->fsp_name,
5064                 (unsigned int)num_file_acls,
5065                 (unsigned int)num_def_acls));
5066
5067         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5068                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5069                 return map_nt_error_from_unix(errno);
5070         }
5071
5072         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5073                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5074                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5075                 return map_nt_error_from_unix(errno);
5076         }
5077         return NT_STATUS_OK;
5078 }
5079 #endif
5080
5081 /****************************************************************************
5082  Deal with SMB_SET_POSIX_LOCK.
5083 ****************************************************************************/
5084
5085 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5086                                 const uint8 *inbuf,
5087                                 int length,
5088                                 const char *pdata,
5089                                 int total_data,
5090                                 files_struct *fsp)
5091 {
5092         SMB_BIG_UINT count;
5093         SMB_BIG_UINT offset;
5094         uint32 lock_pid;
5095         bool blocking_lock = False;
5096         enum brl_type lock_type;
5097         NTSTATUS status = NT_STATUS_OK;
5098
5099         if (fsp == NULL || fsp->fh->fd == -1) {
5100                 return NT_STATUS_INVALID_HANDLE;
5101         }
5102
5103         if (total_data != POSIX_LOCK_DATA_SIZE) {
5104                 return NT_STATUS_INVALID_PARAMETER;
5105         }
5106
5107         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5108                 case POSIX_LOCK_TYPE_READ:
5109                         lock_type = READ_LOCK;
5110                         break;
5111                 case POSIX_LOCK_TYPE_WRITE:
5112                         /* Return the right POSIX-mappable error code for files opened read-only. */
5113                         if (!fsp->can_write) {
5114                                 return NT_STATUS_INVALID_HANDLE;
5115                         }
5116                         lock_type = WRITE_LOCK;
5117                         break;
5118                 case POSIX_LOCK_TYPE_UNLOCK:
5119                         lock_type = UNLOCK_LOCK;
5120                         break;
5121                 default:
5122                         return NT_STATUS_INVALID_PARAMETER;
5123         }
5124
5125         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5126                 blocking_lock = False;
5127         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5128                 blocking_lock = True;
5129         } else {
5130                 return NT_STATUS_INVALID_PARAMETER;
5131         }
5132
5133         if (!lp_blocking_locks(SNUM(conn))) { 
5134                 blocking_lock = False;
5135         }
5136
5137         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5138 #if defined(HAVE_LONGLONG)
5139         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5140                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5141         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5142                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5143 #else /* HAVE_LONGLONG */
5144         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5145         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5146 #endif /* HAVE_LONGLONG */
5147
5148         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5149                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5150                 fsp->fsp_name,
5151                 (unsigned int)lock_type,
5152                 (unsigned int)lock_pid,
5153                 (double)count,
5154                 (double)offset ));
5155
5156         if (lock_type == UNLOCK_LOCK) {
5157                 status = do_unlock(smbd_messaging_context(),
5158                                 fsp,
5159                                 lock_pid,
5160                                 count,
5161                                 offset,
5162                                 POSIX_LOCK);
5163         } else {
5164                 uint32 block_smbpid;
5165
5166                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5167                                                         fsp,
5168                                                         lock_pid,
5169                                                         count,
5170                                                         offset,
5171                                                         lock_type,
5172                                                         POSIX_LOCK,
5173                                                         blocking_lock,
5174                                                         &status,
5175                                                         &block_smbpid);
5176
5177                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5178                         /*
5179                          * A blocking lock was requested. Package up
5180                          * this smb into a queued request and push it
5181                          * onto the blocking lock queue.
5182                          */
5183                         if(push_blocking_lock_request(br_lck,
5184                                                 (char *)inbuf, length,
5185                                                 fsp,
5186                                                 -1, /* infinite timeout. */
5187                                                 0,
5188                                                 lock_pid,
5189                                                 lock_type,
5190                                                 POSIX_LOCK,
5191                                                 offset,
5192                                                 count,
5193                                                 block_smbpid)) {
5194                                 TALLOC_FREE(br_lck);
5195                                 return status;
5196                         }
5197                 }
5198                 TALLOC_FREE(br_lck);
5199         }
5200
5201         return status;
5202 }
5203
5204 /****************************************************************************
5205  Deal with SMB_INFO_STANDARD.
5206 ****************************************************************************/
5207
5208 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5209                                         const char *pdata,
5210                                         int total_data,
5211                                         files_struct *fsp,
5212                                         const char *fname,
5213                                         const SMB_STRUCT_STAT *psbuf)
5214 {
5215         struct timespec ts[2];
5216
5217         if (total_data < 12) {
5218                 return NT_STATUS_INVALID_PARAMETER;
5219         }
5220
5221         /* access time */
5222         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5223         /* write time */
5224         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5225
5226         DEBUG(10,("smb_set_info_standard: file %s\n",
5227                 fname ? fname : fsp->fsp_name ));
5228
5229         return smb_set_file_time(conn,
5230                                 fsp,
5231                                 fname,
5232                                 psbuf,
5233                                 ts,
5234                                 true);
5235 }
5236
5237 /****************************************************************************
5238  Deal with SMB_SET_FILE_BASIC_INFO.
5239 ****************************************************************************/
5240
5241 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5242                                         const char *pdata,
5243                                         int total_data,
5244                                         files_struct *fsp,
5245                                         const char *fname,
5246                                         SMB_STRUCT_STAT *psbuf)
5247 {
5248         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5249         struct timespec write_time;
5250         struct timespec changed_time;
5251         uint32 dosmode = 0;
5252         struct timespec ts[2];
5253         NTSTATUS status = NT_STATUS_OK;
5254         bool setting_write_time = true;
5255
5256         if (total_data < 36) {
5257                 return NT_STATUS_INVALID_PARAMETER;
5258         }
5259
5260         /* Set the attributes */
5261         dosmode = IVAL(pdata,32);
5262         status = smb_set_file_dosmode(conn,
5263                                         fname,
5264                                         psbuf,
5265                                         dosmode);
5266         if (!NT_STATUS_IS_OK(status)) {
5267                 return status;
5268         }
5269
5270         /* Ignore create time at offset pdata. */
5271
5272         /* access time */
5273         ts[0] = interpret_long_date(pdata+8);
5274
5275         write_time = interpret_long_date(pdata+16);
5276         changed_time = interpret_long_date(pdata+24);
5277
5278         /* mtime */
5279         ts[1] = timespec_min(&write_time, &changed_time);
5280
5281         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5282                 ts[1] = write_time;
5283         }
5284
5285         /* Prefer a defined time to an undefined one. */
5286         if (null_timespec(ts[1])) {
5287                 if (null_timespec(write_time)) {
5288                         ts[1] = changed_time;
5289                         setting_write_time = false;
5290                 } else {
5291                         ts[1] = write_time;
5292                 }
5293         }
5294
5295         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5296                 fname ? fname : fsp->fsp_name ));
5297
5298         return smb_set_file_time(conn,
5299                                 fsp,
5300                                 fname,
5301                                 psbuf,
5302                                 ts,
5303                                 setting_write_time);
5304 }
5305
5306 /****************************************************************************
5307  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5308 ****************************************************************************/
5309
5310 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5311                                              struct smb_request *req,
5312                                         const char *pdata,
5313                                         int total_data,
5314                                         files_struct *fsp,
5315                                         const char *fname,
5316                                         SMB_STRUCT_STAT *psbuf)
5317 {
5318         SMB_BIG_UINT allocation_size = 0;
5319         NTSTATUS status = NT_STATUS_OK;
5320         files_struct *new_fsp = NULL;
5321
5322         if (!VALID_STAT(*psbuf)) {
5323                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5324         }
5325
5326         if (total_data < 8) {
5327                 return NT_STATUS_INVALID_PARAMETER;
5328         }
5329
5330         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5331 #ifdef LARGE_SMB_OFF_T
5332         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5333 #else /* LARGE_SMB_OFF_T */
5334         if (IVAL(pdata,4) != 0) {
5335                 /* more than 32 bits? */
5336                 return NT_STATUS_INVALID_PARAMETER;
5337         }
5338 #endif /* LARGE_SMB_OFF_T */
5339
5340         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5341                         fname, (double)allocation_size ));
5342
5343         if (allocation_size) {
5344                 allocation_size = smb_roundup(conn, allocation_size);
5345         }
5346
5347         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5348                         fname, (double)allocation_size ));
5349
5350         if (fsp && fsp->fh->fd != -1) {
5351                 /* Open file handle. */
5352                 /* Only change if needed. */
5353                 if (allocation_size != get_file_size(*psbuf)) {
5354                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5355                                 return map_nt_error_from_unix(errno);
5356                         }
5357                 }
5358                 /* But always update the time. */
5359                 if (null_timespec(fsp->pending_modtime)) {
5360                         /*
5361                          * This is equivalent to a write. Ensure it's seen immediately
5362                          * if there are no pending writes.
5363                          */
5364                         set_filetime(fsp->conn, fsp->fsp_name,
5365                                         timespec_current());
5366                 }
5367                 return NT_STATUS_OK;
5368         }
5369
5370         /* Pathname or stat or directory file. */
5371
5372         status = open_file_ntcreate(conn, req, fname, psbuf,
5373                                 FILE_WRITE_DATA,
5374                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5375                                 FILE_OPEN,
5376                                 0,
5377                                 FILE_ATTRIBUTE_NORMAL,
5378                                 FORCE_OPLOCK_BREAK_TO_NONE,
5379                                 NULL, &new_fsp);
5380
5381         if (!NT_STATUS_IS_OK(status)) {
5382                 /* NB. We check for open_was_deferred in the caller. */
5383                 return status;
5384         }
5385
5386         /* Only change if needed. */
5387         if (allocation_size != get_file_size(*psbuf)) {
5388                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5389                         status = map_nt_error_from_unix(errno);
5390                         close_file(new_fsp,NORMAL_CLOSE);
5391                         return status;
5392                 }
5393         }
5394
5395         /* Changing the allocation size should set the last mod time. */
5396         /* Don't need to call set_filetime as this will be flushed on
5397          * close. */
5398
5399         fsp_set_pending_modtime(new_fsp, timespec_current());
5400
5401         close_file(new_fsp,NORMAL_CLOSE);
5402         return NT_STATUS_OK;
5403 }
5404
5405 /****************************************************************************
5406  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5407 ****************************************************************************/
5408
5409 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5410                                               struct smb_request *req,
5411                                         const char *pdata,
5412                                         int total_data,
5413                                         files_struct *fsp,
5414                                         const char *fname,
5415                                         SMB_STRUCT_STAT *psbuf)
5416 {
5417         SMB_OFF_T size;
5418
5419         if (total_data < 8) {
5420                 return NT_STATUS_INVALID_PARAMETER;
5421         }
5422
5423         size = IVAL(pdata,0);
5424 #ifdef LARGE_SMB_OFF_T
5425         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5426 #else /* LARGE_SMB_OFF_T */
5427         if (IVAL(pdata,4) != 0) {
5428                 /* more than 32 bits? */
5429                 return NT_STATUS_INVALID_PARAMETER;
5430         }
5431 #endif /* LARGE_SMB_OFF_T */
5432         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5433                 "file %s to %.0f\n", fname, (double)size ));
5434
5435         return smb_set_file_size(conn, req,
5436                                 fsp,
5437                                 fname,
5438                                 psbuf,
5439                                 size);
5440 }
5441
5442 /****************************************************************************
5443  Allow a UNIX info mknod.
5444 ****************************************************************************/
5445
5446 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5447                                         const char *pdata,
5448                                         int total_data,
5449                                         const char *fname,
5450                                         SMB_STRUCT_STAT *psbuf)
5451 {
5452         uint32 file_type = IVAL(pdata,56);
5453 #if defined(HAVE_MAKEDEV)
5454         uint32 dev_major = IVAL(pdata,60);
5455         uint32 dev_minor = IVAL(pdata,68);
5456 #endif
5457         SMB_DEV_T dev = (SMB_DEV_T)0;
5458         uint32 raw_unixmode = IVAL(pdata,84);
5459         NTSTATUS status;
5460         mode_t unixmode;
5461
5462         if (total_data < 100) {
5463                 return NT_STATUS_INVALID_PARAMETER;
5464         }
5465
5466         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5467         if (!NT_STATUS_IS_OK(status)) {
5468                 return status;
5469         }
5470
5471 #if defined(HAVE_MAKEDEV)
5472         dev = makedev(dev_major, dev_minor);
5473 #endif
5474
5475         switch (file_type) {
5476 #if defined(S_IFIFO)
5477                 case UNIX_TYPE_FIFO:
5478                         unixmode |= S_IFIFO;
5479                         break;
5480 #endif
5481 #if defined(S_IFSOCK)
5482                 case UNIX_TYPE_SOCKET:
5483                         unixmode |= S_IFSOCK;
5484                         break;
5485 #endif
5486 #if defined(S_IFCHR)
5487                 case UNIX_TYPE_CHARDEV:
5488                         unixmode |= S_IFCHR;
5489                         break;
5490 #endif
5491 #if defined(S_IFBLK)
5492                 case UNIX_TYPE_BLKDEV:
5493                         unixmode |= S_IFBLK;
5494                         break;
5495 #endif
5496                 default:
5497                         return NT_STATUS_INVALID_PARAMETER;
5498         }
5499
5500         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5501 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5502
5503         /* Ok - do the mknod. */
5504         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5505                 return map_nt_error_from_unix(errno);
5506         }
5507
5508         /* If any of the other "set" calls fail we
5509          * don't want to end up with a half-constructed mknod.
5510          */
5511
5512         if (lp_inherit_perms(SNUM(conn))) {
5513                 inherit_access_acl(
5514                         conn, parent_dirname(fname),
5515                         fname, unixmode);
5516         }
5517
5518         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5519                 status = map_nt_error_from_unix(errno);
5520                 SMB_VFS_UNLINK(conn,fname);
5521                 return status;
5522         }
5523         return NT_STATUS_OK;
5524 }
5525
5526 /****************************************************************************
5527  Deal with SMB_SET_FILE_UNIX_BASIC.
5528 ****************************************************************************/
5529
5530 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5531                                         struct smb_request *req,
5532                                         const char *pdata,
5533                                         int total_data,
5534                                         files_struct *fsp,
5535                                         const char *fname,
5536                                         SMB_STRUCT_STAT *psbuf)
5537 {
5538         struct timespec ts[2];
5539         uint32 raw_unixmode;
5540         mode_t unixmode;
5541         SMB_OFF_T size = 0;
5542         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5543         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5544         NTSTATUS status = NT_STATUS_OK;
5545         bool delete_on_fail = False;
5546         enum perm_type ptype;
5547
5548         if (total_data < 100) {
5549                 return NT_STATUS_INVALID_PARAMETER;
5550         }
5551
5552         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5553            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5554                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5555 #ifdef LARGE_SMB_OFF_T
5556                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5557 #else /* LARGE_SMB_OFF_T */
5558                 if (IVAL(pdata,4) != 0) {
5559                         /* more than 32 bits? */
5560                         return NT_STATUS_INVALID_PARAMETER;
5561                 }
5562 #endif /* LARGE_SMB_OFF_T */
5563         }
5564
5565         ts[0] = interpret_long_date(pdata+24); /* access_time */
5566         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5567         set_owner = (uid_t)IVAL(pdata,40);
5568         set_grp = (gid_t)IVAL(pdata,48);
5569         raw_unixmode = IVAL(pdata,84);
5570
5571         if (VALID_STAT(*psbuf)) {
5572                 if (S_ISDIR(psbuf->st_mode)) {
5573                         ptype = PERM_EXISTING_DIR;
5574                 } else {
5575                         ptype = PERM_EXISTING_FILE;
5576                 }
5577         } else {
5578                 ptype = PERM_NEW_FILE;
5579         }
5580
5581         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5582         if (!NT_STATUS_IS_OK(status)) {
5583                 return status;
5584         }
5585
5586         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5587 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5588                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5589
5590         if (!VALID_STAT(*psbuf)) {
5591                 /*
5592                  * The only valid use of this is to create character and block
5593                  * devices, and named pipes. This is deprecated (IMHO) and 
5594                  * a new info level should be used for mknod. JRA.
5595                  */
5596
5597                 status = smb_unix_mknod(conn,
5598                                         pdata,
5599                                         total_data,
5600                                         fname,
5601                                         psbuf);
5602                 if (!NT_STATUS_IS_OK(status)) {
5603                         return status;
5604                 }
5605
5606                 /* Ensure we don't try and change anything else. */
5607                 raw_unixmode = SMB_MODE_NO_CHANGE;
5608                 size = get_file_size(*psbuf);
5609                 ts[0] = get_atimespec(psbuf);
5610                 ts[1] = get_mtimespec(psbuf);
5611                 /* 
5612                  * We continue here as we might want to change the 
5613                  * owner uid/gid.
5614                  */
5615                 delete_on_fail = True;
5616         }
5617
5618 #if 1
5619         /* Horrible backwards compatibility hack as an old server bug
5620          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5621          * */
5622
5623         if (!size) {
5624                 size = get_file_size(*psbuf);
5625         }
5626 #endif
5627
5628         /*
5629          * Deal with the UNIX specific mode set.
5630          */
5631
5632         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5633                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5634                         (unsigned int)unixmode, fname ));
5635                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5636                         return map_nt_error_from_unix(errno);
5637                 }
5638         }
5639
5640         /*
5641          * Deal with the UNIX specific uid set.
5642          */
5643
5644         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5645                 int ret;
5646
5647                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5648                         (unsigned int)set_owner, fname ));
5649
5650                 if (S_ISLNK(psbuf->st_mode)) {
5651                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5652                 } else {
5653                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5654                 }
5655
5656                 if (ret != 0) {
5657                         status = map_nt_error_from_unix(errno);
5658                         if (delete_on_fail) {
5659                                 SMB_VFS_UNLINK(conn,fname);
5660                         }
5661                         return status;
5662                 }
5663         }
5664
5665         /*
5666          * Deal with the UNIX specific gid set.
5667          */
5668
5669         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5670                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5671                         (unsigned int)set_owner, fname ));
5672                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5673                         status = map_nt_error_from_unix(errno);
5674                         if (delete_on_fail) {
5675                                 SMB_VFS_UNLINK(conn,fname);
5676                         }
5677                         return status;
5678                 }
5679         }
5680
5681         /* Deal with any size changes. */
5682
5683         status = smb_set_file_size(conn, req,
5684                                 fsp,
5685                                 fname,
5686                                 psbuf,
5687                                 size);
5688         if (!NT_STATUS_IS_OK(status)) {
5689                 return status;
5690         }
5691
5692         /* Deal with any time changes. */
5693
5694         return smb_set_file_time(conn,
5695                                 fsp,
5696                                 fname,
5697                                 psbuf,
5698                                 ts,
5699                                 true);
5700 }
5701
5702 /****************************************************************************
5703  Deal with SMB_SET_FILE_UNIX_INFO2.
5704 ****************************************************************************/
5705
5706 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5707                                         struct smb_request *req,
5708                                         const char *pdata,
5709                                         int total_data,
5710                                         files_struct *fsp,
5711                                         const char *fname,
5712                                         SMB_STRUCT_STAT *psbuf)
5713 {
5714         NTSTATUS status;
5715         uint32 smb_fflags;
5716         uint32 smb_fmask;
5717
5718         if (total_data < 116) {
5719                 return NT_STATUS_INVALID_PARAMETER;
5720         }
5721
5722         /* Start by setting all the fields that are common between UNIX_BASIC
5723          * and UNIX_INFO2.
5724          */
5725         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5726                                 fsp, fname, psbuf);
5727         if (!NT_STATUS_IS_OK(status)) {
5728                 return status;
5729         }
5730
5731         smb_fflags = IVAL(pdata, 108);
5732         smb_fmask = IVAL(pdata, 112);
5733
5734         /* NB: We should only attempt to alter the file flags if the client
5735          * sends a non-zero mask.
5736          */
5737         if (smb_fmask != 0) {
5738                 int stat_fflags = 0;
5739
5740                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5741                             &stat_fflags)) {
5742                         /* Client asked to alter a flag we don't understand. */
5743                         return NT_STATUS_INVALID_PARAMETER;
5744                 }
5745
5746                 if (fsp && fsp->fh->fd != -1) {
5747                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5748                         return NT_STATUS_NOT_SUPPORTED;
5749                 } else {
5750                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5751                                 return map_nt_error_from_unix(errno);
5752                         }
5753                 }
5754         }
5755
5756         /* XXX: need to add support for changing the create_time here. You
5757          * can do this for paths on Darwin with setattrlist(2). The right way
5758          * to hook this up is probably by extending the VFS utimes interface.
5759          */
5760
5761         return NT_STATUS_OK;
5762 }
5763
5764 /****************************************************************************
5765  Create a directory with POSIX semantics.
5766 ****************************************************************************/
5767
5768 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5769                                 struct smb_request *req,
5770                                 char **ppdata,
5771                                 int total_data,
5772                                 const char *fname,
5773                                 SMB_STRUCT_STAT *psbuf,
5774                                 int *pdata_return_size)
5775 {
5776         NTSTATUS status = NT_STATUS_OK;
5777         uint32 raw_unixmode = 0;
5778         uint32 mod_unixmode = 0;
5779         mode_t unixmode = (mode_t)0;
5780         files_struct *fsp = NULL;
5781         uint16 info_level_return = 0;
5782         int info;
5783         char *pdata = *ppdata;
5784
5785         if (total_data < 18) {
5786                 return NT_STATUS_INVALID_PARAMETER;
5787         }
5788
5789         raw_unixmode = IVAL(pdata,8);
5790         /* Next 4 bytes are not yet defined. */
5791
5792         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5793         if (!NT_STATUS_IS_OK(status)) {
5794                 return status;
5795         }
5796
5797         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5798
5799         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5800                 fname, (unsigned int)unixmode ));
5801
5802         status = open_directory(conn, req,
5803                                 fname,
5804                                 psbuf,
5805                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5806                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5807                                 FILE_CREATE,
5808                                 0,
5809                                 mod_unixmode,
5810                                 &info,
5811                                 &fsp);
5812
5813         if (NT_STATUS_IS_OK(status)) {
5814                 close_file(fsp, NORMAL_CLOSE);
5815         }
5816
5817         info_level_return = SVAL(pdata,16);
5818  
5819         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5820                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5821         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5822                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5823         } else {
5824                 *pdata_return_size = 12;
5825         }
5826
5827         /* Realloc the data size */
5828         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5829         if (*ppdata == NULL) {
5830                 *pdata_return_size = 0;
5831                 return NT_STATUS_NO_MEMORY;
5832         }
5833         pdata = *ppdata;
5834
5835         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5836         SSVAL(pdata,2,0); /* No fnum. */
5837         SIVAL(pdata,4,info); /* Was directory created. */
5838
5839         switch (info_level_return) {
5840                 case SMB_QUERY_FILE_UNIX_BASIC:
5841                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5842                         SSVAL(pdata,10,0); /* Padding. */
5843                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5844                         break;
5845                 case SMB_QUERY_FILE_UNIX_INFO2:
5846                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5847                         SSVAL(pdata,10,0); /* Padding. */
5848                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5849                         break;
5850                 default:
5851                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5852                         SSVAL(pdata,10,0); /* Padding. */
5853                         break;
5854         }
5855
5856         return status;
5857 }
5858
5859 /****************************************************************************
5860  Open/Create a file with POSIX semantics.
5861 ****************************************************************************/
5862
5863 static NTSTATUS smb_posix_open(connection_struct *conn,
5864                                struct smb_request *req,
5865                                 char **ppdata,
5866                                 int total_data,
5867                                 const char *fname,
5868                                 SMB_STRUCT_STAT *psbuf,
5869                                 int *pdata_return_size)
5870 {
5871         bool extended_oplock_granted = False;
5872         char *pdata = *ppdata;
5873         uint32 flags = 0;
5874         uint32 wire_open_mode = 0;
5875         uint32 raw_unixmode = 0;
5876         uint32 mod_unixmode = 0;
5877         uint32 create_disp = 0;
5878         uint32 access_mask = 0;
5879         uint32 create_options = 0;
5880         NTSTATUS status = NT_STATUS_OK;
5881         mode_t unixmode = (mode_t)0;
5882         files_struct *fsp = NULL;
5883         int oplock_request = 0;
5884         int info = 0;
5885         uint16 info_level_return = 0;
5886
5887         if (total_data < 18) {
5888                 return NT_STATUS_INVALID_PARAMETER;
5889         }
5890
5891         flags = IVAL(pdata,0);
5892         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5893         if (oplock_request) {
5894                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5895         }
5896
5897         wire_open_mode = IVAL(pdata,4);
5898
5899         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5900                 return smb_posix_mkdir(conn, req,
5901                                         ppdata,
5902                                         total_data,
5903                                         fname,
5904                                         psbuf,
5905                                         pdata_return_size);
5906         }
5907
5908         switch (wire_open_mode & SMB_ACCMODE) {
5909                 case SMB_O_RDONLY:
5910                         access_mask = FILE_READ_DATA;
5911                         break;
5912                 case SMB_O_WRONLY:
5913                         access_mask = FILE_WRITE_DATA;
5914                         break;
5915                 case SMB_O_RDWR:
5916                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5917                         break;
5918                 default:
5919                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5920                                 (unsigned int)wire_open_mode ));
5921                         return NT_STATUS_INVALID_PARAMETER;
5922         }
5923
5924         wire_open_mode &= ~SMB_ACCMODE;
5925
5926         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5927                 create_disp = FILE_CREATE;
5928         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5929                 create_disp = FILE_OVERWRITE_IF;
5930         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5931                 create_disp = FILE_OPEN_IF;
5932         } else {
5933                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5934                         (unsigned int)wire_open_mode ));
5935                 return NT_STATUS_INVALID_PARAMETER;
5936         }
5937
5938         raw_unixmode = IVAL(pdata,8);
5939         /* Next 4 bytes are not yet defined. */
5940
5941         status = unix_perms_from_wire(conn,
5942                                 psbuf,
5943                                 raw_unixmode,
5944                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5945                                 &unixmode);
5946
5947         if (!NT_STATUS_IS_OK(status)) {
5948                 return status;
5949         }
5950
5951         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5952
5953         if (wire_open_mode & SMB_O_SYNC) {
5954                 create_options |= FILE_WRITE_THROUGH;
5955         }
5956         if (wire_open_mode & SMB_O_APPEND) {
5957                 access_mask |= FILE_APPEND_DATA;
5958         }
5959         if (wire_open_mode & SMB_O_DIRECT) {
5960                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5961         }
5962
5963         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5964                 fname,
5965                 (unsigned int)wire_open_mode,
5966                 (unsigned int)unixmode ));
5967
5968         status = open_file_ntcreate(conn, req,
5969                                 fname,
5970                                 psbuf,
5971                                 access_mask,
5972                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5973                                 create_disp,
5974                                 0,              /* no create options yet. */
5975                                 mod_unixmode,
5976                                 oplock_request,
5977                                 &info,
5978                                 &fsp);
5979
5980         if (!NT_STATUS_IS_OK(status)) {
5981                 return status;
5982         }
5983
5984         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5985                 extended_oplock_granted = True;
5986         }
5987
5988         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5989                 extended_oplock_granted = True;
5990         }
5991
5992         info_level_return = SVAL(pdata,16);
5993  
5994         /* Allocate the correct return size. */
5995
5996         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5997                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5998         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5999                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6000         } else {
6001                 *pdata_return_size = 12;
6002         }
6003
6004         /* Realloc the data size */
6005         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6006         if (*ppdata == NULL) {
6007                 close_file(fsp,ERROR_CLOSE);
6008                 *pdata_return_size = 0;
6009                 return NT_STATUS_NO_MEMORY;
6010         }
6011         pdata = *ppdata;
6012
6013         if (extended_oplock_granted) {
6014                 if (flags & REQUEST_BATCH_OPLOCK) {
6015                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6016                 } else {
6017                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6018                 }
6019         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6020                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6021         } else {
6022                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6023         }
6024
6025         SSVAL(pdata,2,fsp->fnum);
6026         SIVAL(pdata,4,info); /* Was file created etc. */
6027
6028         switch (info_level_return) {
6029                 case SMB_QUERY_FILE_UNIX_BASIC:
6030                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6031                         SSVAL(pdata,10,0); /* padding. */
6032                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6033                         break;
6034                 case SMB_QUERY_FILE_UNIX_INFO2:
6035                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6036                         SSVAL(pdata,10,0); /* padding. */
6037                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6038                         break;
6039                 default:
6040                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6041                         SSVAL(pdata,10,0); /* padding. */
6042                         break;
6043         }
6044         return NT_STATUS_OK;
6045 }
6046
6047 /****************************************************************************
6048  Delete a file with POSIX semantics.
6049 ****************************************************************************/
6050
6051 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6052                                  struct smb_request *req,
6053                                 const char *pdata,
6054                                 int total_data,
6055                                 const char *fname,
6056                                 SMB_STRUCT_STAT *psbuf)
6057 {
6058         NTSTATUS status = NT_STATUS_OK;
6059         files_struct *fsp = NULL;
6060         uint16 flags = 0;
6061         char del = 1;
6062         int info = 0;
6063         int i;
6064         struct share_mode_lock *lck = NULL;
6065
6066         if (total_data < 2) {
6067                 return NT_STATUS_INVALID_PARAMETER;
6068         }
6069
6070         flags = SVAL(pdata,0);
6071
6072         if (!VALID_STAT(*psbuf)) {
6073                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6074         }
6075
6076         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6077                         !VALID_STAT_OF_DIR(*psbuf)) {
6078                 return NT_STATUS_NOT_A_DIRECTORY;
6079         }
6080
6081         DEBUG(10,("smb_posix_unlink: %s %s\n",
6082                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6083                 fname));
6084
6085         if (VALID_STAT_OF_DIR(*psbuf)) {
6086                 status = open_directory(conn, req,
6087                                         fname,
6088                                         psbuf,
6089                                         DELETE_ACCESS,
6090                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6091                                         FILE_OPEN,
6092                                         0,
6093                                         FILE_FLAG_POSIX_SEMANTICS|0777,
6094                                         &info,
6095                                         &fsp);
6096         } else {
6097
6098                 status = open_file_ntcreate(conn, req,
6099                                 fname,
6100                                 psbuf,
6101                                 DELETE_ACCESS,
6102                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6103                                 FILE_OPEN,
6104                                 0,
6105                                 FILE_FLAG_POSIX_SEMANTICS|0777,
6106                                 0, /* No oplock, but break existing ones. */
6107                                 &info,
6108                                 &fsp);
6109         }
6110
6111         if (!NT_STATUS_IS_OK(status)) {
6112                 return status;
6113         }
6114
6115         /*
6116          * Don't lie to client. If we can't really delete due to
6117          * non-POSIX opens return SHARING_VIOLATION.
6118          */
6119
6120         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6121         if (lck == NULL) {
6122                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6123                         "lock for file %s\n", fsp->fsp_name));
6124                 close_file(fsp, NORMAL_CLOSE);
6125                 return NT_STATUS_INVALID_PARAMETER;
6126         }
6127
6128         /*
6129          * See if others still have the file open. If this is the case, then
6130          * don't delete. If all opens are POSIX delete we can set the delete
6131          * on close disposition.
6132          */
6133         for (i=0; i<lck->num_share_modes; i++) {
6134                 struct share_mode_entry *e = &lck->share_modes[i];
6135                 if (is_valid_share_mode_entry(e)) {
6136                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6137                                 continue;
6138                         }
6139                         /* Fail with sharing violation. */
6140                         close_file(fsp, NORMAL_CLOSE);
6141                         TALLOC_FREE(lck);
6142                         return NT_STATUS_SHARING_VIOLATION;
6143                 }
6144         }
6145
6146         /*
6147          * Set the delete on close.
6148          */
6149         status = smb_set_file_disposition_info(conn,
6150                                                 &del,
6151                                                 1,
6152                                                 fsp,
6153                                                 fname,
6154                                                 psbuf);
6155
6156         if (!NT_STATUS_IS_OK(status)) {
6157                 close_file(fsp, NORMAL_CLOSE);
6158                 TALLOC_FREE(lck);
6159                 return status;
6160         }
6161         TALLOC_FREE(lck);
6162         return close_file(fsp, NORMAL_CLOSE);
6163 }
6164
6165 /****************************************************************************
6166  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6167 ****************************************************************************/
6168
6169 static void call_trans2setfilepathinfo(connection_struct *conn,
6170                                        struct smb_request *req,
6171                                        unsigned int tran_call,
6172                                        char **pparams, int total_params,
6173                                        char **ppdata, int total_data,
6174                                        unsigned int max_data_bytes)
6175 {
6176         char *params = *pparams;
6177         char *pdata = *ppdata;
6178         uint16 info_level;
6179         SMB_STRUCT_STAT sbuf;
6180         char *fname = NULL;
6181         files_struct *fsp = NULL;
6182         NTSTATUS status = NT_STATUS_OK;
6183         int data_return_size = 0;
6184         TALLOC_CTX *ctx = talloc_tos();
6185
6186         if (!params) {
6187                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6188                 return;
6189         }
6190
6191         ZERO_STRUCT(sbuf);
6192
6193         if (tran_call == TRANSACT2_SETFILEINFO) {
6194                 if (total_params < 4) {
6195                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6196                         return;
6197                 }
6198
6199                 fsp = file_fsp(SVAL(params,0));
6200                 /* Basic check for non-null fsp. */
6201                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6202                         return;
6203                 }
6204                 info_level = SVAL(params,2);
6205
6206                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6207                 if (!fname) {
6208                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6209                         return;
6210                 }
6211
6212                 if(fsp->is_directory || fsp->fh->fd == -1) {
6213                         /*
6214                          * This is actually a SETFILEINFO on a directory
6215                          * handle (returned from an NT SMB). NT5.0 seems
6216                          * to do this call. JRA.
6217                          */
6218                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6219                                 /* Always do lstat for UNIX calls. */
6220                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6221                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6222                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6223                                         return;
6224                                 }
6225                         } else {
6226                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6227                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6228                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6229                                         return;
6230                                 }
6231                         }
6232                 } else if (fsp->print_file) {
6233                         /*
6234                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6235                          */
6236                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6237                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6238
6239                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6240
6241                                 SSVAL(params,0,0);
6242                                 send_trans2_replies(req, params, 2,
6243                                                     *ppdata, 0,
6244                                                     max_data_bytes);
6245                                 return;
6246                         } else {
6247                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6248                                 return;
6249                         }
6250                 } else {
6251                         /*
6252                          * Original code - this is an open file.
6253                          */
6254                         if (!check_fsp(conn, req, fsp, &current_user)) {
6255                                 return;
6256                         }
6257
6258                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6259                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6260                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6261                                 return;
6262                         }
6263                 }
6264         } else {
6265                 /* set path info */
6266                 if (total_params < 7) {
6267                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6268                         return;
6269                 }
6270
6271                 info_level = SVAL(params,0);
6272                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6273                                 total_params - 6, STR_TERMINATE,
6274                                 &status);
6275                 if (!NT_STATUS_IS_OK(status)) {
6276                         reply_nterror(req, status);
6277                         return;
6278                 }
6279
6280                 status = resolve_dfspath(ctx, conn,
6281                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6282                                          fname,
6283                                          &fname);
6284                 if (!NT_STATUS_IS_OK(status)) {
6285                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6286                                 reply_botherror(req,
6287                                                 NT_STATUS_PATH_NOT_COVERED,
6288                                                 ERRSRV, ERRbadpath);
6289                                 return;
6290                         }
6291                         reply_nterror(req, status);
6292                         return;
6293                 }
6294
6295                 status = unix_convert(ctx, conn, fname, False,
6296                                 &fname, NULL, &sbuf);
6297                 if (!NT_STATUS_IS_OK(status)) {
6298                         reply_nterror(req, status);
6299                         return;
6300                 }
6301
6302                 status = check_name(conn, fname);
6303                 if (!NT_STATUS_IS_OK(status)) {
6304                         reply_nterror(req, status);
6305                         return;
6306                 }
6307
6308                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6309                         /*
6310                          * For CIFS UNIX extensions the target name may not exist.
6311                          */
6312
6313                         /* Always do lstat for UNIX calls. */
6314                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6315
6316                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6317                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6318                         reply_unixerror(req, ERRDOS, ERRbadpath);
6319                         return;
6320                 }
6321         }
6322
6323         if (!CAN_WRITE(conn)) {
6324                 reply_doserror(req, ERRSRV, ERRaccess);
6325                 return;
6326         }
6327
6328         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6329                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6330                 return;
6331         }
6332
6333         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6334                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6335
6336         /* Realloc the parameter size */
6337         *pparams = (char *)SMB_REALLOC(*pparams,2);
6338         if (*pparams == NULL) {
6339                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6340                 return;
6341         }
6342         params = *pparams;
6343
6344         SSVAL(params,0,0);
6345
6346         if (fsp && !null_timespec(fsp->pending_modtime)) {
6347                 /* the pending modtime overrides the current modtime */
6348                 set_mtimespec(&sbuf, fsp->pending_modtime);
6349         }
6350
6351         switch (info_level) {
6352
6353                 case SMB_INFO_STANDARD:
6354                 {
6355                         status = smb_set_info_standard(conn,
6356                                         pdata,
6357                                         total_data,
6358                                         fsp,
6359                                         fname,
6360                                         &sbuf);
6361                         break;
6362                 }
6363
6364                 case SMB_INFO_SET_EA:
6365                 {
6366                         status = smb_info_set_ea(conn,
6367                                                 pdata,
6368                                                 total_data,
6369                                                 fsp,
6370                                                 fname);
6371                         break;
6372                 }
6373
6374                 case SMB_SET_FILE_BASIC_INFO:
6375                 case SMB_FILE_BASIC_INFORMATION:
6376                 {
6377                         status = smb_set_file_basic_info(conn,
6378                                                         pdata,
6379                                                         total_data,
6380                                                         fsp,
6381                                                         fname,
6382                                                         &sbuf);
6383                         break;
6384                 }
6385
6386                 case SMB_FILE_ALLOCATION_INFORMATION:
6387                 case SMB_SET_FILE_ALLOCATION_INFO:
6388                 {
6389                         status = smb_set_file_allocation_info(conn, req,
6390                                                                 pdata,
6391                                                                 total_data,
6392                                                                 fsp,
6393                                                                 fname,
6394                                                                 &sbuf);
6395                         break;
6396                 }
6397
6398                 case SMB_FILE_END_OF_FILE_INFORMATION:
6399                 case SMB_SET_FILE_END_OF_FILE_INFO:
6400                 {
6401                         status = smb_set_file_end_of_file_info(conn, req,
6402                                                                 pdata,
6403                                                                 total_data,
6404                                                                 fsp,
6405                                                                 fname,
6406                                                                 &sbuf);
6407                         break;
6408                 }
6409
6410                 case SMB_FILE_DISPOSITION_INFORMATION:
6411                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6412                 {
6413 #if 0
6414                         /* JRA - We used to just ignore this on a path ? 
6415                          * Shouldn't this be invalid level on a pathname
6416                          * based call ?
6417                          */
6418                         if (tran_call != TRANSACT2_SETFILEINFO) {
6419                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6420                         }
6421 #endif
6422                         status = smb_set_file_disposition_info(conn,
6423                                                 pdata,
6424                                                 total_data,
6425                                                 fsp,
6426                                                 fname,
6427                                                 &sbuf);
6428                         break;
6429                 }
6430
6431                 case SMB_FILE_POSITION_INFORMATION:
6432                 {
6433                         status = smb_file_position_information(conn,
6434                                                 pdata,
6435                                                 total_data,
6436                                                 fsp);
6437                         break;
6438                 }
6439
6440                 /* From tridge Samba4 : 
6441                  * MODE_INFORMATION in setfileinfo (I have no
6442                  * idea what "mode information" on a file is - it takes a value of 0,
6443                  * 2, 4 or 6. What could it be?).
6444                  */
6445
6446                 case SMB_FILE_MODE_INFORMATION:
6447                 {
6448                         status = smb_file_mode_information(conn,
6449                                                 pdata,
6450                                                 total_data);
6451                         break;
6452                 }
6453
6454                 /*
6455                  * CIFS UNIX extensions.
6456                  */
6457
6458                 case SMB_SET_FILE_UNIX_BASIC:
6459                 {
6460                         status = smb_set_file_unix_basic(conn, req,
6461                                                         pdata,
6462                                                         total_data,
6463                                                         fsp,
6464                                                         fname,
6465                                                         &sbuf);
6466                         break;
6467                 }
6468
6469                 case SMB_SET_FILE_UNIX_INFO2:
6470                 {
6471                         status = smb_set_file_unix_info2(conn, req,
6472                                                         pdata,
6473                                                         total_data,
6474                                                         fsp,
6475                                                         fname,
6476                                                         &sbuf);
6477                         break;
6478                 }
6479
6480                 case SMB_SET_FILE_UNIX_LINK:
6481                 {
6482                         if (tran_call != TRANSACT2_SETPATHINFO) {
6483                                 /* We must have a pathname for this. */
6484                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6485                                 return;
6486                         }
6487                         status = smb_set_file_unix_link(conn, req, pdata,
6488                                                         total_data, fname);
6489                         break;
6490                 }
6491
6492                 case SMB_SET_FILE_UNIX_HLINK:
6493                 {
6494                         if (tran_call != TRANSACT2_SETPATHINFO) {
6495                                 /* We must have a pathname for this. */
6496                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6497                                 return;
6498                         }
6499                         status = smb_set_file_unix_hlink(conn, req,
6500                                                          pdata, total_data,
6501                                                          fname);
6502                         break;
6503                 }
6504
6505                 case SMB_FILE_RENAME_INFORMATION:
6506                 {
6507                         status = smb_file_rename_information(conn, req,
6508                                                              pdata, total_data,
6509                                                              fsp, fname);
6510                         break;
6511                 }
6512
6513 #if defined(HAVE_POSIX_ACLS)
6514                 case SMB_SET_POSIX_ACL:
6515                 {
6516                         status = smb_set_posix_acl(conn,
6517                                                 pdata,
6518                                                 total_data,
6519                                                 fsp,
6520                                                 fname,
6521                                                 &sbuf);
6522                         break;
6523                 }
6524 #endif
6525
6526                 case SMB_SET_POSIX_LOCK:
6527                 {
6528                         if (tran_call != TRANSACT2_SETFILEINFO) {
6529                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6530                                 return;
6531                         }
6532                         status = smb_set_posix_lock(conn, req->inbuf,
6533                                                     smb_len(req->inbuf) + 4,
6534                                                     pdata, total_data, fsp);
6535                         break;
6536                 }
6537
6538                 case SMB_POSIX_PATH_OPEN:
6539                 {
6540                         if (tran_call != TRANSACT2_SETPATHINFO) {
6541                                 /* We must have a pathname for this. */
6542                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6543                                 return;
6544                         }
6545
6546                         status = smb_posix_open(conn, req,
6547                                                 ppdata,
6548                                                 total_data,
6549                                                 fname,
6550                                                 &sbuf,
6551                                                 &data_return_size);
6552                         break;
6553                 }
6554
6555                 case SMB_POSIX_PATH_UNLINK:
6556                 {
6557                         if (tran_call != TRANSACT2_SETPATHINFO) {
6558                                 /* We must have a pathname for this. */
6559                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6560                                 return;
6561                         }
6562
6563                         status = smb_posix_unlink(conn, req,
6564                                                 pdata,
6565                                                 total_data,
6566                                                 fname,
6567                                                 &sbuf);
6568                         break;
6569                 }
6570
6571                 default:
6572                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6573                         return;
6574         }
6575
6576         
6577         if (!NT_STATUS_IS_OK(status)) {
6578                 if (open_was_deferred(req->mid)) {
6579                         /* We have re-scheduled this call. */
6580                         return;
6581                 }
6582                 if (blocking_lock_was_deferred(req->mid)) {
6583                         /* We have re-scheduled this call. */
6584                         return;
6585                 }
6586                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6587                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6588                                         ERRSRV, ERRbadpath);
6589                         return;
6590                 }
6591                 if (info_level == SMB_POSIX_PATH_OPEN) {
6592                         reply_openerror(req, status);
6593                         return;
6594                 }
6595
6596                 reply_nterror(req, status);
6597                 return;
6598         }
6599
6600         SSVAL(params,0,0);
6601         send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6602                             max_data_bytes);
6603   
6604         return;
6605 }
6606
6607 /****************************************************************************
6608  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6609 ****************************************************************************/
6610
6611 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6612                              char **pparams, int total_params,
6613                              char **ppdata, int total_data,
6614                              unsigned int max_data_bytes)
6615 {
6616         char *params = *pparams;
6617         char *pdata = *ppdata;
6618         char *directory = NULL;
6619         SMB_STRUCT_STAT sbuf;
6620         NTSTATUS status = NT_STATUS_OK;
6621         struct ea_list *ea_list = NULL;
6622         TALLOC_CTX *ctx = talloc_tos();
6623
6624         if (!CAN_WRITE(conn)) {
6625                 reply_doserror(req, ERRSRV, ERRaccess);
6626                 return;
6627         }
6628
6629         if (total_params < 5) {
6630                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6631                 return;
6632         }
6633
6634         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6635                         total_params - 4, STR_TERMINATE,
6636                         &status);
6637         if (!NT_STATUS_IS_OK(status)) {
6638                 reply_nterror(req, status);
6639                 return;
6640         }
6641
6642         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6643
6644         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6645         if (!NT_STATUS_IS_OK(status)) {
6646                 reply_nterror(req, status);
6647                 return;
6648         }
6649
6650         status = check_name(conn, directory);
6651         if (!NT_STATUS_IS_OK(status)) {
6652                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6653                 reply_nterror(req, status);
6654                 return;
6655         }
6656
6657         /* Any data in this call is an EA list. */
6658         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6659                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6660                 return;
6661         }
6662
6663         /*
6664          * OS/2 workplace shell seems to send SET_EA requests of "null"
6665          * length (4 bytes containing IVAL 4).
6666          * They seem to have no effect. Bug #3212. JRA.
6667          */
6668
6669         if (total_data != 4) {
6670                 if (total_data < 10) {
6671                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6672                         return;
6673                 }
6674
6675                 if (IVAL(pdata,0) > total_data) {
6676                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6677                                 IVAL(pdata,0), (unsigned int)total_data));
6678                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6679                         return;
6680                 }
6681
6682                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6683                                        total_data - 4);
6684                 if (!ea_list) {
6685                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6686                         return;
6687                 }
6688         } else if (IVAL(pdata,0) != 4) {
6689                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6690                 return;
6691         }
6692
6693         status = create_directory(conn, directory);
6694
6695         if (!NT_STATUS_IS_OK(status)) {
6696                 reply_nterror(req, status);
6697                 return;
6698         }
6699   
6700         /* Try and set any given EA. */
6701         if (ea_list) {
6702                 status = set_ea(conn, NULL, directory, ea_list);
6703                 if (!NT_STATUS_IS_OK(status)) {
6704                         reply_nterror(req, status);
6705                         return;
6706                 }
6707         }
6708
6709         /* Realloc the parameter and data sizes */
6710         *pparams = (char *)SMB_REALLOC(*pparams,2);
6711         if(*pparams == NULL) {
6712                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6713                 return;
6714         }
6715         params = *pparams;
6716
6717         SSVAL(params,0,0);
6718
6719         send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6720   
6721         return;
6722 }
6723
6724 /****************************************************************************
6725  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6726  We don't actually do this - we just send a null response.
6727 ****************************************************************************/
6728
6729 static void call_trans2findnotifyfirst(connection_struct *conn,
6730                                        struct smb_request *req,
6731                                        char **pparams, int total_params,
6732                                        char **ppdata, int total_data,
6733                                        unsigned int max_data_bytes)
6734 {
6735         static uint16 fnf_handle = 257;
6736         char *params = *pparams;
6737         uint16 info_level;
6738
6739         if (total_params < 6) {
6740                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6741                 return;
6742         }
6743
6744         info_level = SVAL(params,4);
6745         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6746
6747         switch (info_level) {
6748                 case 1:
6749                 case 2:
6750                         break;
6751                 default:
6752                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6753                         return;
6754         }
6755
6756         /* Realloc the parameter and data sizes */
6757         *pparams = (char *)SMB_REALLOC(*pparams,6);
6758         if (*pparams == NULL) {
6759                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6760                 return;
6761         }
6762         params = *pparams;
6763
6764         SSVAL(params,0,fnf_handle);
6765         SSVAL(params,2,0); /* No changes */
6766         SSVAL(params,4,0); /* No EA errors */
6767
6768         fnf_handle++;
6769
6770         if(fnf_handle == 0)
6771                 fnf_handle = 257;
6772
6773         send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6774   
6775         return;
6776 }
6777
6778 /****************************************************************************
6779  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6780  changes). Currently this does nothing.
6781 ****************************************************************************/
6782
6783 static void call_trans2findnotifynext(connection_struct *conn,
6784                                       struct smb_request *req,
6785                                       char **pparams, int total_params,
6786                                       char **ppdata, int total_data,
6787                                       unsigned int max_data_bytes)
6788 {
6789         char *params = *pparams;
6790
6791         DEBUG(3,("call_trans2findnotifynext\n"));
6792
6793         /* Realloc the parameter and data sizes */
6794         *pparams = (char *)SMB_REALLOC(*pparams,4);
6795         if (*pparams == NULL) {
6796                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6797                 return;
6798         }
6799         params = *pparams;
6800
6801         SSVAL(params,0,0); /* No changes */
6802         SSVAL(params,2,0); /* No EA errors */
6803
6804         send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6805   
6806         return;
6807 }
6808
6809 /****************************************************************************
6810  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6811 ****************************************************************************/
6812
6813 static void call_trans2getdfsreferral(connection_struct *conn,
6814                                       struct smb_request *req,
6815                                       char **pparams, int total_params,
6816                                       char **ppdata, int total_data,
6817                                       unsigned int max_data_bytes)
6818 {
6819         char *params = *pparams;
6820         char *pathname = NULL;
6821         int reply_size = 0;
6822         int max_referral_level;
6823         NTSTATUS status = NT_STATUS_OK;
6824         TALLOC_CTX *ctx = talloc_tos();
6825
6826         DEBUG(10,("call_trans2getdfsreferral\n"));
6827
6828         if (total_params < 3) {
6829                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6830                 return;
6831         }
6832
6833         max_referral_level = SVAL(params,0);
6834
6835         if(!lp_host_msdfs()) {
6836                 reply_doserror(req, ERRDOS, ERRbadfunc);
6837                 return;
6838         }
6839
6840         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6841                     total_params - 2, STR_TERMINATE);
6842         if (!pathname) {
6843                 reply_nterror(req, NT_STATUS_NOT_FOUND);
6844                 return;
6845         }
6846         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6847                                             ppdata,&status)) < 0) {
6848                 reply_nterror(req, status);
6849                 return;
6850         }
6851
6852         SSVAL(req->inbuf, smb_flg2,
6853               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6854         send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6855
6856         return;
6857 }
6858
6859 #define LMCAT_SPL       0x53
6860 #define LMFUNC_GETJOBID 0x60
6861
6862 /****************************************************************************
6863  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6864 ****************************************************************************/
6865
6866 static void call_trans2ioctl(connection_struct *conn,
6867                              struct smb_request *req,
6868                              char **pparams, int total_params,
6869                              char **ppdata, int total_data,
6870                              unsigned int max_data_bytes)
6871 {
6872         char *pdata = *ppdata;
6873         files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6874
6875         /* check for an invalid fid before proceeding */
6876
6877         if (!fsp) {
6878                 reply_doserror(req, ERRDOS, ERRbadfid);
6879                 return;
6880         }
6881
6882         if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6883             && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6884                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6885                 if (*ppdata == NULL) {
6886                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6887                         return;
6888                 }
6889                 pdata = *ppdata;
6890
6891                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6892                         CAN ACCEPT THIS IN UNICODE. JRA. */
6893
6894                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6895                 srvstr_push(pdata, req->flags2, pdata + 2,
6896                             global_myname(), 15,
6897                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6898                 srvstr_push(pdata, req->flags2, pdata+18,
6899                             lp_servicename(SNUM(conn)), 13,
6900                             STR_ASCII|STR_TERMINATE); /* Service name */
6901                 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6902                                     max_data_bytes);
6903                 return;
6904         }
6905
6906         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6907         reply_doserror(req, ERRSRV, ERRerror);
6908 }
6909
6910 /****************************************************************************
6911  Reply to a SMBfindclose (stop trans2 directory search).
6912 ****************************************************************************/
6913
6914 void reply_findclose(connection_struct *conn, struct smb_request *req)
6915 {
6916         int dptr_num;
6917
6918         START_PROFILE(SMBfindclose);
6919
6920         if (req->wct < 1) {
6921                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6922                 END_PROFILE(SMBfindclose);
6923                 return;
6924         }
6925
6926         dptr_num = SVALS(req->inbuf,smb_vwv0);
6927
6928         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6929
6930         dptr_close(&dptr_num);
6931
6932         reply_outbuf(req, 0, 0);
6933
6934         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6935
6936         END_PROFILE(SMBfindclose);
6937         return;
6938 }
6939
6940 /****************************************************************************
6941  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6942 ****************************************************************************/
6943
6944 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6945 {
6946         int dptr_num;
6947
6948         START_PROFILE(SMBfindnclose);
6949
6950         if (req->wct < 1) {
6951                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6952                 END_PROFILE(SMBfindnclose);
6953                 return;
6954         }
6955         
6956         dptr_num = SVAL(req->inbuf,smb_vwv0);
6957
6958         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6959
6960         /* We never give out valid handles for a 
6961            findnotifyfirst - so any dptr_num is ok here. 
6962            Just ignore it. */
6963
6964         reply_outbuf(req, 0, 0);
6965
6966         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6967
6968         END_PROFILE(SMBfindnclose);
6969         return;
6970 }
6971
6972 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6973                           struct trans_state *state)
6974 {
6975         if (Protocol >= PROTOCOL_NT1) {
6976                 req->flags2 |= 0x40; /* IS_LONG_NAME */
6977                 SSVAL(req->inbuf,smb_flg2,req->flags2);
6978         }
6979
6980         /* Now we must call the relevant TRANS2 function */
6981         switch(state->call)  {
6982         case TRANSACT2_OPEN:
6983         {
6984                 START_PROFILE(Trans2_open);
6985                 call_trans2open(conn, req,
6986                                 &state->param, state->total_param,
6987                                 &state->data, state->total_data,
6988                                 state->max_data_return);
6989                 END_PROFILE(Trans2_open);
6990                 break;
6991         }
6992
6993         case TRANSACT2_FINDFIRST:
6994         {
6995                 START_PROFILE(Trans2_findfirst);
6996                 call_trans2findfirst(conn, req,
6997                                      &state->param, state->total_param,
6998                                      &state->data, state->total_data,
6999                                      state->max_data_return);
7000                 END_PROFILE(Trans2_findfirst);
7001                 break;
7002         }
7003
7004         case TRANSACT2_FINDNEXT:
7005         {
7006                 START_PROFILE(Trans2_findnext);
7007                 call_trans2findnext(conn, req,
7008                                     &state->param, state->total_param,
7009                                     &state->data, state->total_data,
7010                                     state->max_data_return);
7011                 END_PROFILE(Trans2_findnext);
7012                 break;
7013         }
7014
7015         case TRANSACT2_QFSINFO:
7016         {
7017                 START_PROFILE(Trans2_qfsinfo);
7018                 call_trans2qfsinfo(conn, req,
7019                                    &state->param, state->total_param,
7020                                    &state->data, state->total_data,
7021                                    state->max_data_return);
7022                 END_PROFILE(Trans2_qfsinfo);
7023             break;
7024         }
7025
7026         case TRANSACT2_SETFSINFO:
7027         {
7028                 START_PROFILE(Trans2_setfsinfo);
7029                 call_trans2setfsinfo(conn, req,
7030                                      &state->param, state->total_param,
7031                                      &state->data, state->total_data,
7032                                      state->max_data_return);
7033                 END_PROFILE(Trans2_setfsinfo);
7034                 break;
7035         }
7036
7037         case TRANSACT2_QPATHINFO:
7038         case TRANSACT2_QFILEINFO:
7039         {
7040                 START_PROFILE(Trans2_qpathinfo);
7041                 call_trans2qfilepathinfo(conn, req, state->call,
7042                                          &state->param, state->total_param,
7043                                          &state->data, state->total_data,
7044                                          state->max_data_return);
7045                 END_PROFILE(Trans2_qpathinfo);
7046                 break;
7047         }
7048
7049         case TRANSACT2_SETPATHINFO:
7050         case TRANSACT2_SETFILEINFO:
7051         {
7052                 START_PROFILE(Trans2_setpathinfo);
7053                 call_trans2setfilepathinfo(conn, req, state->call,
7054                                            &state->param, state->total_param,
7055                                            &state->data, state->total_data,
7056                                            state->max_data_return);
7057                 END_PROFILE(Trans2_setpathinfo);
7058                 break;
7059         }
7060
7061         case TRANSACT2_FINDNOTIFYFIRST:
7062         {
7063                 START_PROFILE(Trans2_findnotifyfirst);
7064                 call_trans2findnotifyfirst(conn, req,
7065                                            &state->param, state->total_param,
7066                                            &state->data, state->total_data,
7067                                            state->max_data_return);
7068                 END_PROFILE(Trans2_findnotifyfirst);
7069                 break;
7070         }
7071
7072         case TRANSACT2_FINDNOTIFYNEXT:
7073         {
7074                 START_PROFILE(Trans2_findnotifynext);
7075                 call_trans2findnotifynext(conn, req,
7076                                           &state->param, state->total_param,
7077                                           &state->data, state->total_data,
7078                                           state->max_data_return);
7079                 END_PROFILE(Trans2_findnotifynext);
7080                 break;
7081         }
7082
7083         case TRANSACT2_MKDIR:
7084         {
7085                 START_PROFILE(Trans2_mkdir);
7086                 call_trans2mkdir(conn, req,
7087                                  &state->param, state->total_param,
7088                                  &state->data, state->total_data,
7089                                  state->max_data_return);
7090                 END_PROFILE(Trans2_mkdir);
7091                 break;
7092         }
7093
7094         case TRANSACT2_GET_DFS_REFERRAL:
7095         {
7096                 START_PROFILE(Trans2_get_dfs_referral);
7097                 call_trans2getdfsreferral(conn, req,
7098                                           &state->param, state->total_param,
7099                                           &state->data, state->total_data,
7100                                           state->max_data_return);
7101                 END_PROFILE(Trans2_get_dfs_referral);
7102                 break;
7103         }
7104
7105         case TRANSACT2_IOCTL:
7106         {
7107                 START_PROFILE(Trans2_ioctl);
7108                 call_trans2ioctl(conn, req,
7109                                  &state->param, state->total_param,
7110                                  &state->data, state->total_data,
7111                                  state->max_data_return);
7112                 END_PROFILE(Trans2_ioctl);
7113                 break;
7114         }
7115
7116         default:
7117                 /* Error in request */
7118                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7119                 reply_doserror(req, ERRSRV,ERRerror);
7120         }
7121 }
7122
7123 /****************************************************************************
7124  Reply to a SMBtrans2.
7125  ****************************************************************************/
7126
7127 void reply_trans2(connection_struct *conn, struct smb_request *req)
7128 {
7129         unsigned int dsoff;
7130         unsigned int dscnt;
7131         unsigned int psoff;
7132         unsigned int pscnt;
7133         unsigned int tran_call;
7134         int size;
7135         struct trans_state *state;
7136         NTSTATUS result;
7137
7138         START_PROFILE(SMBtrans2);
7139
7140         if (req->wct < 14) {
7141                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7142                 END_PROFILE(SMBtrans2);
7143                 return;
7144         }
7145
7146         dsoff = SVAL(req->inbuf, smb_dsoff);
7147         dscnt = SVAL(req->inbuf, smb_dscnt);
7148         psoff = SVAL(req->inbuf, smb_psoff);
7149         pscnt = SVAL(req->inbuf, smb_pscnt);
7150         tran_call = SVAL(req->inbuf, smb_setup0);
7151         size = smb_len(req->inbuf) + 4;
7152
7153         result = allow_new_trans(conn->pending_trans, req->mid);
7154         if (!NT_STATUS_IS_OK(result)) {
7155                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7156                           nt_errstr(result)));
7157                 reply_nterror(req, result);
7158                 END_PROFILE(SMBtrans2);
7159                 return;
7160         }
7161
7162         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7163             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7164             && (tran_call != TRANSACT2_QFILEINFO)) {
7165                 reply_doserror(req, ERRSRV, ERRaccess);
7166                 END_PROFILE(SMBtrans2);
7167                 return;
7168         }
7169
7170         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7171                 DEBUG(0, ("talloc failed\n"));
7172                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7173                 END_PROFILE(SMBtrans2);
7174                 return;
7175         }
7176
7177         state->cmd = SMBtrans2;
7178
7179         state->mid = req->mid;
7180         state->vuid = req->vuid;
7181         state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7182         state->setup = NULL;
7183         state->total_param = SVAL(req->inbuf, smb_tpscnt);
7184         state->param = NULL;
7185         state->total_data =  SVAL(req->inbuf, smb_tdscnt);
7186         state->data = NULL;
7187         state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7188         state->max_data_return  = SVAL(req->inbuf, smb_mdrcnt);
7189         state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7190         state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7191         state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7192
7193         state->call = tran_call;
7194
7195         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7196            is so as a sanity check */
7197         if (state->setup_count != 1) {
7198                 /*
7199                  * Need to have rc=0 for ioctl to get job id for OS/2.
7200                  *  Network printing will fail if function is not successful.
7201                  *  Similar function in reply.c will be used if protocol
7202                  *  is LANMAN1.0 instead of LM1.2X002.
7203                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7204                  *  outbuf doesn't have to be set(only job id is used).
7205                  */
7206                 if ( (state->setup_count == 4)
7207                      && (tran_call == TRANSACT2_IOCTL)
7208                      && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7209                      && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7210                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7211                 } else {
7212                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7213                         DEBUG(2,("Transaction is %d\n",tran_call));
7214                         TALLOC_FREE(state);
7215                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7216                         END_PROFILE(SMBtrans2);
7217                         return;
7218                 }
7219         }
7220
7221         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7222                 goto bad_param;
7223
7224         if (state->total_data) {
7225                 /* Can't use talloc here, the core routines do realloc on the
7226                  * params and data. */
7227                 state->data = (char *)SMB_MALLOC(state->total_data);
7228                 if (state->data == NULL) {
7229                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7230                                  "bytes !\n", (unsigned int)state->total_data));
7231                         TALLOC_FREE(state);
7232                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7233                         END_PROFILE(SMBtrans2);
7234                         return;
7235                 }
7236                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7237                         goto bad_param;
7238                 if ((smb_base(req->inbuf)+dsoff+dscnt
7239                      > (char *)req->inbuf + size) ||
7240                     (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7241                         goto bad_param;
7242
7243                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7244         }
7245
7246         if (state->total_param) {
7247                 /* Can't use talloc here, the core routines do realloc on the
7248                  * params and data. */
7249                 state->param = (char *)SMB_MALLOC(state->total_param);
7250                 if (state->param == NULL) {
7251                         DEBUG(0,("reply_trans: param malloc fail for %u "
7252                                  "bytes !\n", (unsigned int)state->total_param));
7253                         SAFE_FREE(state->data);
7254                         TALLOC_FREE(state);
7255                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7256                         END_PROFILE(SMBtrans2);
7257                         return;
7258                 } 
7259                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7260                         goto bad_param;
7261                 if ((smb_base(req->inbuf)+psoff+pscnt
7262                      > (char *)req->inbuf + size) ||
7263                     (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7264                         goto bad_param;
7265
7266                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7267         }
7268
7269         state->received_data  = dscnt;
7270         state->received_param = pscnt;
7271
7272         if ((state->received_param == state->total_param) &&
7273             (state->received_data == state->total_data)) {
7274
7275                 handle_trans2(conn, req, state);
7276
7277                 SAFE_FREE(state->data);
7278                 SAFE_FREE(state->param);
7279                 TALLOC_FREE(state);
7280                 END_PROFILE(SMBtrans2);
7281                 return;
7282         }
7283
7284         DLIST_ADD(conn->pending_trans, state);
7285
7286         /* We need to send an interim response then receive the rest
7287            of the parameter/data bytes */
7288         reply_outbuf(req, 0, 0);
7289         show_msg((char *)req->outbuf);
7290         END_PROFILE(SMBtrans2);
7291         return;
7292
7293   bad_param:
7294
7295         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7296         SAFE_FREE(state->data);
7297         SAFE_FREE(state->param);
7298         TALLOC_FREE(state);
7299         END_PROFILE(SMBtrans2);
7300         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7301 }
7302
7303
7304 /****************************************************************************
7305  Reply to a SMBtranss2
7306  ****************************************************************************/
7307
7308 void reply_transs2(connection_struct *conn, struct smb_request *req)
7309 {
7310         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7311         struct trans_state *state;
7312         int size;
7313
7314         START_PROFILE(SMBtranss2);
7315
7316         show_msg((char *)req->inbuf);
7317
7318         if (req->wct < 8) {
7319                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7320                 END_PROFILE(SMBtranss2);
7321                 return;
7322         }
7323
7324         size = smb_len(req->inbuf)+4;
7325
7326         for (state = conn->pending_trans; state != NULL;
7327              state = state->next) {
7328                 if (state->mid == req->mid) {
7329                         break;
7330                 }
7331         }
7332
7333         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7334                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7335                 END_PROFILE(SMBtranss2);
7336                 return;
7337         }
7338
7339         /* Revise state->total_param and state->total_data in case they have
7340            changed downwards */
7341
7342         if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7343                 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7344         if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7345                 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7346
7347         pcnt = SVAL(req->inbuf, smb_spscnt);
7348         poff = SVAL(req->inbuf, smb_spsoff);
7349         pdisp = SVAL(req->inbuf, smb_spsdisp);
7350
7351         dcnt = SVAL(req->inbuf, smb_sdscnt);
7352         doff = SVAL(req->inbuf, smb_sdsoff);
7353         ddisp = SVAL(req->inbuf, smb_sdsdisp);
7354
7355         state->received_param += pcnt;
7356         state->received_data += dcnt;
7357                 
7358         if ((state->received_data > state->total_data) ||
7359             (state->received_param > state->total_param))
7360                 goto bad_param;
7361
7362         if (pcnt) {
7363                 if (pdisp+pcnt > state->total_param)
7364                         goto bad_param;
7365                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7366                         goto bad_param;
7367                 if (pdisp > state->total_param)
7368                         goto bad_param;
7369                 if ((smb_base(req->inbuf) + poff + pcnt
7370                      > (char *)req->inbuf + size) ||
7371                     (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7372                         goto bad_param;
7373                 if (state->param + pdisp < state->param)
7374                         goto bad_param;
7375
7376                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7377                        pcnt);
7378         }
7379
7380         if (dcnt) {
7381                 if (ddisp+dcnt > state->total_data)
7382                         goto bad_param;
7383                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7384                         goto bad_param;
7385                 if (ddisp > state->total_data)
7386                         goto bad_param;
7387                 if ((smb_base(req->inbuf) + doff + dcnt
7388                      > (char *)req->inbuf + size) ||
7389                     (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7390                         goto bad_param;
7391                 if (state->data + ddisp < state->data)
7392                         goto bad_param;
7393
7394                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7395                        dcnt);      
7396         }
7397
7398         if ((state->received_param < state->total_param) ||
7399             (state->received_data < state->total_data)) {
7400                 END_PROFILE(SMBtranss2);
7401                 return;
7402         }
7403
7404         /*
7405          * construct_reply_common will copy smb_com from inbuf to
7406          * outbuf. SMBtranss2 is wrong here.
7407          */
7408         SCVAL(req->inbuf,smb_com,SMBtrans2);
7409
7410         handle_trans2(conn, req, state);
7411
7412         DLIST_REMOVE(conn->pending_trans, state);
7413         SAFE_FREE(state->data);
7414         SAFE_FREE(state->param);
7415         TALLOC_FREE(state);
7416
7417         END_PROFILE(SMBtranss2);
7418         return;
7419
7420   bad_param:
7421
7422         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7423         DLIST_REMOVE(conn->pending_trans, state);
7424         SAFE_FREE(state->data);
7425         SAFE_FREE(state->param);
7426         TALLOC_FREE(state);
7427         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7428         END_PROFILE(SMBtranss2);
7429         return;
7430 }