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