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