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