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