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