r25138: More pstring elimination. Add a TALLOC_CTX parameter
[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),
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),
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                         if (!lp_unix_extensions()) {
2723                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2724                                 return;
2725                         }
2726                         data_len = 12;
2727                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2728                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2729                         /* We have POSIX ACLs, pathname and locking capability. */
2730                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2731                                         CIFS_UNIX_POSIX_ACLS_CAP|
2732                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2733                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2734                                         CIFS_UNIX_EXTATTR_CAP|
2735                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2736                                         /* Ensure we don't do this on signed or sealed data. */
2737                                         (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2738                                         )));
2739                         break;
2740
2741                 case SMB_QUERY_POSIX_FS_INFO:
2742                 {
2743                         int rc;
2744                         vfs_statvfs_struct svfs;
2745
2746                         if (!lp_unix_extensions()) {
2747                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2748                                 return;
2749                         }
2750
2751                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2752
2753                         if (!rc) {
2754                                 data_len = 56;
2755                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2756                                 SIVAL(pdata,4,svfs.BlockSize);
2757                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2758                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2759                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2760                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2761                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2762                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2763                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2764 #ifdef EOPNOTSUPP
2765                         } else if (rc == EOPNOTSUPP) {
2766                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2767                                 return;
2768 #endif /* EOPNOTSUPP */
2769                         } else {
2770                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2771                                 reply_doserror(req, ERRSRV, ERRerror);
2772                                 return;
2773                         }
2774                         break;
2775                 }
2776
2777                 case SMB_QUERY_POSIX_WHOAMI:
2778                 {
2779                         uint32_t flags = 0;
2780                         uint32_t sid_bytes;
2781                         int i;
2782
2783                         if (!lp_unix_extensions()) {
2784                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2785                                 return;
2786                         }
2787
2788                         if (max_data_bytes < 40) {
2789                                 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2790                                 return;
2791                         }
2792
2793                         /* We ARE guest if global_sid_Builtin_Guests is
2794                          * in our list of SIDs.
2795                          */
2796                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2797                                     current_user.nt_user_token)) {
2798                                 flags |= SMB_WHOAMI_GUEST;
2799                         }
2800
2801                         /* We are NOT guest if global_sid_Authenticated_Users
2802                          * is in our list of SIDs.
2803                          */
2804                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2805                                     current_user.nt_user_token)) {
2806                                 flags &= ~SMB_WHOAMI_GUEST;
2807                         }
2808
2809                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2810                          * platform size. This matches
2811                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2812                          */
2813                         data_len = 4 /* flags */
2814                             + 4 /* flag mask */
2815                             + 8 /* uid */
2816                             + 8 /* gid */
2817                             + 4 /* ngroups */
2818                             + 4 /* num_sids */
2819                             + 4 /* SID bytes */
2820                             + 4 /* pad/reserved */
2821                             + (current_user.ut.ngroups * 8)
2822                                 /* groups list */
2823                             + (current_user.nt_user_token->num_sids *
2824                                     SID_MAX_SIZE)
2825                                 /* SID list */;
2826
2827                         SIVAL(pdata, 0, flags);
2828                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2829                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2830                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2831
2832
2833                         if (data_len >= max_data_bytes) {
2834                                 /* Potential overflow, skip the GIDs and SIDs. */
2835
2836                                 SIVAL(pdata, 24, 0); /* num_groups */
2837                                 SIVAL(pdata, 28, 0); /* num_sids */
2838                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2839                                 SIVAL(pdata, 36, 0); /* reserved */
2840
2841                                 data_len = 40;
2842                                 break;
2843                         }
2844
2845                         SIVAL(pdata, 24, current_user.ut.ngroups);
2846                         SIVAL(pdata, 28,
2847                                 current_user.nt_user_token->num_sids);
2848
2849                         /* We walk the SID list twice, but this call is fairly
2850                          * infrequent, and I don't expect that it's performance
2851                          * sensitive -- jpeach
2852                          */
2853                         for (i = 0, sid_bytes = 0;
2854                             i < current_user.nt_user_token->num_sids; ++i) {
2855                                 sid_bytes +=
2856                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2857                         }
2858
2859                         /* SID list byte count */
2860                         SIVAL(pdata, 32, sid_bytes);
2861
2862                         /* 4 bytes pad/reserved - must be zero */
2863                         SIVAL(pdata, 36, 0);
2864                         data_len = 40;
2865
2866                         /* GID list */
2867                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2868                                 SBIG_UINT(pdata, data_len,
2869                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2870                                 data_len += 8;
2871                         }
2872
2873                         /* SID list */
2874                         for (i = 0;
2875                             i < current_user.nt_user_token->num_sids; ++i) {
2876                                 int sid_len =
2877                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2878
2879                                 sid_linearize(pdata + data_len, sid_len,
2880                                     &current_user.nt_user_token->user_sids[i]);
2881                                 data_len += sid_len;
2882                         }
2883
2884                         break;
2885                 }
2886
2887                 case SMB_MAC_QUERY_FS_INFO:
2888                         /*
2889                          * Thursby MAC extension... ONLY on NTFS filesystems
2890                          * once we do streams then we don't need this
2891                          */
2892                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2893                                 data_len = 88;
2894                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2895                                 break;
2896                         }
2897                         /* drop through */
2898                 default:
2899                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2900                         return;
2901         }
2902
2903
2904         send_trans2_replies(req, params, 0, pdata, data_len,
2905                             max_data_bytes);
2906
2907         DEBUG( 4, ( "%s info_level = %d\n",
2908                     smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
2909
2910         return;
2911 }
2912
2913 /****************************************************************************
2914  Reply to a TRANS2_SETFSINFO (set filesystem info).
2915 ****************************************************************************/
2916
2917 static void call_trans2setfsinfo(connection_struct *conn,
2918                                  struct smb_request *req,
2919                                  char **pparams, int total_params,
2920                                  char **ppdata, int total_data,
2921                                  unsigned int max_data_bytes)
2922 {
2923         char *pdata = *ppdata;
2924         char *params = *pparams;
2925         uint16 info_level;
2926
2927         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2928
2929         /*  */
2930         if (total_params < 4) {
2931                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2932                         total_params));
2933                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2934                 return;
2935         }
2936
2937         info_level = SVAL(params,2);
2938
2939         switch(info_level) {
2940                 case SMB_SET_CIFS_UNIX_INFO:
2941                         {
2942                                 uint16 client_unix_major;
2943                                 uint16 client_unix_minor;
2944                                 uint32 client_unix_cap_low;
2945                                 uint32 client_unix_cap_high;
2946
2947                                 if (!lp_unix_extensions()) {
2948                                         reply_nterror(req,
2949                                                       NT_STATUS_INVALID_LEVEL);
2950                                         return;
2951                                 }
2952
2953                                 /* There should be 12 bytes of capabilities set. */
2954                                 if (total_data < 8) {
2955                                         reply_nterror(
2956                                                 req,
2957                                                 NT_STATUS_INVALID_PARAMETER);
2958                                         return;
2959                                 }
2960                                 client_unix_major = SVAL(pdata,0);
2961                                 client_unix_minor = SVAL(pdata,2);
2962                                 client_unix_cap_low = IVAL(pdata,4);
2963                                 client_unix_cap_high = IVAL(pdata,8);
2964                                 /* Just print these values for now. */
2965                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2966 cap_low = 0x%x, cap_high = 0x%x\n",
2967                                         (unsigned int)client_unix_major,
2968                                         (unsigned int)client_unix_minor,
2969                                         (unsigned int)client_unix_cap_low,
2970                                         (unsigned int)client_unix_cap_high ));
2971
2972                                 /* Here is where we must switch to posix pathname processing... */
2973                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2974                                         lp_set_posix_pathnames();
2975                                         mangle_change_to_posix();
2976                                 }
2977
2978                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2979                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2980                                         /* Client that knows how to do posix locks,
2981                                          * but not posix open/mkdir operations. Set a
2982                                          * default type for read/write checks. */
2983
2984                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2985
2986                                 }
2987                                 break;
2988                         }
2989                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2990                         {
2991                                 NTSTATUS status;
2992                                 size_t param_len = 0;
2993                                 size_t data_len = total_data;
2994
2995                                 if (!lp_unix_extensions()) {
2996                                         reply_nterror(
2997                                                 req, NT_STATUS_INVALID_LEVEL);
2998                                         return;
2999                                 }
3000
3001                                 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
3002
3003                                 status = srv_request_encryption_setup(conn,
3004                                                                         (unsigned char **)ppdata,
3005                                                                         &data_len,
3006                                                                         (unsigned char **)pparams,
3007                                                                         &param_len
3008                                                                         );
3009
3010                                 if (!NT_STATUS_IS_OK(status)) {
3011                                         /*
3012                                          * TODO: Check
3013                                          * MORE_PROCESSING_REQUIRED, this used
3014                                          * to have special handling here.
3015                                          */
3016                                         reply_nterror(req, status);
3017                                         return;
3018                                 }
3019
3020                                 send_trans2_replies(req,
3021                                                     *pparams, param_len,
3022                                                     *ppdata, data_len,
3023                                                     max_data_bytes);
3024
3025                                 if (NT_STATUS_IS_OK(status)) {
3026                                         /* Server-side transport encryption is now *on*. */
3027                                         status = srv_encryption_start(conn);
3028                                         if (!NT_STATUS_IS_OK(status)) {
3029                                                 exit_server_cleanly("Failure in setting up encrypted transport");
3030                                         }
3031                                 }
3032                                 return;
3033                         }
3034                 case SMB_FS_QUOTA_INFORMATION:
3035                         {
3036                                 files_struct *fsp = NULL;
3037                                 SMB_NTQUOTA_STRUCT quotas;
3038         
3039                                 ZERO_STRUCT(quotas);
3040
3041                                 /* access check */
3042                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
3043                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3044                                                 lp_servicename(SNUM(conn)),conn->user));
3045                                         reply_doserror(req, ERRSRV, ERRaccess);
3046                                         return;
3047                                 }
3048
3049                                 /* note: normaly there're 48 bytes,
3050                                  * but we didn't use the last 6 bytes for now 
3051                                  * --metze 
3052                                  */
3053                                 fsp = file_fsp(SVAL(params,0));
3054                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
3055                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3056                                         reply_nterror(
3057                                                 req, NT_STATUS_INVALID_HANDLE);
3058                                         return;
3059                                 }
3060
3061                                 if (total_data < 42) {
3062                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3063                                                 total_data));
3064                                         reply_nterror(
3065                                                 req,
3066                                                 NT_STATUS_INVALID_PARAMETER);
3067                                         return;
3068                                 }
3069                         
3070                                 /* unknown_1 24 NULL bytes in pdata*/
3071                 
3072                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3073                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3074 #ifdef LARGE_SMB_OFF_T
3075                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3076 #else /* LARGE_SMB_OFF_T */
3077                                 if ((IVAL(pdata,28) != 0)&&
3078                                         ((quotas.softlim != 0xFFFFFFFF)||
3079                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
3080                                         /* more than 32 bits? */
3081                                         reply_nterror(
3082                                                 req,
3083                                                 NT_STATUS_INVALID_PARAMETER);
3084                                         return;
3085                                 }
3086 #endif /* LARGE_SMB_OFF_T */
3087                 
3088                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3089                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3090 #ifdef LARGE_SMB_OFF_T
3091                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3092 #else /* LARGE_SMB_OFF_T */
3093                                 if ((IVAL(pdata,36) != 0)&&
3094                                         ((quotas.hardlim != 0xFFFFFFFF)||
3095                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
3096                                         /* more than 32 bits? */
3097                                         reply_nterror(
3098                                                 req,
3099                                                 NT_STATUS_INVALID_PARAMETER);
3100                                         return;
3101                                 }
3102 #endif /* LARGE_SMB_OFF_T */
3103                 
3104                                 /* quota_flags 2 bytes **/
3105                                 quotas.qflags = SVAL(pdata,40);
3106                 
3107                                 /* unknown_2 6 NULL bytes follow*/
3108                 
3109                                 /* now set the quotas */
3110                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3111                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3112                                         reply_doserror(req, ERRSRV, ERRerror);
3113                                         return;
3114                                 }
3115                         
3116                                 break;
3117                         }
3118                 default:
3119                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3120                                 info_level));
3121                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3122                         return;
3123                         break;
3124         }
3125
3126         /* 
3127          * sending this reply works fine, 
3128          * but I'm not sure it's the same 
3129          * like windows do...
3130          * --metze
3131          */
3132         reply_outbuf(req, 10, 0);
3133 }
3134
3135 #if defined(HAVE_POSIX_ACLS)
3136 /****************************************************************************
3137  Utility function to count the number of entries in a POSIX acl.
3138 ****************************************************************************/
3139
3140 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3141 {
3142         unsigned int ace_count = 0;
3143         int entry_id = SMB_ACL_FIRST_ENTRY;
3144         SMB_ACL_ENTRY_T entry;
3145
3146         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3147                 /* get_next... */
3148                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3149                         entry_id = SMB_ACL_NEXT_ENTRY;
3150                 }
3151                 ace_count++;
3152         }
3153         return ace_count;
3154 }
3155
3156 /****************************************************************************
3157  Utility function to marshall a POSIX acl into wire format.
3158 ****************************************************************************/
3159
3160 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3161 {
3162         int entry_id = SMB_ACL_FIRST_ENTRY;
3163         SMB_ACL_ENTRY_T entry;
3164
3165         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3166                 SMB_ACL_TAG_T tagtype;
3167                 SMB_ACL_PERMSET_T permset;
3168                 unsigned char perms = 0;
3169                 unsigned int own_grp;
3170
3171                 /* get_next... */
3172                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3173                         entry_id = SMB_ACL_NEXT_ENTRY;
3174                 }
3175
3176                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3177                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3178                         return False;
3179                 }
3180
3181                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3182                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3183                         return False;
3184                 }
3185
3186                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3187                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3188                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3189
3190                 SCVAL(pdata,1,perms);
3191
3192                 switch (tagtype) {
3193                         case SMB_ACL_USER_OBJ:
3194                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3195                                 own_grp = (unsigned int)pst->st_uid;
3196                                 SIVAL(pdata,2,own_grp);
3197                                 SIVAL(pdata,6,0);
3198                                 break;
3199                         case SMB_ACL_USER:
3200                                 {
3201                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3202                                         if (!puid) {
3203                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3204                                                 return False;
3205                                         }
3206                                         own_grp = (unsigned int)*puid;
3207                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3208                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3209                                         SIVAL(pdata,2,own_grp);
3210                                         SIVAL(pdata,6,0);
3211                                         break;
3212                                 }
3213                         case SMB_ACL_GROUP_OBJ:
3214                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3215                                 own_grp = (unsigned int)pst->st_gid;
3216                                 SIVAL(pdata,2,own_grp);
3217                                 SIVAL(pdata,6,0);
3218                                 break;
3219                         case SMB_ACL_GROUP:
3220                                 {
3221                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3222                                         if (!pgid) {
3223                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3224                                                 return False;
3225                                         }
3226                                         own_grp = (unsigned int)*pgid;
3227                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3228                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3229                                         SIVAL(pdata,2,own_grp);
3230                                         SIVAL(pdata,6,0);
3231                                         break;
3232                                 }
3233                         case SMB_ACL_MASK:
3234                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3235                                 SIVAL(pdata,2,0xFFFFFFFF);
3236                                 SIVAL(pdata,6,0xFFFFFFFF);
3237                                 break;
3238                         case SMB_ACL_OTHER:
3239                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3240                                 SIVAL(pdata,2,0xFFFFFFFF);
3241                                 SIVAL(pdata,6,0xFFFFFFFF);
3242                                 break;
3243                         default:
3244                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3245                                 return False;
3246                 }
3247                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3248         }
3249
3250         return True;
3251 }
3252 #endif
3253
3254 /****************************************************************************
3255  Store the FILE_UNIX_BASIC info.
3256 ****************************************************************************/
3257
3258 static char *store_file_unix_basic(connection_struct *conn,
3259                                 char *pdata,
3260                                 files_struct *fsp,
3261                                 const SMB_STRUCT_STAT *psbuf)
3262 {
3263         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3264         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3265
3266         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3267         pdata += 8;
3268
3269         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3270         pdata += 8;
3271
3272         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3273         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3274         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3275         pdata += 24;
3276
3277         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3278         SIVAL(pdata,4,0);
3279         pdata += 8;
3280
3281         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3282         SIVAL(pdata,4,0);
3283         pdata += 8;
3284
3285         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3286         pdata += 4;
3287
3288         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3289         SIVAL(pdata,4,0);
3290         pdata += 8;
3291
3292         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3293         SIVAL(pdata,4,0);
3294         pdata += 8;
3295
3296         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3297         pdata += 8;
3298                                 
3299         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3300         SIVAL(pdata,4,0);
3301         pdata += 8;
3302
3303         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3304         SIVAL(pdata,4,0);
3305         pdata += 8;
3306
3307         return pdata;
3308 }
3309
3310 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3311  * the chflags(2) (or equivalent) flags.
3312  *
3313  * XXX: this really should be behind the VFS interface. To do this, we would
3314  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3315  * Each VFS module could then implement it's own mapping as appropriate for the
3316  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3317  */
3318 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3319         info2_flags_map[] =
3320 {
3321 #ifdef UF_NODUMP
3322     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3323 #endif
3324
3325 #ifdef UF_IMMUTABLE
3326     { UF_IMMUTABLE, EXT_IMMUTABLE },
3327 #endif
3328
3329 #ifdef UF_APPEND
3330     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3331 #endif
3332
3333 #ifdef UF_HIDDEN
3334     { UF_HIDDEN, EXT_HIDDEN },
3335 #endif
3336
3337     /* Do not remove. We need to guarantee that this array has at least one
3338      * entry to build on HP-UX.
3339      */
3340     { 0, 0 }
3341
3342 };
3343
3344 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3345                                 uint32 *smb_fflags, uint32 *smb_fmask)
3346 {
3347 #ifdef HAVE_STAT_ST_FLAGS
3348         int i;
3349
3350         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3351             *smb_fmask |= info2_flags_map[i].smb_fflag;
3352             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3353                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3354             }
3355         }
3356 #endif /* HAVE_STAT_ST_FLAGS */
3357 }
3358
3359 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3360                                 const uint32 smb_fflags,
3361                                 const uint32 smb_fmask,
3362                                 int *stat_fflags)
3363 {
3364 #ifdef HAVE_STAT_ST_FLAGS
3365         uint32 max_fmask = 0;
3366         int i;
3367
3368         *stat_fflags = psbuf->st_flags;
3369
3370         /* For each flags requested in smb_fmask, check the state of the
3371          * corresponding flag in smb_fflags and set or clear the matching
3372          * stat flag.
3373          */
3374
3375         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3376             max_fmask |= info2_flags_map[i].smb_fflag;
3377             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3378                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3379                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3380                     } else {
3381                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3382                     }
3383             }
3384         }
3385
3386         /* If smb_fmask is asking to set any bits that are not supported by
3387          * our flag mappings, we should fail.
3388          */
3389         if ((smb_fmask & max_fmask) != smb_fmask) {
3390                 return False;
3391         }
3392
3393         return True;
3394 #else
3395         return False;
3396 #endif /* HAVE_STAT_ST_FLAGS */
3397 }
3398
3399
3400 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3401  * of file flags and birth (create) time.
3402  */
3403 static char *store_file_unix_basic_info2(connection_struct *conn,
3404                                 char *pdata,
3405                                 files_struct *fsp,
3406                                 const SMB_STRUCT_STAT *psbuf)
3407 {
3408         uint32 file_flags = 0;
3409         uint32 flags_mask = 0;
3410
3411         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3412
3413         /* Create (birth) time 64 bit */
3414         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3415         pdata += 8;
3416
3417         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3418         SIVAL(pdata, 0, file_flags); /* flags */
3419         SIVAL(pdata, 4, flags_mask); /* mask */
3420         pdata += 8;
3421
3422         return pdata;
3423 }
3424
3425 /****************************************************************************
3426  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3427 ****************************************************************************/
3428
3429 static void call_trans2qpipeinfo(connection_struct *conn,
3430                                  struct smb_request *req,
3431                                  unsigned int tran_call,
3432                                  char **pparams, int total_params,
3433                                  char **ppdata, int total_data,
3434                                  unsigned int max_data_bytes)
3435 {
3436         char *params = *pparams;
3437         char *pdata = *ppdata;
3438         unsigned int data_size = 0;
3439         unsigned int param_size = 2;
3440         uint16 info_level;
3441         smb_np_struct *p_pipe = NULL;
3442
3443         if (!params) {
3444                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3445                 return;
3446         }
3447
3448         if (total_params < 4) {
3449                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3450                 return;
3451         }
3452
3453         p_pipe = get_rpc_pipe_p(SVAL(params,0));
3454         if (p_pipe == NULL) {
3455                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3456                 return;
3457         }
3458
3459         info_level = SVAL(params,2);
3460
3461         *pparams = (char *)SMB_REALLOC(*pparams,2);
3462         if (*pparams == NULL) {
3463                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3464                 return;
3465         }
3466         params = *pparams;
3467         SSVAL(params,0,0);
3468         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3469         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3470         if (*ppdata == NULL ) {
3471                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3472                 return;
3473         }
3474         pdata = *ppdata;
3475
3476         switch (info_level) {
3477                 case SMB_FILE_STANDARD_INFORMATION:
3478                         memset(pdata,0,24);
3479                         SOFF_T(pdata,0,4096LL);
3480                         SIVAL(pdata,16,1);
3481                         SIVAL(pdata,20,1);
3482                         data_size = 24;
3483                         break;
3484
3485                 default:
3486                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3487                         return;
3488         }
3489
3490         send_trans2_replies(req, params, param_size, *ppdata, data_size,
3491                             max_data_bytes);
3492
3493         return;
3494 }
3495
3496 /****************************************************************************
3497  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3498  file name or file id).
3499 ****************************************************************************/
3500
3501 static void call_trans2qfilepathinfo(connection_struct *conn,
3502                                      struct smb_request *req,
3503                                      unsigned int tran_call,
3504                                      char **pparams, int total_params,
3505                                      char **ppdata, int total_data,
3506                                      unsigned int max_data_bytes)
3507 {
3508         char *params = *pparams;
3509         char *pdata = *ppdata;
3510         char *dstart, *dend;
3511         uint16 info_level;
3512         int mode=0;
3513         int nlink;
3514         SMB_OFF_T file_size=0;
3515         SMB_BIG_UINT allocation_size=0;
3516         unsigned int data_size = 0;
3517         unsigned int param_size = 2;
3518         SMB_STRUCT_STAT sbuf;
3519         char *dos_fname = NULL;
3520         char *fname = NULL;
3521         char *fullpathname;
3522         char *base_name;
3523         char *p;
3524         SMB_OFF_T pos = 0;
3525         BOOL delete_pending = False;
3526         int len;
3527         time_t create_time, mtime, atime;
3528         struct timespec create_time_ts, mtime_ts, atime_ts;
3529         files_struct *fsp = NULL;
3530         struct file_id fileid;
3531         struct ea_list *ea_list = NULL;
3532         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3533         char *lock_data = NULL;
3534         TALLOC_CTX *ctx = talloc_tos();
3535
3536         if (!params) {
3537                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3538                 return;
3539         }
3540
3541         ZERO_STRUCT(sbuf);
3542
3543         if (tran_call == TRANSACT2_QFILEINFO) {
3544                 if (total_params < 4) {
3545                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546                         return;
3547                 }
3548
3549                 if (IS_IPC(conn)) {
3550                         call_trans2qpipeinfo(conn, req, tran_call,
3551                                              pparams, total_params,
3552                                              ppdata, total_data,
3553                                              max_data_bytes);
3554                         return;
3555                 }
3556
3557                 fsp = file_fsp(SVAL(params,0));
3558                 info_level = SVAL(params,2);
3559
3560                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3561
3562                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3563                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3564                         return;
3565                 }
3566
3567                 /* Initial check for valid fsp ptr. */
3568                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
3569                         return;
3570                 }
3571
3572                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3573                 if (!fname) {
3574                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3575                         return;
3576                 }
3577
3578                 if(fsp->fake_file_handle) {
3579                         /*
3580                          * This is actually for the QUOTA_FAKE_FILE --metze
3581                          */
3582
3583                         /* We know this name is ok, it's already passed the checks. */
3584
3585                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3586                         /*
3587                          * This is actually a QFILEINFO on a directory
3588                          * handle (returned from an NT SMB). NT5.0 seems
3589                          * to do this call. JRA.
3590                          */
3591
3592                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3593                                 /* Always do lstat for UNIX calls. */
3594                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3595                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3596                                         reply_unixerror(req,ERRDOS,ERRbadpath);
3597                                         return;
3598                                 }
3599                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3600                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3601                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3602                                 return;
3603                         }
3604
3605                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3606                         delete_pending = get_delete_on_close_flag(fileid);
3607                 } else {
3608                         /*
3609                          * Original code - this is an open file.
3610                          */
3611                         if (!check_fsp(conn, req, fsp, &current_user)) {
3612                                 return;
3613                         }
3614
3615                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3616                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3617                                 reply_unixerror(req, ERRDOS, ERRbadfid);
3618                                 return;
3619                         }
3620                         pos = fsp->fh->position_information;
3621                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3622                         delete_pending = get_delete_on_close_flag(fileid);
3623                         access_mask = fsp->access_mask;
3624                 }
3625
3626         } else {
3627                 NTSTATUS status = NT_STATUS_OK;
3628
3629                 /* qpathinfo */
3630                 if (total_params < 7) {
3631                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3632                         return;
3633                 }
3634
3635                 info_level = SVAL(params,0);
3636
3637                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3638
3639                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3640                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3641                         return;
3642                 }
3643
3644                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3645                                 total_params - 6,
3646                                 STR_TERMINATE, &status);
3647                 if (!NT_STATUS_IS_OK(status)) {
3648                         reply_nterror(req, status);
3649                         return;
3650                 }
3651
3652                 status = resolve_dfspath(ctx,
3653                                         conn,
3654                                         req->flags2 & FLAGS2_DFS_PATHNAMES,
3655                                         fname,
3656                                         &fname);
3657                 if (!NT_STATUS_IS_OK(status)) {
3658                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3659                                 reply_botherror(req,
3660                                                 NT_STATUS_PATH_NOT_COVERED,
3661                                                 ERRSRV, ERRbadpath);
3662                         }
3663                         reply_nterror(req, status);
3664                         return;
3665                 }
3666
3667                 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3668                 if (!NT_STATUS_IS_OK(status)) {
3669                         reply_nterror(req, status);
3670                         return;
3671                 }
3672                 status = check_name(conn, fname);
3673                 if (!NT_STATUS_IS_OK(status)) {
3674                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3675                         reply_nterror(req, status);
3676                         return;
3677                 }
3678
3679                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3680                         /* Always do lstat for UNIX calls. */
3681                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3682                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3683                                 reply_unixerror(req, ERRDOS, ERRbadpath);
3684                                 return;
3685                         }
3686                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3687                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3688                         reply_unixerror(req, ERRDOS, ERRbadpath);
3689                         return;
3690                 }
3691
3692                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3693                 delete_pending = get_delete_on_close_flag(fileid);
3694                 if (delete_pending) {
3695                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
3696                         return;
3697                 }
3698         }
3699
3700         nlink = sbuf.st_nlink;
3701
3702         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3703                 /* NTFS does not seem to count ".." */
3704                 nlink -= 1;
3705         }
3706
3707         if ((nlink > 0) && delete_pending) {
3708                 nlink -= 1;
3709         }
3710
3711         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3712                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3713                 return;
3714         }
3715
3716         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3717                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3718
3719         p = strrchr_m(fname,'/');
3720         if (!p)
3721                 base_name = fname;
3722         else
3723                 base_name = p+1;
3724
3725         mode = dos_mode(conn,fname,&sbuf);
3726         if (!mode)
3727                 mode = FILE_ATTRIBUTE_NORMAL;
3728
3729         fullpathname = fname;
3730         if (!(mode & aDIR))
3731                 file_size = get_file_size(sbuf);
3732
3733         /* Pull out any data sent here before we realloc. */
3734         switch (info_level) {
3735                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3736                 {
3737                         /* Pull any EA list from the data portion. */
3738                         uint32 ea_size;
3739
3740                         if (total_data < 4) {
3741                                 reply_nterror(
3742                                         req, NT_STATUS_INVALID_PARAMETER);
3743                                 return;
3744                         }
3745                         ea_size = IVAL(pdata,0);
3746
3747                         if (total_data > 0 && ea_size != total_data) {
3748                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3749 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3750                                 reply_nterror(
3751                                         req, NT_STATUS_INVALID_PARAMETER);
3752                                 return;
3753                         }
3754
3755                         if (!lp_ea_support(SNUM(conn))) {
3756                                 reply_doserror(req, ERRDOS,
3757                                                ERReasnotsupported);
3758                                 return;
3759                         }
3760
3761                         /* Pull out the list of names. */
3762                         ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3763                         if (!ea_list) {
3764                                 reply_nterror(
3765                                         req, NT_STATUS_INVALID_PARAMETER);
3766                                 return;
3767                         }
3768                         break;
3769                 }
3770
3771                 case SMB_QUERY_POSIX_LOCK:
3772                 {
3773                         if (fsp == NULL || fsp->fh->fd == -1) {
3774                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3775                                 return;
3776                         }
3777
3778                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3779                                 reply_nterror(
3780                                         req, NT_STATUS_INVALID_PARAMETER);
3781                                 return;
3782                         }
3783
3784                         /* Copy the lock range data. */
3785                         lock_data = (char *)TALLOC_MEMDUP(
3786                                 ctx, pdata, total_data);
3787                         if (!lock_data) {
3788                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3789                                 return;
3790                         }
3791                 }
3792                 default:
3793                         break;
3794         }
3795
3796         *pparams = (char *)SMB_REALLOC(*pparams,2);
3797         if (*pparams == NULL) {
3798                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3799                 return;
3800         }
3801         params = *pparams;
3802         SSVAL(params,0,0);
3803         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3804         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3805         if (*ppdata == NULL ) {
3806                 reply_nterror(req, NT_STATUS_NO_MEMORY);
3807                 return;
3808         }
3809         pdata = *ppdata;
3810         dstart = pdata;
3811         dend = dstart + data_size - 1;
3812
3813         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3814         mtime_ts = get_mtimespec(&sbuf);
3815         atime_ts = get_atimespec(&sbuf);
3816
3817         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3818
3819         if (fsp) {
3820                 if (!null_timespec(fsp->pending_modtime)) {
3821                         /* the pending modtime overrides the current modtime */
3822                         mtime_ts = fsp->pending_modtime;
3823                 }
3824         } else {
3825                 files_struct *fsp1;
3826                 /* Do we have this path open ? */
3827                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3828                 fsp1 = file_find_di_first(fileid);
3829                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3830                         /* the pending modtime overrides the current modtime */
3831                         mtime_ts = fsp1->pending_modtime;
3832                 }
3833                 if (fsp1 && fsp1->initial_allocation_size) {
3834                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3835                 }
3836         }
3837
3838         if (lp_dos_filetime_resolution(SNUM(conn))) {
3839                 dos_filetime_timespec(&create_time_ts);
3840                 dos_filetime_timespec(&mtime_ts);
3841                 dos_filetime_timespec(&atime_ts);
3842         }
3843
3844         create_time = convert_timespec_to_time_t(create_time_ts);
3845         mtime = convert_timespec_to_time_t(mtime_ts);
3846         atime = convert_timespec_to_time_t(atime_ts);
3847
3848         /* NT expects the name to be in an exact form of the *full*
3849            filename. See the trans2 torture test */
3850         if (ISDOT(base_name)) {
3851                 dos_fname = talloc_strdup(ctx, "\\");
3852                 if (!dos_fname) {
3853                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3854                         return;
3855                 }
3856         } else {
3857                 dos_fname = talloc_asprintf(ctx,
3858                                 "\\%s",
3859                                 fname);
3860                 if (!dos_fname) {
3861                         reply_nterror(req, NT_STATUS_NO_MEMORY);
3862                         return;
3863                 }
3864                 string_replace(dos_fname, '/', '\\');
3865         }
3866
3867         switch (info_level) {
3868                 case SMB_INFO_STANDARD:
3869                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3870                         data_size = 22;
3871                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3872                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3873                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3874                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3875                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3876                         SSVAL(pdata,l1_attrFile,mode);
3877                         break;
3878
3879                 case SMB_INFO_QUERY_EA_SIZE:
3880                 {
3881                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3882                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3883                         data_size = 26;
3884                         srv_put_dos_date2(pdata,0,create_time);
3885                         srv_put_dos_date2(pdata,4,atime);
3886                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3887                         SIVAL(pdata,12,(uint32)file_size);
3888                         SIVAL(pdata,16,(uint32)allocation_size);
3889                         SSVAL(pdata,20,mode);
3890                         SIVAL(pdata,22,ea_size);
3891                         break;
3892                 }
3893
3894                 case SMB_INFO_IS_NAME_VALID:
3895                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3896                         if (tran_call == TRANSACT2_QFILEINFO) {
3897                                 /* os/2 needs this ? really ?*/
3898                                 reply_doserror(req, ERRDOS, ERRbadfunc);
3899                                 return;
3900                         }
3901                         data_size = 0;
3902                         param_size = 0;
3903                         break;
3904
3905                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3906                 {
3907                         size_t total_ea_len = 0;
3908                         struct ea_list *ea_file_list = NULL;
3909
3910                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3911
3912                         ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3913                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3914
3915                         if (!ea_list || (total_ea_len > data_size)) {
3916                                 data_size = 4;
3917                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3918                                 break;
3919                         }
3920
3921                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3922                         break;
3923                 }
3924
3925                 case SMB_INFO_QUERY_ALL_EAS:
3926                 {
3927                         /* We have data_size bytes to put EA's into. */
3928                         size_t total_ea_len = 0;
3929
3930                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3931
3932                         ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
3933                         if (!ea_list || (total_ea_len > data_size)) {
3934                                 data_size = 4;
3935                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3936                                 break;
3937                         }
3938
3939                         data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
3940                         break;
3941                 }
3942
3943                 case SMB_FILE_BASIC_INFORMATION:
3944                 case SMB_QUERY_FILE_BASIC_INFO:
3945
3946                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3947                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3948                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3949                         } else {
3950                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3951                                 data_size = 40;
3952                                 SIVAL(pdata,36,0);
3953                         }
3954                         put_long_date_timespec(pdata,create_time_ts);
3955                         put_long_date_timespec(pdata+8,atime_ts);
3956                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3957                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3958                         SIVAL(pdata,32,mode);
3959
3960                         DEBUG(5,("SMB_QFBI - "));
3961                         DEBUG(5,("create: %s ", ctime(&create_time)));
3962                         DEBUG(5,("access: %s ", ctime(&atime)));
3963                         DEBUG(5,("write: %s ", ctime(&mtime)));
3964                         DEBUG(5,("change: %s ", ctime(&mtime)));
3965                         DEBUG(5,("mode: %x\n", mode));
3966                         break;
3967
3968                 case SMB_FILE_STANDARD_INFORMATION:
3969                 case SMB_QUERY_FILE_STANDARD_INFO:
3970
3971                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3972                         data_size = 24;
3973                         SOFF_T(pdata,0,allocation_size);
3974                         SOFF_T(pdata,8,file_size);
3975                         SIVAL(pdata,16,nlink);
3976                         SCVAL(pdata,20,delete_pending?1:0);
3977                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3978                         SSVAL(pdata,22,0); /* Padding. */
3979                         break;
3980
3981                 case SMB_FILE_EA_INFORMATION:
3982                 case SMB_QUERY_FILE_EA_INFO:
3983                 {
3984                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3985                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3986                         data_size = 4;
3987                         SIVAL(pdata,0,ea_size);
3988                         break;
3989                 }
3990
3991                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3992                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3993                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3994                 {
3995                         char mangled_name[13];
3996                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3997                         if (!name_to_8_3(base_name,mangled_name,
3998                                                 True,conn->params)) {
3999                                 reply_nterror(
4000                                         req,
4001                                         NT_STATUS_NO_MEMORY);
4002                         }
4003                         len = srvstr_push(dstart, req->flags2,
4004                                           pdata+4, mangled_name,
4005                                           PTR_DIFF(dend, pdata+4),
4006                                           STR_UNICODE);
4007                         data_size = 4 + len;
4008                         SIVAL(pdata,0,len);
4009                         break;
4010                 }
4011
4012                 case SMB_QUERY_FILE_NAME_INFO:
4013                         /*
4014                           this must be *exactly* right for ACLs on mapped drives to work
4015                          */
4016                         len = srvstr_push(dstart, req->flags2,
4017                                           pdata+4, dos_fname,
4018                                           PTR_DIFF(dend, pdata+4),
4019                                           STR_UNICODE);
4020                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4021                         data_size = 4 + len;
4022                         SIVAL(pdata,0,len);
4023                         break;
4024
4025                 case SMB_FILE_ALLOCATION_INFORMATION:
4026                 case SMB_QUERY_FILE_ALLOCATION_INFO:
4027                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4028                         data_size = 8;
4029                         SOFF_T(pdata,0,allocation_size);
4030                         break;
4031
4032                 case SMB_FILE_END_OF_FILE_INFORMATION:
4033                 case SMB_QUERY_FILE_END_OF_FILEINFO:
4034                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4035                         data_size = 8;
4036                         SOFF_T(pdata,0,file_size);
4037                         break;
4038
4039                 case SMB_QUERY_FILE_ALL_INFO:
4040                 case SMB_FILE_ALL_INFORMATION:
4041                 {
4042                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4043                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4044                         put_long_date_timespec(pdata,create_time_ts);
4045                         put_long_date_timespec(pdata+8,atime_ts);
4046                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4047                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4048                         SIVAL(pdata,32,mode);
4049                         SIVAL(pdata,36,0); /* padding. */
4050                         pdata += 40;
4051                         SOFF_T(pdata,0,allocation_size);
4052                         SOFF_T(pdata,8,file_size);
4053                         SIVAL(pdata,16,nlink);
4054                         SCVAL(pdata,20,delete_pending);
4055                         SCVAL(pdata,21,(mode&aDIR)?1:0);
4056                         SSVAL(pdata,22,0);
4057                         pdata += 24;
4058                         SIVAL(pdata,0,ea_size);
4059                         pdata += 4; /* EA info */
4060                         len = srvstr_push(dstart, req->flags2,
4061                                           pdata+4, dos_fname,
4062                                           PTR_DIFF(dend, pdata+4),
4063                                           STR_UNICODE);
4064                         SIVAL(pdata,0,len);
4065                         pdata += 4 + len;
4066                         data_size = PTR_DIFF(pdata,(*ppdata));
4067                         break;
4068                 }
4069                 case SMB_FILE_INTERNAL_INFORMATION:
4070                         /* This should be an index number - looks like
4071                            dev/ino to me :-) 
4072
4073                            I think this causes us to fail the IFSKIT
4074                            BasicFileInformationTest. -tpot */
4075
4076                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4077                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4078                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4079                         data_size = 8;
4080                         break;
4081
4082                 case SMB_FILE_ACCESS_INFORMATION:
4083                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4084                         SIVAL(pdata,0,access_mask);
4085                         data_size = 4;
4086                         break;
4087
4088                 case SMB_FILE_NAME_INFORMATION:
4089                         /* Pathname with leading '\'. */
4090                         {
4091                                 size_t byte_len;
4092                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4093                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4094                                 SIVAL(pdata,0,byte_len);
4095                                 data_size = 4 + byte_len;
4096                                 break;
4097                         }
4098
4099                 case SMB_FILE_DISPOSITION_INFORMATION:
4100                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4101                         data_size = 1;
4102                         SCVAL(pdata,0,delete_pending);
4103                         break;
4104
4105                 case SMB_FILE_POSITION_INFORMATION:
4106                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4107                         data_size = 8;
4108                         SOFF_T(pdata,0,pos);
4109                         break;
4110
4111                 case SMB_FILE_MODE_INFORMATION:
4112                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4113                         SIVAL(pdata,0,mode);
4114                         data_size = 4;
4115                         break;
4116
4117                 case SMB_FILE_ALIGNMENT_INFORMATION:
4118                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4119                         SIVAL(pdata,0,0); /* No alignment needed. */
4120                         data_size = 4;
4121                         break;
4122
4123 #if 0
4124                 /*
4125                  * NT4 server just returns "invalid query" to this - if we try to answer
4126                  * it then NTws gets a BSOD! (tridge).
4127                  * W2K seems to want this. JRA.
4128                  */
4129                 case SMB_QUERY_FILE_STREAM_INFO:
4130 #endif
4131                 case SMB_FILE_STREAM_INFORMATION:
4132                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
4133                         if (mode & aDIR) {
4134                                 data_size = 0;
4135                         } else {
4136                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
4137                                 SIVAL(pdata,0,0); /* ??? */
4138                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
4139                                 SOFF_T(pdata,8,file_size);
4140                                 SOFF_T(pdata,16,allocation_size);
4141                                 data_size = 24 + byte_len;
4142                         }
4143                         break;
4144
4145                 case SMB_QUERY_COMPRESSION_INFO:
4146                 case SMB_FILE_COMPRESSION_INFORMATION:
4147                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4148                         SOFF_T(pdata,0,file_size);
4149                         SIVAL(pdata,8,0); /* ??? */
4150                         SIVAL(pdata,12,0); /* ??? */
4151                         data_size = 16;
4152                         break;
4153
4154                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4155                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4156                         put_long_date_timespec(pdata,create_time_ts);
4157                         put_long_date_timespec(pdata+8,atime_ts);
4158                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4159                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4160                         SOFF_T(pdata,32,allocation_size);
4161                         SOFF_T(pdata,40,file_size);
4162                         SIVAL(pdata,48,mode);
4163                         SIVAL(pdata,52,0); /* ??? */
4164                         data_size = 56;
4165                         break;
4166
4167                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4168                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4169                         SIVAL(pdata,0,mode);
4170                         SIVAL(pdata,4,0);
4171                         data_size = 8;
4172                         break;
4173
4174                 /*
4175                  * CIFS UNIX Extensions.
4176                  */
4177
4178                 case SMB_QUERY_FILE_UNIX_BASIC:
4179
4180                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4181                         data_size = PTR_DIFF(pdata,(*ppdata));
4182
4183                         {
4184                                 int i;
4185                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4186
4187                                 for (i=0; i<100; i++)
4188                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4189                                 DEBUG(4,("\n"));
4190                         }
4191
4192                         break;
4193
4194                 case SMB_QUERY_FILE_UNIX_INFO2:
4195
4196                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4197                         data_size = PTR_DIFF(pdata,(*ppdata));
4198
4199                         {
4200                                 int i;
4201                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4202
4203                                 for (i=0; i<100; i++)
4204                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4205                                 DEBUG(4,("\n"));
4206                         }
4207
4208                         break;
4209
4210                 case SMB_QUERY_FILE_UNIX_LINK:
4211                         {
4212                                 char *buffer = TALLOC_SIZE(ctx, 1024);
4213
4214                                 if (!buffer) {
4215                                         reply_nterror(req, NT_STATUS_NO_MEMORY);
4216                                         return;
4217                                 }
4218
4219                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4220 #ifdef S_ISLNK
4221                                 if(!S_ISLNK(sbuf.st_mode)) {
4222                                         reply_unixerror(req, ERRSRV,
4223                                                         ERRbadlink);
4224                                         return;
4225                                 }
4226 #else
4227                                 reply_unixerror(req, ERRDOS, ERRbadlink);
4228                                 return;
4229 #endif
4230                                 len = SMB_VFS_READLINK(conn,fullpathname,
4231                                                 buffer, 1023);
4232                                 if (len == -1) {
4233                                         reply_unixerror(req, ERRDOS,
4234                                                         ERRnoaccess);
4235                                         return;
4236                                 }
4237                                 buffer[len] = 0;
4238                                 len = srvstr_push(dstart, req->flags2,
4239                                                   pdata, buffer,
4240                                                   PTR_DIFF(dend, pdata),
4241                                                   STR_TERMINATE);
4242                                 pdata += len;
4243                                 data_size = PTR_DIFF(pdata,(*ppdata));
4244
4245                                 break;
4246                         }
4247
4248 #if defined(HAVE_POSIX_ACLS)
4249                 case SMB_QUERY_POSIX_ACL:
4250                         {
4251                                 SMB_ACL_T file_acl = NULL;
4252                                 SMB_ACL_T def_acl = NULL;
4253                                 uint16 num_file_acls = 0;
4254                                 uint16 num_def_acls = 0;
4255
4256                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4257                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
4258                                 } else {
4259                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4260                                 }
4261
4262                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4263                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4264                                                 fname ));
4265                                         reply_nterror(
4266                                                 req,
4267                                                 NT_STATUS_NOT_IMPLEMENTED);
4268                                         return;
4269                                 }
4270
4271                                 if (S_ISDIR(sbuf.st_mode)) {
4272                                         if (fsp && fsp->is_directory) {
4273                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4274                                         } else {
4275                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4276                                         }
4277                                         def_acl = free_empty_sys_acl(conn, def_acl);
4278                                 }
4279
4280                                 num_file_acls = count_acl_entries(conn, file_acl);
4281                                 num_def_acls = count_acl_entries(conn, def_acl);
4282
4283                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4284                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4285                                                 data_size,
4286                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4287                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4288                                         if (file_acl) {
4289                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4290                                         }
4291                                         if (def_acl) {
4292                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4293                                         }
4294                                         reply_nterror(
4295                                                 req,
4296                                                 NT_STATUS_BUFFER_TOO_SMALL);
4297                                         return;
4298                                 }
4299
4300                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4301                                 SSVAL(pdata,2,num_file_acls);
4302                                 SSVAL(pdata,4,num_def_acls);
4303                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4304                                         if (file_acl) {
4305                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4306                                         }
4307                                         if (def_acl) {
4308                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4309                                         }
4310                                         reply_nterror(
4311                                                 req, NT_STATUS_INTERNAL_ERROR);
4312                                         return;
4313                                 }
4314                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4315                                         if (file_acl) {
4316                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4317                                         }
4318                                         if (def_acl) {
4319                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4320                                         }
4321                                         reply_nterror(
4322                                                 req,
4323                                                 NT_STATUS_INTERNAL_ERROR);
4324                                         return;
4325                                 }
4326
4327                                 if (file_acl) {
4328                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4329                                 }
4330                                 if (def_acl) {
4331                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4332                                 }
4333                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4334                                 break;
4335                         }
4336 #endif
4337
4338
4339                 case SMB_QUERY_POSIX_LOCK:
4340                 {
4341                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4342                         SMB_BIG_UINT count;
4343                         SMB_BIG_UINT offset;
4344                         uint32 lock_pid;
4345                         enum brl_type lock_type;
4346
4347                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4348                                 reply_nterror(
4349                                         req, NT_STATUS_INVALID_PARAMETER);
4350                                 return;
4351                         }
4352
4353                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4354                                 case POSIX_LOCK_TYPE_READ:
4355                                         lock_type = READ_LOCK;
4356                                         break;
4357                                 case POSIX_LOCK_TYPE_WRITE:
4358                                         lock_type = WRITE_LOCK;
4359                                         break;
4360                                 case POSIX_LOCK_TYPE_UNLOCK:
4361                                 default:
4362                                         /* There's no point in asking for an unlock... */
4363                                         reply_nterror(
4364                                                 req,
4365                                                 NT_STATUS_INVALID_PARAMETER);
4366                                         return;
4367                         }
4368
4369                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4370 #if defined(HAVE_LONGLONG)
4371                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4372                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4373                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4374                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4375 #else /* HAVE_LONGLONG */
4376                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4377                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4378 #endif /* HAVE_LONGLONG */
4379
4380                         status = query_lock(fsp,
4381                                         &lock_pid,
4382                                         &count,
4383                                         &offset,
4384                                         &lock_type,
4385                                         POSIX_LOCK);
4386
4387                         if (ERROR_WAS_LOCK_DENIED(status)) {
4388                                 /* Here we need to report who has it locked... */
4389                                 data_size = POSIX_LOCK_DATA_SIZE;
4390
4391                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4392                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4393                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4394 #if defined(HAVE_LONGLONG)
4395                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4396                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4397                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4398                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4399 #else /* HAVE_LONGLONG */
4400                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4401                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4402 #endif /* HAVE_LONGLONG */
4403
4404                         } else if (NT_STATUS_IS_OK(status)) {
4405                                 /* For success we just return a copy of what we sent
4406                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4407                                 data_size = POSIX_LOCK_DATA_SIZE;
4408                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4409                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4410                         } else {
4411                                 reply_nterror(req, status);
4412                                 return;
4413                         }
4414                         break;
4415                 }
4416
4417                 default:
4418                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4419                         return;
4420         }
4421
4422         send_trans2_replies(req, params, param_size, *ppdata, data_size,
4423                             max_data_bytes);
4424
4425         return;
4426 }
4427
4428 /****************************************************************************
4429  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4430  code.
4431 ****************************************************************************/
4432
4433 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4434                 connection_struct *conn,
4435                 const char *oldname_in,
4436                 const char *newname_in)
4437 {
4438         SMB_STRUCT_STAT sbuf1, sbuf2;
4439         char *last_component_oldname = NULL;
4440         char *last_component_newname = NULL;
4441         char *oldname = NULL;
4442         char *newname = NULL;
4443         NTSTATUS status = NT_STATUS_OK;
4444
4445         ZERO_STRUCT(sbuf1);
4446         ZERO_STRUCT(sbuf2);
4447
4448         status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4449                         &last_component_oldname, &sbuf1);
4450         if (!NT_STATUS_IS_OK(status)) {
4451                 return status;
4452         }
4453
4454         status = check_name(conn, oldname);
4455         if (!NT_STATUS_IS_OK(status)) {
4456                 return status;
4457         }
4458
4459         /* source must already exist. */
4460         if (!VALID_STAT(sbuf1)) {
4461                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4462         }
4463
4464         status = unix_convert(ctx, conn, newname_in, False, &newname,
4465                         &last_component_newname, &sbuf2);
4466         if (!NT_STATUS_IS_OK(status)) {
4467                 return status;
4468         }
4469
4470         status = check_name(conn, newname);
4471         if (!NT_STATUS_IS_OK(status)) {
4472                 return status;
4473         }
4474
4475         /* Disallow if newname already exists. */
4476         if (VALID_STAT(sbuf2)) {
4477                 return NT_STATUS_OBJECT_NAME_COLLISION;
4478         }
4479
4480         /* No links from a directory. */
4481         if (S_ISDIR(sbuf1.st_mode)) {
4482                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4483         }
4484
4485         /* Ensure this is within the share. */
4486         status = check_reduced_name(conn, oldname);
4487         if (!NT_STATUS_IS_OK(status)) {
4488                 return status;
4489         }
4490
4491         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4492
4493         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4494                 status = map_nt_error_from_unix(errno);
4495                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4496                                 nt_errstr(status), newname, oldname));
4497         }
4498
4499         return status;
4500 }
4501
4502 /****************************************************************************
4503  Deal with setting the time from any of the setfilepathinfo functions.
4504 ****************************************************************************/
4505
4506 static NTSTATUS smb_set_file_time(connection_struct *conn,
4507                                 files_struct *fsp,
4508                                 const char *fname,
4509                                 const SMB_STRUCT_STAT *psbuf,
4510                                 struct timespec ts[2])
4511 {
4512         uint32 action =
4513                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4514                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4515
4516         
4517         if (!VALID_STAT(*psbuf)) {
4518                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4519         }
4520
4521         /* get some defaults (no modifications) if any info is zero or -1. */
4522         if (null_timespec(ts[0])) {
4523                 ts[0] = get_atimespec(psbuf);
4524                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4525         }
4526
4527         if (null_timespec(ts[1])) {
4528                 ts[1] = get_mtimespec(psbuf);
4529                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4530         }
4531
4532         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4533         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4534
4535         /*
4536          * Try and set the times of this file if
4537          * they are different from the current values.
4538          */
4539
4540         {
4541                 struct timespec mts = get_mtimespec(psbuf);
4542                 struct timespec ats = get_atimespec(psbuf);
4543                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4544                         return NT_STATUS_OK;
4545                 }
4546         }
4547
4548         if(fsp != NULL) {
4549                 /*
4550                  * This was a setfileinfo on an open file.
4551                  * NT does this a lot. We also need to 
4552                  * set the time here, as it can be read by 
4553                  * FindFirst/FindNext and with the patch for bug #2045
4554                  * in smbd/fileio.c it ensures that this timestamp is
4555                  * kept sticky even after a write. We save the request
4556                  * away and will set it on file close and after a write. JRA.
4557                  */
4558
4559                 if (!null_timespec(ts[1])) {
4560                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4561                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4562                         fsp_set_pending_modtime(fsp, ts[1]);
4563                 }
4564
4565         }
4566         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4567
4568         if(file_ntimes(conn, fname, ts)!=0) {
4569                 return map_nt_error_from_unix(errno);
4570         }
4571         if (action != 0) {
4572                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4573         }
4574         return NT_STATUS_OK;
4575 }
4576
4577 /****************************************************************************
4578  Deal with setting the dosmode from any of the setfilepathinfo functions.
4579 ****************************************************************************/
4580
4581 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4582                                 const char *fname,
4583                                 SMB_STRUCT_STAT *psbuf,
4584                                 uint32 dosmode)
4585 {
4586         if (!VALID_STAT(*psbuf)) {
4587                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4588         }
4589
4590         if (dosmode) {
4591                 if (S_ISDIR(psbuf->st_mode)) {
4592                         dosmode |= aDIR;
4593                 } else {
4594                         dosmode &= ~aDIR;
4595                 }
4596         }
4597
4598         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4599
4600         /* check the mode isn't different, before changing it */
4601         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4602
4603                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4604                                         fname, (unsigned int)dosmode ));
4605
4606                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4607                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4608                                                 fname, strerror(errno)));
4609                         return map_nt_error_from_unix(errno);
4610                 }
4611         }
4612         return NT_STATUS_OK;
4613 }
4614
4615 /****************************************************************************
4616  Deal with setting the size from any of the setfilepathinfo functions.
4617 ****************************************************************************/
4618
4619 static NTSTATUS smb_set_file_size(connection_struct *conn,
4620                                   struct smb_request *req,
4621                                 files_struct *fsp,
4622                                 const char *fname,
4623                                 SMB_STRUCT_STAT *psbuf,
4624                                 SMB_OFF_T size)
4625 {
4626         NTSTATUS status = NT_STATUS_OK;
4627         files_struct *new_fsp = NULL;
4628
4629         if (!VALID_STAT(*psbuf)) {
4630                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4631         }
4632
4633         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4634
4635         if (size == get_file_size(*psbuf)) {
4636                 return NT_STATUS_OK;
4637         }
4638
4639         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4640                 fname, (double)size ));
4641
4642         if (fsp && fsp->fh->fd != -1) {
4643                 /* Handle based call. */
4644                 if (vfs_set_filelen(fsp, size) == -1) {
4645                         return map_nt_error_from_unix(errno);
4646                 }
4647                 return NT_STATUS_OK;
4648         }
4649
4650         status = open_file_ntcreate(conn, req, fname, psbuf,
4651                                 FILE_WRITE_DATA,
4652                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4653                                 FILE_OPEN,
4654                                 0,
4655                                 FILE_ATTRIBUTE_NORMAL,
4656                                 FORCE_OPLOCK_BREAK_TO_NONE,
4657                                 NULL, &new_fsp);
4658         
4659         if (!NT_STATUS_IS_OK(status)) {
4660                 /* NB. We check for open_was_deferred in the caller. */
4661                 return status;
4662         }
4663
4664         if (vfs_set_filelen(new_fsp, size) == -1) {
4665                 status = map_nt_error_from_unix(errno);
4666                 close_file(new_fsp,NORMAL_CLOSE);
4667                 return status;
4668         }
4669
4670         close_file(new_fsp,NORMAL_CLOSE);
4671         return NT_STATUS_OK;
4672 }
4673
4674 /****************************************************************************
4675  Deal with SMB_INFO_SET_EA.
4676 ****************************************************************************/
4677
4678 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4679                                 const char *pdata,
4680                                 int total_data,
4681                                 files_struct *fsp,
4682                                 const char *fname)
4683 {
4684         struct ea_list *ea_list = NULL;
4685         TALLOC_CTX *ctx = NULL;
4686         NTSTATUS status = NT_STATUS_OK;
4687
4688         if (total_data < 10) {
4689
4690                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4691                    length. They seem to have no effect. Bug #3212. JRA */
4692
4693                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4694                         /* We're done. We only get EA info in this call. */
4695                         return NT_STATUS_OK;
4696                 }
4697
4698                 return NT_STATUS_INVALID_PARAMETER;
4699         }
4700
4701         if (IVAL(pdata,0) > total_data) {
4702                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4703                         IVAL(pdata,0), (unsigned int)total_data));
4704                 return NT_STATUS_INVALID_PARAMETER;
4705         }
4706
4707         ctx = talloc_init("SMB_INFO_SET_EA");
4708         if (!ctx) {
4709                 return NT_STATUS_NO_MEMORY;
4710         }
4711         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4712         if (!ea_list) {
4713                 talloc_destroy(ctx);
4714                 return NT_STATUS_INVALID_PARAMETER;
4715         }
4716         status = set_ea(conn, fsp, fname, ea_list);
4717         talloc_destroy(ctx);
4718
4719         return status;
4720 }
4721
4722 /****************************************************************************
4723  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4724 ****************************************************************************/
4725
4726 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4727                                 const char *pdata,
4728                                 int total_data,
4729                                 files_struct *fsp,
4730                                 const char *fname,
4731                                 SMB_STRUCT_STAT *psbuf)
4732 {
4733         NTSTATUS status = NT_STATUS_OK;
4734         BOOL delete_on_close;
4735         uint32 dosmode = 0;
4736
4737         if (total_data < 1) {
4738                 return NT_STATUS_INVALID_PARAMETER;
4739         }
4740
4741         if (fsp == NULL) {
4742                 return NT_STATUS_INVALID_HANDLE;
4743         }
4744
4745         delete_on_close = (CVAL(pdata,0) ? True : False);
4746         dosmode = dos_mode(conn, fname, psbuf);
4747
4748         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4749                 "delete_on_close = %u\n",
4750                 fsp->fsp_name,
4751                 (unsigned int)dosmode,
4752                 (unsigned int)delete_on_close ));
4753
4754         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4755  
4756         if (!NT_STATUS_IS_OK(status)) {
4757                 return status;
4758         }
4759
4760         /* The set is across all open files on this dev/inode pair. */
4761         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4762                 return NT_STATUS_ACCESS_DENIED;
4763         }
4764         return NT_STATUS_OK;
4765 }
4766
4767 /****************************************************************************
4768  Deal with SMB_FILE_POSITION_INFORMATION.
4769 ****************************************************************************/
4770
4771 static NTSTATUS smb_file_position_information(connection_struct *conn,
4772                                 const char *pdata,
4773                                 int total_data,
4774                                 files_struct *fsp)
4775 {
4776         SMB_BIG_UINT position_information;
4777
4778         if (total_data < 8) {
4779                 return NT_STATUS_INVALID_PARAMETER;
4780         }
4781
4782         if (fsp == NULL) {
4783                 /* Ignore on pathname based set. */
4784                 return NT_STATUS_OK;
4785         }
4786
4787         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4788 #ifdef LARGE_SMB_OFF_T
4789         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4790 #else /* LARGE_SMB_OFF_T */
4791         if (IVAL(pdata,4) != 0) {
4792                 /* more than 32 bits? */
4793                 return NT_STATUS_INVALID_PARAMETER;
4794         }
4795 #endif /* LARGE_SMB_OFF_T */
4796
4797         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4798                 fsp->fsp_name, (double)position_information ));
4799         fsp->fh->position_information = position_information;
4800         return NT_STATUS_OK;
4801 }
4802
4803 /****************************************************************************
4804  Deal with SMB_FILE_MODE_INFORMATION.
4805 ****************************************************************************/
4806
4807 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4808                                 const char *pdata,
4809                                 int total_data)
4810 {
4811         uint32 mode;
4812
4813         if (total_data < 4) {
4814                 return NT_STATUS_INVALID_PARAMETER;
4815         }
4816         mode = IVAL(pdata,0);
4817         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4818                 return NT_STATUS_INVALID_PARAMETER;
4819         }
4820         return NT_STATUS_OK;
4821 }
4822
4823 /****************************************************************************
4824  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4825 ****************************************************************************/
4826
4827 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4828                                        struct smb_request *req,
4829                                        const char *pdata,
4830                                        int total_data,
4831                                        const char *fname)
4832 {
4833         char *link_target = NULL;
4834         const char *newname = fname;
4835         NTSTATUS status = NT_STATUS_OK;
4836         TALLOC_CTX *ctx = talloc_tos();
4837
4838         /* Set a symbolic link. */
4839         /* Don't allow this if follow links is false. */
4840
4841         if (total_data == 0) {
4842                 return NT_STATUS_INVALID_PARAMETER;
4843         }
4844
4845         if (!lp_symlinks(SNUM(conn))) {
4846                 return NT_STATUS_ACCESS_DENIED;
4847         }
4848
4849         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
4850                     total_data, STR_TERMINATE);
4851
4852         if (!link_target) {
4853                 return NT_STATUS_INVALID_PARAMETER;
4854         }
4855
4856         /* !widelinks forces the target path to be within the share. */
4857         /* This means we can interpret the target as a pathname. */
4858         if (!lp_widelinks(SNUM(conn))) {
4859                 char *rel_name = NULL;
4860                 char *last_dirp = NULL;
4861
4862                 if (*link_target == '/') {
4863                         /* No absolute paths allowed. */
4864                         return NT_STATUS_ACCESS_DENIED;
4865                 }
4866                 rel_name = talloc_strdup(ctx,newname);
4867                 if (!rel_name) {
4868                         return NT_STATUS_NO_MEMORY;
4869                 }
4870                 last_dirp = strrchr_m(rel_name, '/');
4871                 if (last_dirp) {
4872                         last_dirp[1] = '\0';
4873                 } else {
4874                         rel_name = talloc_strdup(ctx,"./");
4875                         if (!rel_name) {
4876                                 return NT_STATUS_NO_MEMORY;
4877                         }
4878                 }
4879                 rel_name = talloc_asprintf_append(ctx,
4880                                 "%s",
4881                                 link_target);
4882                 if (!rel_name) {
4883                         return NT_STATUS_NO_MEMORY;
4884                 }
4885
4886                 status = check_name(conn, rel_name);
4887                 if (!NT_STATUS_IS_OK(status)) {
4888                         return status;
4889                 }
4890         }
4891
4892         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4893                         newname, link_target ));
4894
4895         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4896                 return map_nt_error_from_unix(errno);
4897         }
4898
4899         return NT_STATUS_OK;
4900 }
4901
4902 /****************************************************************************
4903  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4904 ****************************************************************************/
4905
4906 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4907                                         struct smb_request *req,
4908                                         const char *pdata, int total_data,
4909                                         const char *fname)
4910 {
4911         char *oldname = NULL;
4912         TALLOC_CTX *ctx = talloc_tos();
4913         NTSTATUS status = NT_STATUS_OK;
4914
4915         /* Set a hard link. */
4916         if (total_data == 0) {
4917                 return NT_STATUS_INVALID_PARAMETER;
4918         }
4919
4920         srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
4921                         total_data, STR_TERMINATE, &status);
4922         if (!NT_STATUS_IS_OK(status)) {
4923                 return status;
4924         }
4925
4926         status = resolve_dfspath(ctx, conn,
4927                                 req->flags2 & FLAGS2_DFS_PATHNAMES,
4928                                 oldname,
4929                                 &oldname);
4930         if (!NT_STATUS_IS_OK(status)) {
4931                 return status;
4932         }
4933
4934         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4935                 fname, oldname));
4936
4937         return hardlink_internals(ctx, conn, oldname, fname);
4938 }
4939
4940 /****************************************************************************
4941  Deal with SMB_FILE_RENAME_INFORMATION.
4942 ****************************************************************************/
4943
4944 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4945                                             struct smb_request *req,
4946                                             const char *pdata,
4947                                             int total_data,
4948                                             files_struct *fsp,
4949                                             const char *fname)
4950 {
4951         BOOL overwrite;
4952         uint32 root_fid;
4953         uint32 len;
4954         char *newname = NULL;
4955         char *base_name = NULL;
4956         BOOL dest_has_wcard = False;
4957         NTSTATUS status = NT_STATUS_OK;
4958         char *p;
4959         TALLOC_CTX *ctx = talloc_tos();
4960
4961         if (total_data < 13) {
4962                 return NT_STATUS_INVALID_PARAMETER;
4963         }
4964
4965         overwrite = (CVAL(pdata,0) ? True : False);
4966         root_fid = IVAL(pdata,4);
4967         len = IVAL(pdata,8);
4968
4969         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4970                 return NT_STATUS_INVALID_PARAMETER;
4971         }
4972
4973         srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
4974                               len, 0, &status,
4975                               &dest_has_wcard);
4976         if (!NT_STATUS_IS_OK(status)) {
4977                 return status;
4978         }
4979
4980         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4981                                 newname));
4982
4983         status = resolve_dfspath_wcard(ctx, conn,
4984                                        req->flags2 & FLAGS2_DFS_PATHNAMES,
4985                                        newname,
4986                                        &newname,
4987                                        &dest_has_wcard);
4988         if (!NT_STATUS_IS_OK(status)) {
4989                 return status;
4990         }
4991
4992         /* Check the new name has no '/' characters. */
4993         if (strchr_m(newname, '/')) {
4994                 return NT_STATUS_NOT_SUPPORTED;
4995         }
4996
4997         /* Create the base directory. */
4998         base_name = talloc_strdup(ctx, fname);
4999         if (!base_name) {
5000                 return NT_STATUS_NO_MEMORY;
5001         }
5002         p = strrchr_m(base_name, '/');
5003         if (p) {
5004                 p[1] = '\0';
5005         } else {
5006                 base_name = talloc_strdup(ctx, "./");
5007                 if (!base_name) {
5008                         return NT_STATUS_NO_MEMORY;
5009                 }
5010         }
5011         /* Append the new name. */
5012         base_name = talloc_asprintf_append(base_name,
5013                         "%s",
5014                         newname);
5015         if (!base_name) {
5016                 return NT_STATUS_NO_MEMORY;
5017         }
5018
5019         if (fsp) {
5020                 SMB_STRUCT_STAT sbuf;
5021                 char *newname_last_component = NULL;
5022
5023                 ZERO_STRUCT(sbuf);
5024
5025                 status = unix_convert(ctx, conn, newname, False,
5026                                         &newname,
5027                                         &newname_last_component,
5028                                         &sbuf);
5029
5030                 /* If an error we expect this to be
5031                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5032
5033                 if (!NT_STATUS_IS_OK(status)
5034                     && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5035                                         status)) {
5036                         return status;
5037                 }
5038
5039                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5040                         fsp->fnum, fsp->fsp_name, base_name ));
5041                 status = rename_internals_fsp(conn, fsp, base_name,
5042                                               newname_last_component, 0,
5043                                               overwrite);
5044         } else {
5045                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5046                         fname, base_name ));
5047                 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5048                                           overwrite, False, dest_has_wcard);
5049         }
5050
5051         return status;
5052 }
5053
5054 /****************************************************************************
5055  Deal with SMB_SET_POSIX_ACL.
5056 ****************************************************************************/
5057
5058 #if defined(HAVE_POSIX_ACLS)
5059 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5060                                 const char *pdata,
5061                                 int total_data,
5062                                 files_struct *fsp,
5063                                 const char *fname,
5064                                 SMB_STRUCT_STAT *psbuf)
5065 {
5066         uint16 posix_acl_version;
5067         uint16 num_file_acls;
5068         uint16 num_def_acls;
5069         BOOL valid_file_acls = True;
5070         BOOL valid_def_acls = True;
5071
5072         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5073                 return NT_STATUS_INVALID_PARAMETER;
5074         }
5075         posix_acl_version = SVAL(pdata,0);
5076         num_file_acls = SVAL(pdata,2);
5077         num_def_acls = SVAL(pdata,4);
5078
5079         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5080                 valid_file_acls = False;
5081                 num_file_acls = 0;
5082         }
5083
5084         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5085                 valid_def_acls = False;
5086                 num_def_acls = 0;
5087         }
5088
5089         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5090                 return NT_STATUS_INVALID_PARAMETER;
5091         }
5092
5093         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5094                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5095                 return NT_STATUS_INVALID_PARAMETER;
5096         }
5097
5098         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5099                 fname ? fname : fsp->fsp_name,
5100                 (unsigned int)num_file_acls,
5101                 (unsigned int)num_def_acls));
5102
5103         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5104                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5105                 return map_nt_error_from_unix(errno);
5106         }
5107
5108         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5109                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
5110                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5111                 return map_nt_error_from_unix(errno);
5112         }
5113         return NT_STATUS_OK;
5114 }
5115 #endif
5116
5117 /****************************************************************************
5118  Deal with SMB_SET_POSIX_LOCK.
5119 ****************************************************************************/
5120
5121 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5122                                 const uint8 *inbuf,
5123                                 int length,
5124                                 const char *pdata,
5125                                 int total_data,
5126                                 files_struct *fsp)
5127 {
5128         SMB_BIG_UINT count;
5129         SMB_BIG_UINT offset;
5130         uint32 lock_pid;
5131         BOOL blocking_lock = False;
5132         enum brl_type lock_type;
5133         NTSTATUS status = NT_STATUS_OK;
5134
5135         if (fsp == NULL || fsp->fh->fd == -1) {
5136                 return NT_STATUS_INVALID_HANDLE;
5137         }
5138
5139         if (total_data != POSIX_LOCK_DATA_SIZE) {
5140                 return NT_STATUS_INVALID_PARAMETER;
5141         }
5142
5143         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5144                 case POSIX_LOCK_TYPE_READ:
5145                         lock_type = READ_LOCK;
5146                         break;
5147                 case POSIX_LOCK_TYPE_WRITE:
5148                         /* Return the right POSIX-mappable error code for files opened read-only. */
5149                         if (!fsp->can_write) {
5150                                 return NT_STATUS_INVALID_HANDLE;
5151                         }
5152                         lock_type = WRITE_LOCK;
5153                         break;
5154                 case POSIX_LOCK_TYPE_UNLOCK:
5155                         lock_type = UNLOCK_LOCK;
5156                         break;
5157                 default:
5158                         return NT_STATUS_INVALID_PARAMETER;
5159         }
5160
5161         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5162                 blocking_lock = False;
5163         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5164                 blocking_lock = True;
5165         } else {
5166                 return NT_STATUS_INVALID_PARAMETER;
5167         }
5168
5169         if (!lp_blocking_locks(SNUM(conn))) { 
5170                 blocking_lock = False;
5171         }
5172
5173         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5174 #if defined(HAVE_LONGLONG)
5175         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5176                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5177         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5178                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5179 #else /* HAVE_LONGLONG */
5180         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5181         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5182 #endif /* HAVE_LONGLONG */
5183
5184         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5185                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
5186                 fsp->fsp_name,
5187                 (unsigned int)lock_type,
5188                 (unsigned int)lock_pid,
5189                 (double)count,
5190                 (double)offset ));
5191
5192         if (lock_type == UNLOCK_LOCK) {
5193                 status = do_unlock(smbd_messaging_context(),
5194                                 fsp,
5195                                 lock_pid,
5196                                 count,
5197                                 offset,
5198                                 POSIX_LOCK);
5199         } else {
5200                 uint32 block_smbpid;
5201
5202                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5203                                                         fsp,
5204                                                         lock_pid,
5205                                                         count,
5206                                                         offset,
5207                                                         lock_type,
5208                                                         POSIX_LOCK,
5209                                                         blocking_lock,
5210                                                         &status,
5211                                                         &block_smbpid);
5212
5213                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5214                         /*
5215                          * A blocking lock was requested. Package up
5216                          * this smb into a queued request and push it
5217                          * onto the blocking lock queue.
5218                          */
5219                         if(push_blocking_lock_request(br_lck,
5220                                                 (char *)inbuf, length,
5221                                                 fsp,
5222                                                 -1, /* infinite timeout. */
5223                                                 0,
5224                                                 lock_pid,
5225                                                 lock_type,
5226                                                 POSIX_LOCK,
5227                                                 offset,
5228                                                 count,
5229                                                 block_smbpid)) {
5230                                 TALLOC_FREE(br_lck);
5231                                 return status;
5232                         }
5233                 }
5234                 TALLOC_FREE(br_lck);
5235         }
5236
5237         return status;
5238 }
5239
5240 /****************************************************************************
5241  Deal with SMB_INFO_STANDARD.
5242 ****************************************************************************/
5243
5244 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5245                                         const char *pdata,
5246                                         int total_data,
5247                                         files_struct *fsp,
5248                                         const char *fname,
5249                                         const SMB_STRUCT_STAT *psbuf)
5250 {
5251         struct timespec ts[2];
5252
5253         if (total_data < 12) {
5254                 return NT_STATUS_INVALID_PARAMETER;
5255         }
5256
5257         /* access time */
5258         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5259         /* write time */
5260         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5261
5262         DEBUG(10,("smb_set_info_standard: file %s\n",
5263                 fname ? fname : fsp->fsp_name ));
5264
5265         return smb_set_file_time(conn,
5266                                 fsp,
5267                                 fname,
5268                                 psbuf,
5269                                 ts);
5270 }
5271
5272 /****************************************************************************
5273  Deal with SMB_SET_FILE_BASIC_INFO.
5274 ****************************************************************************/
5275
5276 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5277                                         const char *pdata,
5278                                         int total_data,
5279                                         files_struct *fsp,
5280                                         const char *fname,
5281                                         SMB_STRUCT_STAT *psbuf)
5282 {
5283         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5284         struct timespec write_time;
5285         struct timespec changed_time;
5286         uint32 dosmode = 0;
5287         struct timespec ts[2];
5288         NTSTATUS status = NT_STATUS_OK;
5289
5290         if (total_data < 36) {
5291                 return NT_STATUS_INVALID_PARAMETER;
5292         }
5293
5294         /* Set the attributes */
5295         dosmode = IVAL(pdata,32);
5296         status = smb_set_file_dosmode(conn,
5297                                         fname,
5298                                         psbuf,
5299                                         dosmode);
5300         if (!NT_STATUS_IS_OK(status)) {
5301                 return status;
5302         }
5303
5304         /* Ignore create time at offset pdata. */
5305
5306         /* access time */
5307         ts[0] = interpret_long_date(pdata+8);
5308
5309         write_time = interpret_long_date(pdata+16);
5310         changed_time = interpret_long_date(pdata+24);
5311
5312         /* mtime */
5313         ts[1] = timespec_min(&write_time, &changed_time);
5314
5315         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5316                 ts[1] = write_time;
5317         }
5318
5319         /* Prefer a defined time to an undefined one. */
5320         if (null_timespec(ts[1])) {
5321                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
5322         }
5323
5324         DEBUG(10,("smb_set_file_basic_info: file %s\n",
5325                 fname ? fname : fsp->fsp_name ));
5326
5327         return smb_set_file_time(conn,
5328                                 fsp,
5329                                 fname,
5330                                 psbuf,
5331                                 ts);
5332 }
5333
5334 /****************************************************************************
5335  Deal with SMB_SET_FILE_ALLOCATION_INFO.
5336 ****************************************************************************/
5337
5338 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5339                                              struct smb_request *req,
5340                                         const char *pdata,
5341                                         int total_data,
5342                                         files_struct *fsp,
5343                                         const char *fname,
5344                                         SMB_STRUCT_STAT *psbuf)
5345 {
5346         SMB_BIG_UINT allocation_size = 0;
5347         NTSTATUS status = NT_STATUS_OK;
5348         files_struct *new_fsp = NULL;
5349
5350         if (!VALID_STAT(*psbuf)) {
5351                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5352         }
5353
5354         if (total_data < 8) {
5355                 return NT_STATUS_INVALID_PARAMETER;
5356         }
5357
5358         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5359 #ifdef LARGE_SMB_OFF_T
5360         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5361 #else /* LARGE_SMB_OFF_T */
5362         if (IVAL(pdata,4) != 0) {
5363                 /* more than 32 bits? */
5364                 return NT_STATUS_INVALID_PARAMETER;
5365         }
5366 #endif /* LARGE_SMB_OFF_T */
5367
5368         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5369                         fname, (double)allocation_size ));
5370
5371         if (allocation_size) {
5372                 allocation_size = smb_roundup(conn, allocation_size);
5373         }
5374
5375         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5376                         fname, (double)allocation_size ));
5377
5378         if (fsp && fsp->fh->fd != -1) {
5379                 /* Open file handle. */
5380                 /* Only change if needed. */
5381                 if (allocation_size != get_file_size(*psbuf)) {
5382                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5383                                 return map_nt_error_from_unix(errno);
5384                         }
5385                 }
5386                 /* But always update the time. */
5387                 if (null_timespec(fsp->pending_modtime)) {
5388                         /*
5389                          * This is equivalent to a write. Ensure it's seen immediately
5390                          * if there are no pending writes.
5391                          */
5392                         set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5393                 }
5394                 return NT_STATUS_OK;
5395         }
5396
5397         /* Pathname or stat or directory file. */
5398
5399         status = open_file_ntcreate(conn, req, fname, psbuf,
5400                                 FILE_WRITE_DATA,
5401                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5402                                 FILE_OPEN,
5403                                 0,
5404                                 FILE_ATTRIBUTE_NORMAL,
5405                                 FORCE_OPLOCK_BREAK_TO_NONE,
5406                                 NULL, &new_fsp);
5407
5408         if (!NT_STATUS_IS_OK(status)) {
5409                 /* NB. We check for open_was_deferred in the caller. */
5410                 return status;
5411         }
5412
5413         /* Only change if needed. */
5414         if (allocation_size != get_file_size(*psbuf)) {
5415                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5416                         status = map_nt_error_from_unix(errno);
5417                         close_file(new_fsp,NORMAL_CLOSE);
5418                         return status;
5419                 }
5420         }
5421
5422         /* Changing the allocation size should set the last mod time. */
5423         /* Don't need to call set_filetime as this will be flushed on
5424          * close. */
5425
5426         fsp_set_pending_modtime(new_fsp, timespec_current());
5427
5428         close_file(new_fsp,NORMAL_CLOSE);
5429         return NT_STATUS_OK;
5430 }
5431
5432 /****************************************************************************
5433  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5434 ****************************************************************************/
5435
5436 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5437                                               struct smb_request *req,
5438                                         const char *pdata,
5439                                         int total_data,
5440                                         files_struct *fsp,
5441                                         const char *fname,
5442                                         SMB_STRUCT_STAT *psbuf)
5443 {
5444         SMB_OFF_T size;
5445
5446         if (total_data < 8) {
5447                 return NT_STATUS_INVALID_PARAMETER;
5448         }
5449
5450         size = IVAL(pdata,0);
5451 #ifdef LARGE_SMB_OFF_T
5452         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5453 #else /* LARGE_SMB_OFF_T */
5454         if (IVAL(pdata,4) != 0) {
5455                 /* more than 32 bits? */
5456                 return NT_STATUS_INVALID_PARAMETER;
5457         }
5458 #endif /* LARGE_SMB_OFF_T */
5459         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5460                 "file %s to %.0f\n", fname, (double)size ));
5461
5462         return smb_set_file_size(conn, req,
5463                                 fsp,
5464                                 fname,
5465                                 psbuf,
5466                                 size);
5467 }
5468
5469 /****************************************************************************
5470  Allow a UNIX info mknod.
5471 ****************************************************************************/
5472
5473 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5474                                         const char *pdata,
5475                                         int total_data,
5476                                         const char *fname,
5477                                         SMB_STRUCT_STAT *psbuf)
5478 {
5479         uint32 file_type = IVAL(pdata,56);
5480 #if defined(HAVE_MAKEDEV)
5481         uint32 dev_major = IVAL(pdata,60);
5482         uint32 dev_minor = IVAL(pdata,68);
5483 #endif
5484         SMB_DEV_T dev = (SMB_DEV_T)0;
5485         uint32 raw_unixmode = IVAL(pdata,84);
5486         NTSTATUS status;
5487         mode_t unixmode;
5488
5489         if (total_data < 100) {
5490                 return NT_STATUS_INVALID_PARAMETER;
5491         }
5492
5493         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5494         if (!NT_STATUS_IS_OK(status)) {
5495                 return status;
5496         }
5497
5498 #if defined(HAVE_MAKEDEV)
5499         dev = makedev(dev_major, dev_minor);
5500 #endif
5501
5502         switch (file_type) {
5503 #if defined(S_IFIFO)
5504                 case UNIX_TYPE_FIFO:
5505                         unixmode |= S_IFIFO;
5506                         break;
5507 #endif
5508 #if defined(S_IFSOCK)
5509                 case UNIX_TYPE_SOCKET:
5510                         unixmode |= S_IFSOCK;
5511                         break;
5512 #endif
5513 #if defined(S_IFCHR)
5514                 case UNIX_TYPE_CHARDEV:
5515                         unixmode |= S_IFCHR;
5516                         break;
5517 #endif
5518 #if defined(S_IFBLK)
5519                 case UNIX_TYPE_BLKDEV:
5520                         unixmode |= S_IFBLK;
5521                         break;
5522 #endif
5523                 default:
5524                         return NT_STATUS_INVALID_PARAMETER;
5525         }
5526
5527         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5528 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5529
5530         /* Ok - do the mknod. */
5531         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5532                 return map_nt_error_from_unix(errno);
5533         }
5534
5535         /* If any of the other "set" calls fail we
5536          * don't want to end up with a half-constructed mknod.
5537          */
5538
5539         if (lp_inherit_perms(SNUM(conn))) {
5540                 inherit_access_acl(
5541                         conn, parent_dirname(fname),
5542                         fname, unixmode);
5543         }
5544
5545         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5546                 status = map_nt_error_from_unix(errno);
5547                 SMB_VFS_UNLINK(conn,fname);
5548                 return status;
5549         }
5550         return NT_STATUS_OK;
5551 }
5552
5553 /****************************************************************************
5554  Deal with SMB_SET_FILE_UNIX_BASIC.
5555 ****************************************************************************/
5556
5557 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5558                                         struct smb_request *req,
5559                                         const char *pdata,
5560                                         int total_data,
5561                                         files_struct *fsp,
5562                                         const char *fname,
5563                                         SMB_STRUCT_STAT *psbuf)
5564 {
5565         struct timespec ts[2];
5566         uint32 raw_unixmode;
5567         mode_t unixmode;
5568         SMB_OFF_T size = 0;
5569         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5570         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5571         NTSTATUS status = NT_STATUS_OK;
5572         BOOL delete_on_fail = False;
5573         enum perm_type ptype;
5574
5575         if (total_data < 100) {
5576                 return NT_STATUS_INVALID_PARAMETER;
5577         }
5578
5579         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5580            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5581                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5582 #ifdef LARGE_SMB_OFF_T
5583                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5584 #else /* LARGE_SMB_OFF_T */
5585                 if (IVAL(pdata,4) != 0) {
5586                         /* more than 32 bits? */
5587                         return NT_STATUS_INVALID_PARAMETER;
5588                 }
5589 #endif /* LARGE_SMB_OFF_T */
5590         }
5591
5592         ts[0] = interpret_long_date(pdata+24); /* access_time */
5593         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5594         set_owner = (uid_t)IVAL(pdata,40);
5595         set_grp = (gid_t)IVAL(pdata,48);
5596         raw_unixmode = IVAL(pdata,84);
5597
5598         if (VALID_STAT(*psbuf)) {
5599                 if (S_ISDIR(psbuf->st_mode)) {
5600                         ptype = PERM_EXISTING_DIR;
5601                 } else {
5602                         ptype = PERM_EXISTING_FILE;
5603                 }
5604         } else {
5605                 ptype = PERM_NEW_FILE;
5606         }
5607
5608         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5609         if (!NT_STATUS_IS_OK(status)) {
5610                 return status;
5611         }
5612
5613         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5614 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5615                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5616
5617         if (!VALID_STAT(*psbuf)) {
5618                 /*
5619                  * The only valid use of this is to create character and block
5620                  * devices, and named pipes. This is deprecated (IMHO) and 
5621                  * a new info level should be used for mknod. JRA.
5622                  */
5623
5624                 status = smb_unix_mknod(conn,
5625                                         pdata,
5626                                         total_data,
5627                                         fname,
5628                                         psbuf);
5629                 if (!NT_STATUS_IS_OK(status)) {
5630                         return status;
5631                 }
5632
5633                 /* Ensure we don't try and change anything else. */
5634                 raw_unixmode = SMB_MODE_NO_CHANGE;
5635                 size = get_file_size(*psbuf);
5636                 ts[0] = get_atimespec(psbuf);
5637                 ts[1] = get_mtimespec(psbuf);
5638                 /* 
5639                  * We continue here as we might want to change the 
5640                  * owner uid/gid.
5641                  */
5642                 delete_on_fail = True;
5643         }
5644
5645 #if 1
5646         /* Horrible backwards compatibility hack as an old server bug
5647          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5648          * */
5649
5650         if (!size) {
5651                 size = get_file_size(*psbuf);
5652         }
5653 #endif
5654
5655         /*
5656          * Deal with the UNIX specific mode set.
5657          */
5658
5659         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5660                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5661                         (unsigned int)unixmode, fname ));
5662                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5663                         return map_nt_error_from_unix(errno);
5664                 }
5665         }
5666
5667         /*
5668          * Deal with the UNIX specific uid set.
5669          */
5670
5671         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5672                 int ret;
5673
5674                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5675                         (unsigned int)set_owner, fname ));
5676
5677                 if (S_ISLNK(psbuf->st_mode)) {
5678                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5679                 } else {
5680                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5681                 }
5682
5683                 if (ret != 0) {
5684                         status = map_nt_error_from_unix(errno);
5685                         if (delete_on_fail) {
5686                                 SMB_VFS_UNLINK(conn,fname);
5687                         }
5688                         return status;
5689                 }
5690         }
5691
5692         /*
5693          * Deal with the UNIX specific gid set.
5694          */
5695
5696         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5697                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5698                         (unsigned int)set_owner, fname ));
5699                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5700                         status = map_nt_error_from_unix(errno);
5701                         if (delete_on_fail) {
5702                                 SMB_VFS_UNLINK(conn,fname);
5703                         }
5704                         return status;
5705                 }
5706         }
5707
5708         /* Deal with any size changes. */
5709
5710         status = smb_set_file_size(conn, req,
5711                                 fsp,
5712                                 fname,
5713                                 psbuf,
5714                                 size);
5715         if (!NT_STATUS_IS_OK(status)) {
5716                 return status;
5717         }
5718
5719         /* Deal with any time changes. */
5720
5721         return smb_set_file_time(conn,
5722                                 fsp,
5723                                 fname,
5724                                 psbuf,
5725                                 ts);
5726 }
5727
5728 /****************************************************************************
5729  Deal with SMB_SET_FILE_UNIX_INFO2.
5730 ****************************************************************************/
5731
5732 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5733                                         struct smb_request *req,
5734                                         const char *pdata,
5735                                         int total_data,
5736                                         files_struct *fsp,
5737                                         const char *fname,
5738                                         SMB_STRUCT_STAT *psbuf)
5739 {
5740         NTSTATUS status;
5741         uint32 smb_fflags;
5742         uint32 smb_fmask;
5743
5744         if (total_data < 116) {
5745                 return NT_STATUS_INVALID_PARAMETER;
5746         }
5747
5748         /* Start by setting all the fields that are common between UNIX_BASIC
5749          * and UNIX_INFO2.
5750          */
5751         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5752                                 fsp, fname, psbuf);
5753         if (!NT_STATUS_IS_OK(status)) {
5754                 return status;
5755         }
5756
5757         smb_fflags = IVAL(pdata, 108);
5758         smb_fmask = IVAL(pdata, 112);
5759
5760         /* NB: We should only attempt to alter the file flags if the client
5761          * sends a non-zero mask.
5762          */
5763         if (smb_fmask != 0) {
5764                 int stat_fflags = 0;
5765
5766                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5767                             &stat_fflags)) {
5768                         /* Client asked to alter a flag we don't understand. */
5769                         return NT_STATUS_INVALID_PARAMETER;
5770                 }
5771
5772                 if (fsp && fsp->fh->fd != -1) {
5773                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5774                         return NT_STATUS_NOT_SUPPORTED;
5775                 } else {
5776                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5777                                 return map_nt_error_from_unix(errno);
5778                         }
5779                 }
5780         }
5781
5782         /* XXX: need to add support for changing the create_time here. You
5783          * can do this for paths on Darwin with setattrlist(2). The right way
5784          * to hook this up is probably by extending the VFS utimes interface.
5785          */
5786
5787         return NT_STATUS_OK;
5788 }
5789
5790 /****************************************************************************
5791  Create a directory with POSIX semantics.
5792 ****************************************************************************/
5793
5794 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5795                                 struct smb_request *req,
5796                                 char **ppdata,
5797                                 int total_data,
5798                                 const char *fname,
5799                                 SMB_STRUCT_STAT *psbuf,
5800                                 int *pdata_return_size)
5801 {
5802         NTSTATUS status = NT_STATUS_OK;
5803         uint32 raw_unixmode = 0;
5804         uint32 mod_unixmode = 0;
5805         mode_t unixmode = (mode_t)0;
5806         files_struct *fsp = NULL;
5807         uint16 info_level_return = 0;
5808         int info;
5809         char *pdata = *ppdata;
5810
5811         if (total_data < 18) {
5812                 return NT_STATUS_INVALID_PARAMETER;
5813         }
5814
5815         raw_unixmode = IVAL(pdata,8);
5816         /* Next 4 bytes are not yet defined. */
5817
5818         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5819         if (!NT_STATUS_IS_OK(status)) {
5820                 return status;
5821         }
5822
5823         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5824
5825         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5826                 fname, (unsigned int)unixmode ));
5827
5828         status = open_directory(conn, req,
5829                                 fname,
5830                                 psbuf,
5831                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5832                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5833                                 FILE_CREATE,
5834                                 0,
5835                                 mod_unixmode,
5836                                 &info,
5837                                 &fsp);
5838
5839         if (NT_STATUS_IS_OK(status)) {
5840                 close_file(fsp, NORMAL_CLOSE);
5841         }
5842
5843         info_level_return = SVAL(pdata,16);
5844  
5845         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5846                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5847         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5848                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5849         } else {
5850                 *pdata_return_size = 12;
5851         }
5852
5853         /* Realloc the data size */
5854         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5855         if (*ppdata == NULL) {
5856                 *pdata_return_size = 0;
5857                 return NT_STATUS_NO_MEMORY;
5858         }
5859         pdata = *ppdata;
5860
5861         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5862         SSVAL(pdata,2,0); /* No fnum. */
5863         SIVAL(pdata,4,info); /* Was directory created. */
5864
5865         switch (info_level_return) {
5866                 case SMB_QUERY_FILE_UNIX_BASIC:
5867                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5868                         SSVAL(pdata,10,0); /* Padding. */
5869                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5870                         break;
5871                 case SMB_QUERY_FILE_UNIX_INFO2:
5872                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5873                         SSVAL(pdata,10,0); /* Padding. */
5874                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5875                         break;
5876                 default:
5877                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5878                         SSVAL(pdata,10,0); /* Padding. */
5879                         break;
5880         }
5881
5882         return status;
5883 }
5884
5885 /****************************************************************************
5886  Open/Create a file with POSIX semantics.
5887 ****************************************************************************/
5888
5889 static NTSTATUS smb_posix_open(connection_struct *conn,
5890                                struct smb_request *req,
5891                                 char **ppdata,
5892                                 int total_data,
5893                                 const char *fname,
5894                                 SMB_STRUCT_STAT *psbuf,
5895                                 int *pdata_return_size)
5896 {
5897         BOOL extended_oplock_granted = False;
5898         char *pdata = *ppdata;
5899         uint32 flags = 0;
5900         uint32 wire_open_mode = 0;
5901         uint32 raw_unixmode = 0;
5902         uint32 mod_unixmode = 0;
5903         uint32 create_disp = 0;
5904         uint32 access_mask = 0;
5905         uint32 create_options = 0;
5906         NTSTATUS status = NT_STATUS_OK;
5907         mode_t unixmode = (mode_t)0;
5908         files_struct *fsp = NULL;
5909         int oplock_request = 0;
5910         int info = 0;
5911         uint16 info_level_return = 0;
5912
5913         if (total_data < 18) {
5914                 return NT_STATUS_INVALID_PARAMETER;
5915         }
5916
5917         flags = IVAL(pdata,0);
5918         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5919         if (oplock_request) {
5920                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5921         }
5922
5923         wire_open_mode = IVAL(pdata,4);
5924
5925         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5926                 return smb_posix_mkdir(conn, req,
5927                                         ppdata,
5928                                         total_data,
5929                                         fname,
5930                                         psbuf,
5931                                         pdata_return_size);
5932         }
5933
5934         switch (wire_open_mode & SMB_ACCMODE) {
5935                 case SMB_O_RDONLY:
5936                         access_mask = FILE_READ_DATA;
5937                         break;
5938                 case SMB_O_WRONLY:
5939                         access_mask = FILE_WRITE_DATA;
5940                         break;
5941                 case SMB_O_RDWR:
5942                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5943                         break;
5944                 default:
5945                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5946                                 (unsigned int)wire_open_mode ));
5947                         return NT_STATUS_INVALID_PARAMETER;
5948         }
5949
5950         wire_open_mode &= ~SMB_ACCMODE;
5951
5952         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5953                 create_disp = FILE_CREATE;
5954         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5955                 create_disp = FILE_OVERWRITE_IF;
5956         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5957                 create_disp = FILE_OPEN_IF;
5958         } else {
5959                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5960                         (unsigned int)wire_open_mode ));
5961                 return NT_STATUS_INVALID_PARAMETER;
5962         }
5963
5964         raw_unixmode = IVAL(pdata,8);
5965         /* Next 4 bytes are not yet defined. */
5966
5967         status = unix_perms_from_wire(conn,
5968                                 psbuf,
5969                                 raw_unixmode,
5970                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5971                                 &unixmode);
5972
5973         if (!NT_STATUS_IS_OK(status)) {
5974                 return status;
5975         }
5976
5977         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5978
5979         if (wire_open_mode & SMB_O_SYNC) {
5980                 create_options |= FILE_WRITE_THROUGH;
5981         }
5982         if (wire_open_mode & SMB_O_APPEND) {
5983                 access_mask |= FILE_APPEND_DATA;
5984         }
5985         if (wire_open_mode & SMB_O_DIRECT) {
5986                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5987         }
5988
5989         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5990                 fname,
5991                 (unsigned int)wire_open_mode,
5992                 (unsigned int)unixmode ));
5993
5994         status = open_file_ntcreate(conn, req,
5995                                 fname,
5996                                 psbuf,
5997                                 access_mask,
5998                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5999                                 create_disp,
6000                                 0,              /* no create options yet. */
6001                                 mod_unixmode,
6002                                 oplock_request,
6003                                 &info,
6004                                 &fsp);
6005
6006         if (!NT_STATUS_IS_OK(status)) {
6007                 return status;
6008         }
6009
6010         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6011                 extended_oplock_granted = True;
6012         }
6013
6014         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6015                 extended_oplock_granted = True;
6016         }
6017
6018         info_level_return = SVAL(pdata,16);
6019  
6020         /* Allocate the correct return size. */
6021
6022         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6023                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6024         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
6025                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6026         } else {
6027                 *pdata_return_size = 12;
6028         }
6029
6030         /* Realloc the data size */
6031         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6032         if (*ppdata == NULL) {
6033                 close_file(fsp,ERROR_CLOSE);
6034                 *pdata_return_size = 0;
6035                 return NT_STATUS_NO_MEMORY;
6036         }
6037         pdata = *ppdata;
6038
6039         if (extended_oplock_granted) {
6040                 if (flags & REQUEST_BATCH_OPLOCK) {
6041                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6042                 } else {
6043                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6044                 }
6045         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6046                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6047         } else {
6048                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6049         }
6050
6051         SSVAL(pdata,2,fsp->fnum);
6052         SIVAL(pdata,4,info); /* Was file created etc. */
6053
6054         switch (info_level_return) {
6055                 case SMB_QUERY_FILE_UNIX_BASIC:
6056                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6057                         SSVAL(pdata,10,0); /* padding. */
6058                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6059                         break;
6060                 case SMB_QUERY_FILE_UNIX_INFO2:
6061                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6062                         SSVAL(pdata,10,0); /* padding. */
6063                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6064                         break;
6065                 default:
6066                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6067                         SSVAL(pdata,10,0); /* padding. */
6068                         break;
6069         }
6070         return NT_STATUS_OK;
6071 }
6072
6073 /****************************************************************************
6074  Delete a file with POSIX semantics.
6075 ****************************************************************************/
6076
6077 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6078                                  struct smb_request *req,
6079                                 const char *pdata,
6080                                 int total_data,
6081                                 const char *fname,
6082                                 SMB_STRUCT_STAT *psbuf)
6083 {
6084         NTSTATUS status = NT_STATUS_OK;
6085         files_struct *fsp = NULL;
6086         uint16 flags = 0;
6087         char del = 1;
6088         int info = 0;
6089         int i;
6090         struct share_mode_lock *lck = NULL;
6091
6092         if (total_data < 2) {
6093                 return NT_STATUS_INVALID_PARAMETER;
6094         }
6095
6096         flags = SVAL(pdata,0);
6097
6098         if (!VALID_STAT(*psbuf)) {
6099                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6100         }
6101
6102         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6103                         !VALID_STAT_OF_DIR(*psbuf)) {
6104                 return NT_STATUS_NOT_A_DIRECTORY;
6105         }
6106
6107         DEBUG(10,("smb_posix_unlink: %s %s\n",
6108                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6109                 fname));
6110
6111         if (VALID_STAT_OF_DIR(*psbuf)) {
6112                 status = open_directory(conn, req,
6113                                         fname,
6114                                         psbuf,
6115                                         DELETE_ACCESS,
6116                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6117                                         FILE_OPEN,
6118                                         0,
6119                                         FILE_FLAG_POSIX_SEMANTICS|0777,
6120                                         &info,
6121                                         &fsp);
6122         } else {
6123
6124                 status = open_file_ntcreate(conn, req,
6125                                 fname,
6126                                 psbuf,
6127                                 DELETE_ACCESS,
6128                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6129                                 FILE_OPEN,
6130                                 0,
6131                                 FILE_FLAG_POSIX_SEMANTICS|0777,
6132                                 0, /* No oplock, but break existing ones. */
6133                                 &info,
6134                                 &fsp);
6135         }
6136
6137         if (!NT_STATUS_IS_OK(status)) {
6138                 return status;
6139         }
6140
6141         /*
6142          * Don't lie to client. If we can't really delete due to
6143          * non-POSIX opens return SHARING_VIOLATION.
6144          */
6145
6146         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
6147         if (lck == NULL) {
6148                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6149                         "lock for file %s\n", fsp->fsp_name));
6150                 close_file(fsp, NORMAL_CLOSE);
6151                 return NT_STATUS_INVALID_PARAMETER;
6152         }
6153
6154         /*
6155          * See if others still have the file open. If this is the case, then
6156          * don't delete. If all opens are POSIX delete we can set the delete
6157          * on close disposition.
6158          */
6159         for (i=0; i<lck->num_share_modes; i++) {
6160                 struct share_mode_entry *e = &lck->share_modes[i];
6161                 if (is_valid_share_mode_entry(e)) {
6162                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6163                                 continue;
6164                         }
6165                         /* Fail with sharing violation. */
6166                         close_file(fsp, NORMAL_CLOSE);
6167                         TALLOC_FREE(lck);
6168                         return NT_STATUS_SHARING_VIOLATION;
6169                 }
6170         }
6171
6172         /*
6173          * Set the delete on close.
6174          */
6175         status = smb_set_file_disposition_info(conn,
6176                                                 &del,
6177                                                 1,
6178                                                 fsp,
6179                                                 fname,
6180                                                 psbuf);
6181
6182         if (!NT_STATUS_IS_OK(status)) {
6183                 close_file(fsp, NORMAL_CLOSE);
6184                 TALLOC_FREE(lck);
6185                 return status;
6186         }
6187         TALLOC_FREE(lck);
6188         return close_file(fsp, NORMAL_CLOSE);
6189 }
6190
6191 /****************************************************************************
6192  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6193 ****************************************************************************/
6194
6195 static void call_trans2setfilepathinfo(connection_struct *conn,
6196                                        struct smb_request *req,
6197                                        unsigned int tran_call,
6198                                        char **pparams, int total_params,
6199                                        char **ppdata, int total_data,
6200                                        unsigned int max_data_bytes)
6201 {
6202         char *params = *pparams;
6203         char *pdata = *ppdata;
6204         uint16 info_level;
6205         SMB_STRUCT_STAT sbuf;
6206         char *fname = NULL;
6207         files_struct *fsp = NULL;
6208         NTSTATUS status = NT_STATUS_OK;
6209         int data_return_size = 0;
6210         TALLOC_CTX *ctx = talloc_tos();
6211
6212         if (!params) {
6213                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6214                 return;
6215         }
6216
6217         ZERO_STRUCT(sbuf);
6218
6219         if (tran_call == TRANSACT2_SETFILEINFO) {
6220                 if (total_params < 4) {
6221                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6222                         return;
6223                 }
6224
6225                 fsp = file_fsp(SVAL(params,0));
6226                 /* Basic check for non-null fsp. */
6227                 if (!check_fsp_open(conn, req, fsp, &current_user)) {
6228                         return;
6229                 }
6230                 info_level = SVAL(params,2);
6231
6232                 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6233                 if (!fname) {
6234                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6235                         return;
6236                 }
6237
6238                 if(fsp->is_directory || fsp->fh->fd == -1) {
6239                         /*
6240                          * This is actually a SETFILEINFO on a directory
6241                          * handle (returned from an NT SMB). NT5.0 seems
6242                          * to do this call. JRA.
6243                          */
6244                         if (INFO_LEVEL_IS_UNIX(info_level)) {
6245                                 /* Always do lstat for UNIX calls. */
6246                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6247                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6248                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6249                                         return;
6250                                 }
6251                         } else {
6252                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6253                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6254                                         reply_unixerror(req,ERRDOS,ERRbadpath);
6255                                         return;
6256                                 }
6257                         }
6258                 } else if (fsp->print_file) {
6259                         /*
6260                          * Doing a DELETE_ON_CLOSE should cancel a print job.
6261                          */
6262                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6263                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6264
6265                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6266
6267                                 SSVAL(params,0,0);
6268                                 send_trans2_replies(req, params, 2,
6269                                                     *ppdata, 0,
6270                                                     max_data_bytes);
6271                                 return;
6272                         } else {
6273                                 reply_unixerror(req, ERRDOS, ERRbadpath);
6274                                 return;
6275                         }
6276                 } else {
6277                         /*
6278                          * Original code - this is an open file.
6279                          */
6280                         if (!check_fsp(conn, req, fsp, &current_user)) {
6281                                 return;
6282                         }
6283
6284                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
6285                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6286                                 reply_unixerror(req, ERRDOS, ERRbadfid);
6287                                 return;
6288                         }
6289                 }
6290         } else {
6291                 /* set path info */
6292                 if (total_params < 7) {
6293                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6294                         return;
6295                 }
6296
6297                 info_level = SVAL(params,0);
6298                 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6299                                 total_params - 6, STR_TERMINATE,
6300                                 &status);
6301                 if (!NT_STATUS_IS_OK(status)) {
6302                         reply_nterror(req, status);
6303                         return;
6304                 }
6305
6306                 status = resolve_dfspath(ctx, conn,
6307                                          req->flags2 & FLAGS2_DFS_PATHNAMES,
6308                                          fname,
6309                                          &fname);
6310                 if (!NT_STATUS_IS_OK(status)) {
6311                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6312                                 reply_botherror(req,
6313                                                 NT_STATUS_PATH_NOT_COVERED,
6314                                                 ERRSRV, ERRbadpath);
6315                                 return;
6316                         }
6317                         reply_nterror(req, status);
6318                         return;
6319                 }
6320
6321                 status = unix_convert(ctx, conn, fname, False,
6322                                 &fname, NULL, &sbuf);
6323                 if (!NT_STATUS_IS_OK(status)) {
6324                         reply_nterror(req, status);
6325                         return;
6326                 }
6327
6328                 status = check_name(conn, fname);
6329                 if (!NT_STATUS_IS_OK(status)) {
6330                         reply_nterror(req, status);
6331                         return;
6332                 }
6333
6334                 if (INFO_LEVEL_IS_UNIX(info_level)) {
6335                         /*
6336                          * For CIFS UNIX extensions the target name may not exist.
6337                          */
6338
6339                         /* Always do lstat for UNIX calls. */
6340                         SMB_VFS_LSTAT(conn,fname,&sbuf);
6341
6342                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6343                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6344                         reply_unixerror(req, ERRDOS, ERRbadpath);
6345                         return;
6346                 }
6347         }
6348
6349         if (!CAN_WRITE(conn)) {
6350                 reply_doserror(req, ERRSRV, ERRaccess);
6351                 return;
6352         }
6353
6354         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6355                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6356                 return;
6357         }
6358
6359         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6360                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6361
6362         /* Realloc the parameter size */
6363         *pparams = (char *)SMB_REALLOC(*pparams,2);
6364         if (*pparams == NULL) {
6365                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6366                 return;
6367         }
6368         params = *pparams;
6369
6370         SSVAL(params,0,0);
6371
6372         if (fsp && !null_timespec(fsp->pending_modtime)) {
6373                 /* the pending modtime overrides the current modtime */
6374                 set_mtimespec(&sbuf, fsp->pending_modtime);
6375         }
6376
6377         switch (info_level) {
6378
6379                 case SMB_INFO_STANDARD:
6380                 {
6381                         status = smb_set_info_standard(conn,
6382                                         pdata,
6383                                         total_data,
6384                                         fsp,
6385                                         fname,
6386                                         &sbuf);
6387                         break;
6388                 }
6389
6390                 case SMB_INFO_SET_EA:
6391                 {
6392                         status = smb_info_set_ea(conn,
6393                                                 pdata,
6394                                                 total_data,
6395                                                 fsp,
6396                                                 fname);
6397                         break;
6398                 }
6399
6400                 case SMB_SET_FILE_BASIC_INFO:
6401                 case SMB_FILE_BASIC_INFORMATION:
6402                 {
6403                         status = smb_set_file_basic_info(conn,
6404                                                         pdata,
6405                                                         total_data,
6406                                                         fsp,
6407                                                         fname,
6408                                                         &sbuf);
6409                         break;
6410                 }
6411
6412                 case SMB_FILE_ALLOCATION_INFORMATION:
6413                 case SMB_SET_FILE_ALLOCATION_INFO:
6414                 {
6415                         status = smb_set_file_allocation_info(conn, req,
6416                                                                 pdata,
6417                                                                 total_data,
6418                                                                 fsp,
6419                                                                 fname,
6420                                                                 &sbuf);
6421                         break;
6422                 }
6423
6424                 case SMB_FILE_END_OF_FILE_INFORMATION:
6425                 case SMB_SET_FILE_END_OF_FILE_INFO:
6426                 {
6427                         status = smb_set_file_end_of_file_info(conn, req,
6428                                                                 pdata,
6429                                                                 total_data,
6430                                                                 fsp,
6431                                                                 fname,
6432                                                                 &sbuf);
6433                         break;
6434                 }
6435
6436                 case SMB_FILE_DISPOSITION_INFORMATION:
6437                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6438                 {
6439 #if 0
6440                         /* JRA - We used to just ignore this on a path ? 
6441                          * Shouldn't this be invalid level on a pathname
6442                          * based call ?
6443                          */
6444                         if (tran_call != TRANSACT2_SETFILEINFO) {
6445                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6446                         }
6447 #endif
6448                         status = smb_set_file_disposition_info(conn,
6449                                                 pdata,
6450                                                 total_data,
6451                                                 fsp,
6452                                                 fname,
6453                                                 &sbuf);
6454                         break;
6455                 }
6456
6457                 case SMB_FILE_POSITION_INFORMATION:
6458                 {
6459                         status = smb_file_position_information(conn,
6460                                                 pdata,
6461                                                 total_data,
6462                                                 fsp);
6463                         break;
6464                 }
6465
6466                 /* From tridge Samba4 : 
6467                  * MODE_INFORMATION in setfileinfo (I have no
6468                  * idea what "mode information" on a file is - it takes a value of 0,
6469                  * 2, 4 or 6. What could it be?).
6470                  */
6471
6472                 case SMB_FILE_MODE_INFORMATION:
6473                 {
6474                         status = smb_file_mode_information(conn,
6475                                                 pdata,
6476                                                 total_data);
6477                         break;
6478                 }
6479
6480                 /*
6481                  * CIFS UNIX extensions.
6482                  */
6483
6484                 case SMB_SET_FILE_UNIX_BASIC:
6485                 {
6486                         status = smb_set_file_unix_basic(conn, req,
6487                                                         pdata,
6488                                                         total_data,
6489                                                         fsp,
6490                                                         fname,
6491                                                         &sbuf);
6492                         break;
6493                 }
6494
6495                 case SMB_SET_FILE_UNIX_INFO2:
6496                 {
6497                         status = smb_set_file_unix_info2(conn, req,
6498                                                         pdata,
6499                                                         total_data,
6500                                                         fsp,
6501                                                         fname,
6502                                                         &sbuf);
6503                         break;
6504                 }
6505
6506                 case SMB_SET_FILE_UNIX_LINK:
6507                 {
6508                         if (tran_call != TRANSACT2_SETPATHINFO) {
6509                                 /* We must have a pathname for this. */
6510                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6511                                 return;
6512                         }
6513                         status = smb_set_file_unix_link(conn, req, pdata,
6514                                                         total_data, fname);
6515                         break;
6516                 }
6517
6518                 case SMB_SET_FILE_UNIX_HLINK:
6519                 {
6520                         if (tran_call != TRANSACT2_SETPATHINFO) {
6521                                 /* We must have a pathname for this. */
6522                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6523                                 return;
6524                         }
6525                         status = smb_set_file_unix_hlink(conn, req,
6526                                                          pdata, total_data,
6527                                                          fname);
6528                         break;
6529                 }
6530
6531                 case SMB_FILE_RENAME_INFORMATION:
6532                 {
6533                         status = smb_file_rename_information(conn, req,
6534                                                              pdata, total_data,
6535                                                              fsp, fname);
6536                         break;
6537                 }
6538
6539 #if defined(HAVE_POSIX_ACLS)
6540                 case SMB_SET_POSIX_ACL:
6541                 {
6542                         status = smb_set_posix_acl(conn,
6543                                                 pdata,
6544                                                 total_data,
6545                                                 fsp,
6546                                                 fname,
6547                                                 &sbuf);
6548                         break;
6549                 }
6550 #endif
6551
6552                 case SMB_SET_POSIX_LOCK:
6553                 {
6554                         if (tran_call != TRANSACT2_SETFILEINFO) {
6555                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6556                                 return;
6557                         }
6558                         status = smb_set_posix_lock(conn, req->inbuf,
6559                                                     smb_len(req->inbuf) + 4,
6560                                                     pdata, total_data, fsp);
6561                         break;
6562                 }
6563
6564                 case SMB_POSIX_PATH_OPEN:
6565                 {
6566                         if (tran_call != TRANSACT2_SETPATHINFO) {
6567                                 /* We must have a pathname for this. */
6568                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6569                                 return;
6570                         }
6571
6572                         status = smb_posix_open(conn, req,
6573                                                 ppdata,
6574                                                 total_data,
6575                                                 fname,
6576                                                 &sbuf,
6577                                                 &data_return_size);
6578                         break;
6579                 }
6580
6581                 case SMB_POSIX_PATH_UNLINK:
6582                 {
6583                         if (tran_call != TRANSACT2_SETPATHINFO) {
6584                                 /* We must have a pathname for this. */
6585                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6586                                 return;
6587                         }
6588
6589                         status = smb_posix_unlink(conn, req,
6590                                                 pdata,
6591                                                 total_data,
6592                                                 fname,
6593                                                 &sbuf);
6594                         break;
6595                 }
6596
6597                 default:
6598                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6599                         return;
6600         }
6601
6602         
6603         if (!NT_STATUS_IS_OK(status)) {
6604                 if (open_was_deferred(req->mid)) {
6605                         /* We have re-scheduled this call. */
6606                         return;
6607                 }
6608                 if (blocking_lock_was_deferred(req->mid)) {
6609                         /* We have re-scheduled this call. */
6610                         return;
6611                 }
6612                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6613                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6614                                         ERRSRV, ERRbadpath);
6615                         return;
6616                 }
6617                 if (info_level == SMB_POSIX_PATH_OPEN) {
6618                         reply_openerror(req, status);
6619                         return;
6620                 }
6621
6622                 reply_nterror(req, status);
6623                 return;
6624         }
6625
6626         SSVAL(params,0,0);
6627         send_trans2_replies(req, params, 2, *ppdata, data_return_size,
6628                             max_data_bytes);
6629   
6630         return;
6631 }
6632
6633 /****************************************************************************
6634  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6635 ****************************************************************************/
6636
6637 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6638                              char **pparams, int total_params,
6639                              char **ppdata, int total_data,
6640                              unsigned int max_data_bytes)
6641 {
6642         char *params = *pparams;
6643         char *pdata = *ppdata;
6644         char *directory = NULL;
6645         SMB_STRUCT_STAT sbuf;
6646         NTSTATUS status = NT_STATUS_OK;
6647         struct ea_list *ea_list = NULL;
6648         TALLOC_CTX *ctx = talloc_tos();
6649
6650         if (!CAN_WRITE(conn)) {
6651                 reply_doserror(req, ERRSRV, ERRaccess);
6652                 return;
6653         }
6654
6655         if (total_params < 5) {
6656                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6657                 return;
6658         }
6659
6660         srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
6661                         total_params - 4, STR_TERMINATE,
6662                         &status);
6663         if (!NT_STATUS_IS_OK(status)) {
6664                 reply_nterror(req, status);
6665                 return;
6666         }
6667
6668         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6669
6670         status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
6671         if (!NT_STATUS_IS_OK(status)) {
6672                 reply_nterror(req, status);
6673                 return;
6674         }
6675
6676         status = check_name(conn, directory);
6677         if (!NT_STATUS_IS_OK(status)) {
6678                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6679                 reply_nterror(req, status);
6680                 return;
6681         }
6682
6683         /* Any data in this call is an EA list. */
6684         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6685                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6686                 return;
6687         }
6688
6689         /*
6690          * OS/2 workplace shell seems to send SET_EA requests of "null"
6691          * length (4 bytes containing IVAL 4).
6692          * They seem to have no effect. Bug #3212. JRA.
6693          */
6694
6695         if (total_data != 4) {
6696                 if (total_data < 10) {
6697                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6698                         return;
6699                 }
6700
6701                 if (IVAL(pdata,0) > total_data) {
6702                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6703                                 IVAL(pdata,0), (unsigned int)total_data));
6704                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6705                         return;
6706                 }
6707
6708                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
6709                                        total_data - 4);
6710                 if (!ea_list) {
6711                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6712                         return;
6713                 }
6714         } else if (IVAL(pdata,0) != 4) {
6715                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6716                 return;
6717         }
6718
6719         status = create_directory(conn, directory);
6720
6721         if (!NT_STATUS_IS_OK(status)) {
6722                 reply_nterror(req, status);
6723                 return;
6724         }
6725   
6726         /* Try and set any given EA. */
6727         if (ea_list) {
6728                 status = set_ea(conn, NULL, directory, ea_list);
6729                 if (!NT_STATUS_IS_OK(status)) {
6730                         reply_nterror(req, status);
6731                         return;
6732                 }
6733         }
6734
6735         /* Realloc the parameter and data sizes */
6736         *pparams = (char *)SMB_REALLOC(*pparams,2);
6737         if(*pparams == NULL) {
6738                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6739                 return;
6740         }
6741         params = *pparams;
6742
6743         SSVAL(params,0,0);
6744
6745         send_trans2_replies(req, params, 2, *ppdata, 0, max_data_bytes);
6746   
6747         return;
6748 }
6749
6750 /****************************************************************************
6751  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6752  We don't actually do this - we just send a null response.
6753 ****************************************************************************/
6754
6755 static void call_trans2findnotifyfirst(connection_struct *conn,
6756                                        struct smb_request *req,
6757                                        char **pparams, int total_params,
6758                                        char **ppdata, int total_data,
6759                                        unsigned int max_data_bytes)
6760 {
6761         static uint16 fnf_handle = 257;
6762         char *params = *pparams;
6763         uint16 info_level;
6764
6765         if (total_params < 6) {
6766                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6767                 return;
6768         }
6769
6770         info_level = SVAL(params,4);
6771         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6772
6773         switch (info_level) {
6774                 case 1:
6775                 case 2:
6776                         break;
6777                 default:
6778                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6779                         return;
6780         }
6781
6782         /* Realloc the parameter and data sizes */
6783         *pparams = (char *)SMB_REALLOC(*pparams,6);
6784         if (*pparams == NULL) {
6785                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6786                 return;
6787         }
6788         params = *pparams;
6789
6790         SSVAL(params,0,fnf_handle);
6791         SSVAL(params,2,0); /* No changes */
6792         SSVAL(params,4,0); /* No EA errors */
6793
6794         fnf_handle++;
6795
6796         if(fnf_handle == 0)
6797                 fnf_handle = 257;
6798
6799         send_trans2_replies(req, params, 6, *ppdata, 0, max_data_bytes);
6800   
6801         return;
6802 }
6803
6804 /****************************************************************************
6805  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6806  changes). Currently this does nothing.
6807 ****************************************************************************/
6808
6809 static void call_trans2findnotifynext(connection_struct *conn,
6810                                       struct smb_request *req,
6811                                       char **pparams, int total_params,
6812                                       char **ppdata, int total_data,
6813                                       unsigned int max_data_bytes)
6814 {
6815         char *params = *pparams;
6816
6817         DEBUG(3,("call_trans2findnotifynext\n"));
6818
6819         /* Realloc the parameter and data sizes */
6820         *pparams = (char *)SMB_REALLOC(*pparams,4);
6821         if (*pparams == NULL) {
6822                 reply_nterror(req, NT_STATUS_NO_MEMORY);
6823                 return;
6824         }
6825         params = *pparams;
6826
6827         SSVAL(params,0,0); /* No changes */
6828         SSVAL(params,2,0); /* No EA errors */
6829
6830         send_trans2_replies(req, params, 4, *ppdata, 0, max_data_bytes);
6831   
6832         return;
6833 }
6834
6835 /****************************************************************************
6836  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6837 ****************************************************************************/
6838
6839 static void call_trans2getdfsreferral(connection_struct *conn,
6840                                       struct smb_request *req,
6841                                       char **pparams, int total_params,
6842                                       char **ppdata, int total_data,
6843                                       unsigned int max_data_bytes)
6844 {
6845         char *params = *pparams;
6846         char *pathname = NULL;
6847         int reply_size = 0;
6848         int max_referral_level;
6849         NTSTATUS status = NT_STATUS_OK;
6850         TALLOC_CTX *ctx = talloc_tos();
6851
6852         DEBUG(10,("call_trans2getdfsreferral\n"));
6853
6854         if (total_params < 3) {
6855                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6856                 return;
6857         }
6858
6859         max_referral_level = SVAL(params,0);
6860
6861         if(!lp_host_msdfs()) {
6862                 reply_doserror(req, ERRDOS, ERRbadfunc);
6863                 return;
6864         }
6865
6866         srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
6867                     total_params - 2, STR_TERMINATE);
6868         if (!pathname) {
6869                 reply_nterror(req, NT_STATUS_NOT_FOUND);
6870                 return;
6871         }
6872         if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
6873                                             ppdata,&status)) < 0) {
6874                 reply_nterror(req, status);
6875                 return;
6876         }
6877
6878         SSVAL(req->inbuf, smb_flg2,
6879               SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6880         send_trans2_replies(req,0,0,*ppdata,reply_size, max_data_bytes);
6881
6882         return;
6883 }
6884
6885 #define LMCAT_SPL       0x53
6886 #define LMFUNC_GETJOBID 0x60
6887
6888 /****************************************************************************
6889  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6890 ****************************************************************************/
6891
6892 static void call_trans2ioctl(connection_struct *conn,
6893                              struct smb_request *req,
6894                              char **pparams, int total_params,
6895                              char **ppdata, int total_data,
6896                              unsigned int max_data_bytes)
6897 {
6898         char *pdata = *ppdata;
6899         files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
6900
6901         /* check for an invalid fid before proceeding */
6902
6903         if (!fsp) {
6904                 reply_doserror(req, ERRDOS, ERRbadfid);
6905                 return;
6906         }
6907
6908         if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
6909             && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6910                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6911                 if (*ppdata == NULL) {
6912                         reply_nterror(req, NT_STATUS_NO_MEMORY);
6913                         return;
6914                 }
6915                 pdata = *ppdata;
6916
6917                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6918                         CAN ACCEPT THIS IN UNICODE. JRA. */
6919
6920                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6921                 srvstr_push(pdata, req->flags2, pdata + 2,
6922                             global_myname(), 15,
6923                             STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6924                 srvstr_push(pdata, req->flags2, pdata+18,
6925                             lp_servicename(SNUM(conn)), 13,
6926                             STR_ASCII|STR_TERMINATE); /* Service name */
6927                 send_trans2_replies(req, *pparams, 0, *ppdata, 32,
6928                                     max_data_bytes);
6929                 return;
6930         }
6931
6932         DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6933         reply_doserror(req, ERRSRV, ERRerror);
6934 }
6935
6936 /****************************************************************************
6937  Reply to a SMBfindclose (stop trans2 directory search).
6938 ****************************************************************************/
6939
6940 void reply_findclose(connection_struct *conn, struct smb_request *req)
6941 {
6942         int dptr_num;
6943
6944         START_PROFILE(SMBfindclose);
6945
6946         if (req->wct < 1) {
6947                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6948                 END_PROFILE(SMBfindclose);
6949                 return;
6950         }
6951
6952         dptr_num = SVALS(req->inbuf,smb_vwv0);
6953
6954         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6955
6956         dptr_close(&dptr_num);
6957
6958         reply_outbuf(req, 0, 0);
6959
6960         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6961
6962         END_PROFILE(SMBfindclose);
6963         return;
6964 }
6965
6966 /****************************************************************************
6967  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6968 ****************************************************************************/
6969
6970 void reply_findnclose(connection_struct *conn, struct smb_request *req)
6971 {
6972         int dptr_num;
6973
6974         START_PROFILE(SMBfindnclose);
6975
6976         if (req->wct < 1) {
6977                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6978                 END_PROFILE(SMBfindnclose);
6979                 return;
6980         }
6981         
6982         dptr_num = SVAL(req->inbuf,smb_vwv0);
6983
6984         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6985
6986         /* We never give out valid handles for a 
6987            findnotifyfirst - so any dptr_num is ok here. 
6988            Just ignore it. */
6989
6990         reply_outbuf(req, 0, 0);
6991
6992         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6993
6994         END_PROFILE(SMBfindnclose);
6995         return;
6996 }
6997
6998 static void handle_trans2(connection_struct *conn, struct smb_request *req,
6999                           struct trans_state *state)
7000 {
7001         if (Protocol >= PROTOCOL_NT1) {
7002                 req->flags2 |= 0x40; /* IS_LONG_NAME */
7003                 SSVAL(req->inbuf,smb_flg2,req->flags2);
7004         }
7005
7006         /* Now we must call the relevant TRANS2 function */
7007         switch(state->call)  {
7008         case TRANSACT2_OPEN:
7009         {
7010                 START_PROFILE(Trans2_open);
7011                 call_trans2open(conn, req,
7012                                 &state->param, state->total_param,
7013                                 &state->data, state->total_data,
7014                                 state->max_data_return);
7015                 END_PROFILE(Trans2_open);
7016                 break;
7017         }
7018
7019         case TRANSACT2_FINDFIRST:
7020         {
7021                 START_PROFILE(Trans2_findfirst);
7022                 call_trans2findfirst(conn, req,
7023                                      &state->param, state->total_param,
7024                                      &state->data, state->total_data,
7025                                      state->max_data_return);
7026                 END_PROFILE(Trans2_findfirst);
7027                 break;
7028         }
7029
7030         case TRANSACT2_FINDNEXT:
7031         {
7032                 START_PROFILE(Trans2_findnext);
7033                 call_trans2findnext(conn, req,
7034                                     &state->param, state->total_param,
7035                                     &state->data, state->total_data,
7036                                     state->max_data_return);
7037                 END_PROFILE(Trans2_findnext);
7038                 break;
7039         }
7040
7041         case TRANSACT2_QFSINFO:
7042         {
7043                 START_PROFILE(Trans2_qfsinfo);
7044                 call_trans2qfsinfo(conn, req,
7045                                    &state->param, state->total_param,
7046                                    &state->data, state->total_data,
7047                                    state->max_data_return);
7048                 END_PROFILE(Trans2_qfsinfo);
7049             break;
7050         }
7051
7052         case TRANSACT2_SETFSINFO:
7053         {
7054                 START_PROFILE(Trans2_setfsinfo);
7055                 call_trans2setfsinfo(conn, req,
7056                                      &state->param, state->total_param,
7057                                      &state->data, state->total_data,
7058                                      state->max_data_return);
7059                 END_PROFILE(Trans2_setfsinfo);
7060                 break;
7061         }
7062
7063         case TRANSACT2_QPATHINFO:
7064         case TRANSACT2_QFILEINFO:
7065         {
7066                 START_PROFILE(Trans2_qpathinfo);
7067                 call_trans2qfilepathinfo(conn, req, state->call,
7068                                          &state->param, state->total_param,
7069                                          &state->data, state->total_data,
7070                                          state->max_data_return);
7071                 END_PROFILE(Trans2_qpathinfo);
7072                 break;
7073         }
7074
7075         case TRANSACT2_SETPATHINFO:
7076         case TRANSACT2_SETFILEINFO:
7077         {
7078                 START_PROFILE(Trans2_setpathinfo);
7079                 call_trans2setfilepathinfo(conn, req, state->call,
7080                                            &state->param, state->total_param,
7081                                            &state->data, state->total_data,
7082                                            state->max_data_return);
7083                 END_PROFILE(Trans2_setpathinfo);
7084                 break;
7085         }
7086
7087         case TRANSACT2_FINDNOTIFYFIRST:
7088         {
7089                 START_PROFILE(Trans2_findnotifyfirst);
7090                 call_trans2findnotifyfirst(conn, req,
7091                                            &state->param, state->total_param,
7092                                            &state->data, state->total_data,
7093                                            state->max_data_return);
7094                 END_PROFILE(Trans2_findnotifyfirst);
7095                 break;
7096         }
7097
7098         case TRANSACT2_FINDNOTIFYNEXT:
7099         {
7100                 START_PROFILE(Trans2_findnotifynext);
7101                 call_trans2findnotifynext(conn, req,
7102                                           &state->param, state->total_param,
7103                                           &state->data, state->total_data,
7104                                           state->max_data_return);
7105                 END_PROFILE(Trans2_findnotifynext);
7106                 break;
7107         }
7108
7109         case TRANSACT2_MKDIR:
7110         {
7111                 START_PROFILE(Trans2_mkdir);
7112                 call_trans2mkdir(conn, req,
7113                                  &state->param, state->total_param,
7114                                  &state->data, state->total_data,
7115                                  state->max_data_return);
7116                 END_PROFILE(Trans2_mkdir);
7117                 break;
7118         }
7119
7120         case TRANSACT2_GET_DFS_REFERRAL:
7121         {
7122                 START_PROFILE(Trans2_get_dfs_referral);
7123                 call_trans2getdfsreferral(conn, req,
7124                                           &state->param, state->total_param,
7125                                           &state->data, state->total_data,
7126                                           state->max_data_return);
7127                 END_PROFILE(Trans2_get_dfs_referral);
7128                 break;
7129         }
7130
7131         case TRANSACT2_IOCTL:
7132         {
7133                 START_PROFILE(Trans2_ioctl);
7134                 call_trans2ioctl(conn, req,
7135                                  &state->param, state->total_param,
7136                                  &state->data, state->total_data,
7137                                  state->max_data_return);
7138                 END_PROFILE(Trans2_ioctl);
7139                 break;
7140         }
7141
7142         default:
7143                 /* Error in request */
7144                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7145                 reply_doserror(req, ERRSRV,ERRerror);
7146         }
7147 }
7148
7149 /****************************************************************************
7150  Reply to a SMBtrans2.
7151  ****************************************************************************/
7152
7153 void reply_trans2(connection_struct *conn, struct smb_request *req)
7154 {
7155         unsigned int dsoff;
7156         unsigned int dscnt;
7157         unsigned int psoff;
7158         unsigned int pscnt;
7159         unsigned int tran_call;
7160         int size;
7161         struct trans_state *state;
7162         NTSTATUS result;
7163
7164         START_PROFILE(SMBtrans2);
7165
7166         if (req->wct < 14) {
7167                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7168                 END_PROFILE(SMBtrans2);
7169                 return;
7170         }
7171
7172         dsoff = SVAL(req->inbuf, smb_dsoff);
7173         dscnt = SVAL(req->inbuf, smb_dscnt);
7174         psoff = SVAL(req->inbuf, smb_psoff);
7175         pscnt = SVAL(req->inbuf, smb_pscnt);
7176         tran_call = SVAL(req->inbuf, smb_setup0);
7177         size = smb_len(req->inbuf) + 4;
7178
7179         result = allow_new_trans(conn->pending_trans, req->mid);
7180         if (!NT_STATUS_IS_OK(result)) {
7181                 DEBUG(2, ("Got invalid trans2 request: %s\n",
7182                           nt_errstr(result)));
7183                 reply_nterror(req, result);
7184                 END_PROFILE(SMBtrans2);
7185                 return;
7186         }
7187
7188         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
7189             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
7190             && (tran_call != TRANSACT2_QFILEINFO)) {
7191                 reply_doserror(req, ERRSRV, ERRaccess);
7192                 END_PROFILE(SMBtrans2);
7193                 return;
7194         }
7195
7196         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
7197                 DEBUG(0, ("talloc failed\n"));
7198                 reply_nterror(req, NT_STATUS_NO_MEMORY);
7199                 END_PROFILE(SMBtrans2);
7200                 return;
7201         }
7202
7203         state->cmd = SMBtrans2;
7204
7205         state->mid = req->mid;
7206         state->vuid = req->vuid;
7207         state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7208         state->setup = NULL;
7209         state->total_param = SVAL(req->inbuf, smb_tpscnt);
7210         state->param = NULL;
7211         state->total_data =  SVAL(req->inbuf, smb_tdscnt);
7212         state->data = NULL;
7213         state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7214         state->max_data_return  = SVAL(req->inbuf, smb_mdrcnt);
7215         state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7216         state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7217         state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7218
7219         state->call = tran_call;
7220
7221         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7222            is so as a sanity check */
7223         if (state->setup_count != 1) {
7224                 /*
7225                  * Need to have rc=0 for ioctl to get job id for OS/2.
7226                  *  Network printing will fail if function is not successful.
7227                  *  Similar function in reply.c will be used if protocol
7228                  *  is LANMAN1.0 instead of LM1.2X002.
7229                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
7230                  *  outbuf doesn't have to be set(only job id is used).
7231                  */
7232                 if ( (state->setup_count == 4)
7233                      && (tran_call == TRANSACT2_IOCTL)
7234                      && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7235                      && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7236                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7237                 } else {
7238                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7239                         DEBUG(2,("Transaction is %d\n",tran_call));
7240                         TALLOC_FREE(state);
7241                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7242                         END_PROFILE(SMBtrans2);
7243                         return;
7244                 }
7245         }
7246
7247         if ((dscnt > state->total_data) || (pscnt > state->total_param))
7248                 goto bad_param;
7249
7250         if (state->total_data) {
7251                 /* Can't use talloc here, the core routines do realloc on the
7252                  * params and data. */
7253                 state->data = (char *)SMB_MALLOC(state->total_data);
7254                 if (state->data == NULL) {
7255                         DEBUG(0,("reply_trans2: data malloc fail for %u "
7256                                  "bytes !\n", (unsigned int)state->total_data));
7257                         TALLOC_FREE(state);
7258                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7259                         END_PROFILE(SMBtrans2);
7260                         return;
7261                 }
7262                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
7263                         goto bad_param;
7264                 if ((smb_base(req->inbuf)+dsoff+dscnt
7265                      > (char *)req->inbuf + size) ||
7266                     (smb_base(req->inbuf)+dsoff+dscnt < smb_base(req->inbuf)))
7267                         goto bad_param;
7268
7269                 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7270         }
7271
7272         if (state->total_param) {
7273                 /* Can't use talloc here, the core routines do realloc on the
7274                  * params and data. */
7275                 state->param = (char *)SMB_MALLOC(state->total_param);
7276                 if (state->param == NULL) {
7277                         DEBUG(0,("reply_trans: param malloc fail for %u "
7278                                  "bytes !\n", (unsigned int)state->total_param));
7279                         SAFE_FREE(state->data);
7280                         TALLOC_FREE(state);
7281                         reply_nterror(req, NT_STATUS_NO_MEMORY);
7282                         END_PROFILE(SMBtrans2);
7283                         return;
7284                 } 
7285                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
7286                         goto bad_param;
7287                 if ((smb_base(req->inbuf)+psoff+pscnt
7288                      > (char *)req->inbuf + size) ||
7289                     (smb_base(req->inbuf)+psoff+pscnt < smb_base(req->inbuf)))
7290                         goto bad_param;
7291
7292                 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7293         }
7294
7295         state->received_data  = dscnt;
7296         state->received_param = pscnt;
7297
7298         if ((state->received_param == state->total_param) &&
7299             (state->received_data == state->total_data)) {
7300
7301                 handle_trans2(conn, req, state);
7302
7303                 SAFE_FREE(state->data);
7304                 SAFE_FREE(state->param);
7305                 TALLOC_FREE(state);
7306                 END_PROFILE(SMBtrans2);
7307                 return;
7308         }
7309
7310         DLIST_ADD(conn->pending_trans, state);
7311
7312         /* We need to send an interim response then receive the rest
7313            of the parameter/data bytes */
7314         reply_outbuf(req, 0, 0);
7315         show_msg((char *)req->outbuf);
7316         END_PROFILE(SMBtrans2);
7317         return;
7318
7319   bad_param:
7320
7321         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7322         SAFE_FREE(state->data);
7323         SAFE_FREE(state->param);
7324         TALLOC_FREE(state);
7325         END_PROFILE(SMBtrans2);
7326         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7327 }
7328
7329
7330 /****************************************************************************
7331  Reply to a SMBtranss2
7332  ****************************************************************************/
7333
7334 void reply_transs2(connection_struct *conn, struct smb_request *req)
7335 {
7336         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7337         struct trans_state *state;
7338         int size;
7339
7340         START_PROFILE(SMBtranss2);
7341
7342         show_msg((char *)req->inbuf);
7343
7344         if (req->wct < 8) {
7345                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7346                 END_PROFILE(SMBtranss2);
7347                 return;
7348         }
7349
7350         size = smb_len(req->inbuf)+4;
7351
7352         for (state = conn->pending_trans; state != NULL;
7353              state = state->next) {
7354                 if (state->mid == req->mid) {
7355                         break;
7356                 }
7357         }
7358
7359         if ((state == NULL) || (state->cmd != SMBtrans2)) {
7360                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7361                 END_PROFILE(SMBtranss2);
7362                 return;
7363         }
7364
7365         /* Revise state->total_param and state->total_data in case they have
7366            changed downwards */
7367
7368         if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7369                 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7370         if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7371                 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7372
7373         pcnt = SVAL(req->inbuf, smb_spscnt);
7374         poff = SVAL(req->inbuf, smb_spsoff);
7375         pdisp = SVAL(req->inbuf, smb_spsdisp);
7376
7377         dcnt = SVAL(req->inbuf, smb_sdscnt);
7378         doff = SVAL(req->inbuf, smb_sdsoff);
7379         ddisp = SVAL(req->inbuf, smb_sdsdisp);
7380
7381         state->received_param += pcnt;
7382         state->received_data += dcnt;
7383                 
7384         if ((state->received_data > state->total_data) ||
7385             (state->received_param > state->total_param))
7386                 goto bad_param;
7387
7388         if (pcnt) {
7389                 if (pdisp+pcnt > state->total_param)
7390                         goto bad_param;
7391                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
7392                         goto bad_param;
7393                 if (pdisp > state->total_param)
7394                         goto bad_param;
7395                 if ((smb_base(req->inbuf) + poff + pcnt
7396                      > (char *)req->inbuf + size) ||
7397                     (smb_base(req->inbuf) + poff + pcnt < smb_base(req->inbuf)))
7398                         goto bad_param;
7399                 if (state->param + pdisp < state->param)
7400                         goto bad_param;
7401
7402                 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7403                        pcnt);
7404         }
7405
7406         if (dcnt) {
7407                 if (ddisp+dcnt > state->total_data)
7408                         goto bad_param;
7409                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
7410                         goto bad_param;
7411                 if (ddisp > state->total_data)
7412                         goto bad_param;
7413                 if ((smb_base(req->inbuf) + doff + dcnt
7414                      > (char *)req->inbuf + size) ||
7415                     (smb_base(req->inbuf) + doff + dcnt < smb_base(req->inbuf)))
7416                         goto bad_param;
7417                 if (state->data + ddisp < state->data)
7418                         goto bad_param;
7419
7420                 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7421                        dcnt);      
7422         }
7423
7424         if ((state->received_param < state->total_param) ||
7425             (state->received_data < state->total_data)) {
7426                 END_PROFILE(SMBtranss2);
7427                 return;
7428         }
7429
7430         /*
7431          * construct_reply_common will copy smb_com from inbuf to
7432          * outbuf. SMBtranss2 is wrong here.
7433          */
7434         SCVAL(req->inbuf,smb_com,SMBtrans2);
7435
7436         handle_trans2(conn, req, state);
7437
7438         DLIST_REMOVE(conn->pending_trans, state);
7439         SAFE_FREE(state->data);
7440         SAFE_FREE(state->param);
7441         TALLOC_FREE(state);
7442
7443         END_PROFILE(SMBtranss2);
7444         return;
7445
7446   bad_param:
7447
7448         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7449         DLIST_REMOVE(conn->pending_trans, state);
7450         SAFE_FREE(state->data);
7451         SAFE_FREE(state->param);
7452         TALLOC_FREE(state);
7453         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7454         END_PROFILE(SMBtranss2);
7455         return;
7456 }