source: trunk/samba/source/smbd/trans2.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 193.1 KB
Line 
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
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 2 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, write to the Free Software
24   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25*/
26
27#include "includes.h"
28
29extern int max_send;
30extern enum protocol_types Protocol;
31extern int smb_read_error;
32extern uint32 global_client_caps;
33extern struct current_user current_user;
34
35#define get_file_size(sbuf) ((sbuf).st_size)
36#define DIR_ENTRY_SAFETY_MARGIN 4096
37
38static char *store_file_unix_basic(connection_struct *conn,
39                                char *pdata,
40                                files_struct *fsp,
41                                const SMB_STRUCT_STAT *psbuf);
42
43static char *store_file_unix_basic_info2(connection_struct *conn,
44                                char *pdata,
45                                files_struct *fsp,
46                                const SMB_STRUCT_STAT *psbuf);
47
48/********************************************************************
49 Roundup a value to the nearest allocation roundup size boundary.
50 Only do this for Windows clients.
51********************************************************************/
52
53SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54{
55        SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56
57        /* Only roundup for Windows clients. */
58        enum remote_arch_types ra_type = get_remote_arch();
59        if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60                val = SMB_ROUNDUP(val,rval);
61        }
62        return val;
63}
64
65/********************************************************************
66 Given a stat buffer return the allocated size on disk, taking into
67 account sparse files.
68********************************************************************/
69
70SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71{
72        SMB_BIG_UINT ret;
73
74        if(S_ISDIR(sbuf->st_mode)) {
75                return 0;
76        }
77
78#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79        ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80#else
81        ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82#endif
83
84        if (fsp && fsp->initial_allocation_size)
85                ret = MAX(ret,fsp->initial_allocation_size);
86
87        return smb_roundup(conn, ret);
88}
89
90/****************************************************************************
91 Utility functions for dealing with extended attributes.
92****************************************************************************/
93
94static const char *prohibited_ea_names[] = {
95        SAMBA_POSIX_INHERITANCE_EA_NAME,
96        SAMBA_XATTR_DOS_ATTRIB,
97        NULL
98};
99
100/****************************************************************************
101 Refuse to allow clients to overwrite our private xattrs.
102****************************************************************************/
103
104static BOOL samba_private_attr_name(const char *unix_ea_name)
105{
106        int i;
107
108        for (i = 0; prohibited_ea_names[i]; i++) {
109                if (strequal( prohibited_ea_names[i], unix_ea_name))
110                        return True;
111        }
112        return False;
113}
114
115/****************************************************************************
116 Get one EA value. Fill in a struct ea_struct.
117****************************************************************************/
118
119static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120                                const char *fname, char *ea_name, struct ea_struct *pea)
121{
122        /* Get the value of this xattr. Max size is 64k. */
123        size_t attr_size = 256;
124        char *val = NULL;
125        ssize_t sizeret;
126
127 again:
128
129        val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130        if (!val) {
131                return False;
132        }
133
134        if (fsp && fsp->fh->fd != -1) {
135                sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136        } else {
137                sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138        }
139
140        if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141                attr_size = 65536;
142                goto again;
143        }
144
145        if (sizeret == -1) {
146                return False;
147        }
148
149        DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150        dump_data(10, val, sizeret);
151
152        pea->flags = 0;
153#ifndef __OS2__
154        if (strnequal(ea_name, "user.", 5)) {
155                pea->name = &ea_name[5];
156        } else 
157#endif
158        {
159                pea->name = ea_name;
160        }
161        pea->value.data = (unsigned char *)val;
162        pea->value.length = (size_t)sizeret;
163        return True;
164}
165
166/****************************************************************************
167 Return a linked list of the total EA's. Plus the total size
168****************************************************************************/
169
170static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
171                                        const char *fname, size_t *pea_total_len)
172{
173        /* Get a list of all xattrs. Max namesize is 64k. */
174        size_t ea_namelist_size = 1024;
175        char *ea_namelist;
176        char *p;
177        ssize_t sizeret;
178        int i;
179        struct ea_list *ea_list_head = NULL;
180
181        *pea_total_len = 0;
182
183        if (!lp_ea_support(SNUM(conn))) {
184                return NULL;
185        }
186
187        for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
188             ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
189
190                if (!ea_namelist) {
191                        return NULL;
192                }
193
194                if (fsp && fsp->fh->fd != -1) {
195                        sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
196                } else {
197                        sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
198                }
199
200                if (sizeret == -1 && errno == ERANGE) {
201                        ea_namelist_size *= 2;
202                } else {
203                        break;
204                }
205        }
206
207        if (sizeret == -1){
208                return NULL;}
209
210        DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
211
212        if (sizeret) {
213                for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
214                        struct ea_list *listp;
215
216                        if (
217#ifndef __OS2__
218                                strnequal(p, "system.", 7)  ||
219#endif
220                                samba_private_attr_name(p))
221                                continue;
222               
223                        listp = TALLOC_P(mem_ctx, struct ea_list);
224                        if (!listp)
225                                return NULL;
226
227                        if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
228                                return NULL;
229                        }
230
231                        {
232                                fstring dos_ea_name;
233                                push_ascii_fstring(dos_ea_name, listp->ea.name);
234                                *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
235                                DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
236                                        (unsigned int)*pea_total_len, dos_ea_name,
237                                        (unsigned int)listp->ea.value.length ));
238                        }
239                        DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
240                }
241                /* Add on 4 for total length. */
242                if (*pea_total_len) {
243                        *pea_total_len += 4;
244                }
245        }
246
247        DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
248        return ea_list_head;
249}
250
251/****************************************************************************
252 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
253 that was filled.
254****************************************************************************/
255
256static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
257        connection_struct *conn, struct ea_list *ea_list)
258{
259        unsigned int ret_data_size = 4;
260        char *p = pdata;
261
262        SMB_ASSERT(total_data_size >= 4);
263
264        if (!lp_ea_support(SNUM(conn))) {
265                SIVAL(pdata,4,0);
266                return 4;
267        }
268
269        for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
270                size_t dos_namelen;
271                fstring dos_ea_name;
272                push_ascii_fstring(dos_ea_name, ea_list->ea.name);
273                dos_namelen = strlen(dos_ea_name);
274                if (dos_namelen > 255 || dos_namelen == 0) {
275                        break;
276                }
277                if (ea_list->ea.value.length > 65535) {
278                        break;
279                }
280                if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
281                        break;
282                }
283
284                /* We know we have room. */
285                SCVAL(p,0,ea_list->ea.flags);
286                SCVAL(p,1,dos_namelen);
287                SSVAL(p,2,ea_list->ea.value.length);
288                fstrcpy(p+4, dos_ea_name);
289                memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
290
291                total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
292                p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
293        }
294
295        ret_data_size = PTR_DIFF(p, pdata);
296        DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
297        SIVAL(pdata,0,ret_data_size);
298        return ret_data_size;
299}
300
301static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
302{
303        size_t total_ea_len = 0;
304        TALLOC_CTX *mem_ctx = NULL;
305        if (!lp_ea_support(SNUM(conn))) {
306                return 0;
307        }
308        mem_ctx = talloc_init("estimate_ea_size");
309        (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
310        talloc_destroy(mem_ctx);
311        return total_ea_len;
312}
313
314/****************************************************************************
315 Ensure the EA name is case insensitive by matching any existing EA name.
316****************************************************************************/
317
318static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
319{
320        size_t total_ea_len;
321        TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
322        struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
323
324        for (; ea_list; ea_list = ea_list->next) {
325                if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
326                        DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
327                                &unix_ea_name[5], ea_list->ea.name));
328                        safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
329                        break;
330                }
331        }
332        talloc_destroy(mem_ctx);
333}
334
335/****************************************************************************
336 Set or delete an extended attribute.
337****************************************************************************/
338
339NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
340{
341        if (!lp_ea_support(SNUM(conn))) {
342                return NT_STATUS_EAS_NOT_SUPPORTED;
343        }
344
345        for (;ea_list; ea_list = ea_list->next) {
346                int ret;
347                fstring unix_ea_name;
348
349#ifdef __OS2__
350                /* All EA's must start with user - except on OS/2 */
351                fstrcpy(unix_ea_name, ea_list->ea.name);
352#else
353                fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
354                fstrcat(unix_ea_name, ea_list->ea.name);
355#endif
356                canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
357
358                DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
359
360                if (samba_private_attr_name(unix_ea_name)) {
361                        DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
362                        return NT_STATUS_ACCESS_DENIED;
363                }
364
365                if (ea_list->ea.value.length == 0) {
366                        /* Remove the attribute. */
367                        if (fsp && (fsp->fh->fd != -1)) {
368                                DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
369                                        unix_ea_name, fsp->fsp_name));
370                                ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
371                        } else {
372                                DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
373                                        unix_ea_name, fname));
374                                ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
375                        }
376#ifdef ENOATTR
377                        /* Removing a non existent attribute always succeeds. */
378                        if (ret == -1 && errno == ENOATTR) {
379                                DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
380                                                unix_ea_name));
381                                ret = 0;
382                        }
383#endif
384                } else {
385                        if (fsp && (fsp->fh->fd != -1)) {
386                                DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
387                                        unix_ea_name, fsp->fsp_name));
388                                ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
389                                                        ea_list->ea.value.data, ea_list->ea.value.length, 0);
390                        } else {
391                                DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
392                                        unix_ea_name, fname));
393                                ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
394                                                        ea_list->ea.value.data, ea_list->ea.value.length, 0);
395                        }
396                }
397
398                if (ret == -1) {
399#ifdef ENOTSUP
400                        if (errno == ENOTSUP) {
401                                return NT_STATUS_EAS_NOT_SUPPORTED;
402                        }
403#endif
404                        return map_nt_error_from_unix(errno);
405                }
406
407        }
408        return NT_STATUS_OK;
409}
410/****************************************************************************
411 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
412****************************************************************************/
413
414static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
415{
416        struct ea_list *ea_list_head = NULL;
417        size_t offset = 0;
418
419        while (offset + 2 < data_size) {
420                struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
421                unsigned int namelen = CVAL(pdata,offset);
422
423                offset++; /* Go past the namelen byte. */
424
425                /* integer wrap paranioa. */
426                if ((offset + namelen < offset) || (offset + namelen < namelen) ||
427                                (offset > data_size) || (namelen > data_size) ||
428                                (offset + namelen >= data_size)) {
429                        break;
430                }
431                /* Ensure the name is null terminated. */
432                if (pdata[offset + namelen] != '\0') {
433                        return NULL;
434                }
435                pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
436                if (!eal->ea.name) {
437                        return NULL;
438                }
439
440                offset += (namelen + 1); /* Go past the name + terminating zero. */
441                DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
442                DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
443        }
444
445        return ea_list_head;
446}
447
448/****************************************************************************
449 Read one EA list entry from the buffer.
450****************************************************************************/
451
452struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
453{
454        struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
455        uint16 val_len;
456        unsigned int namelen;
457
458        if (!eal) {
459                return NULL;
460        }
461
462        if (data_size < 6) {
463                return NULL;
464        }
465
466        eal->ea.flags = CVAL(pdata,0);
467        namelen = CVAL(pdata,1);
468        val_len = SVAL(pdata,2);
469
470        if (4 + namelen + 1 + val_len > data_size) {
471                return NULL;
472        }
473
474        /* Ensure the name is null terminated. */
475        if (pdata[namelen + 4] != '\0') {
476                return NULL;
477        }
478        pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
479        if (!eal->ea.name) {
480                return NULL;
481        }
482
483        eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
484        if (!eal->ea.value.data) {
485                return NULL;
486        }
487
488        memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
489
490        /* Ensure we're null terminated just in case we print the value. */
491        eal->ea.value.data[val_len] = '\0';
492        /* But don't count the null. */
493        eal->ea.value.length--;
494
495        if (pbytes_used) {
496                *pbytes_used = 4 + namelen + 1 + val_len;
497        }
498
499        DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
500        dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
501
502        return eal;
503}
504
505/****************************************************************************
506 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
507****************************************************************************/
508
509static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
510{
511        struct ea_list *ea_list_head = NULL;
512        size_t offset = 0;
513        size_t bytes_used = 0;
514
515        while (offset < data_size) {
516                struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
517
518                if (!eal) {
519                        return NULL;
520                }
521
522                DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
523                offset += bytes_used;
524        }
525
526        return ea_list_head;
527}
528
529/****************************************************************************
530 Count the total EA size needed.
531****************************************************************************/
532
533static size_t ea_list_size(struct ea_list *ealist)
534{
535        fstring dos_ea_name;
536        struct ea_list *listp;
537        size_t ret = 0;
538
539        for (listp = ealist; listp; listp = listp->next) {
540                push_ascii_fstring(dos_ea_name, listp->ea.name);
541                ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
542        }
543        /* Add on 4 for total length. */
544        if (ret) {
545                ret += 4;
546        }
547
548        return ret;
549}
550
551/****************************************************************************
552 Return a union of EA's from a file list and a list of names.
553 The TALLOC context for the two lists *MUST* be identical as we steal
554 memory from one list to add to another. JRA.
555****************************************************************************/
556
557static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
558{
559        struct ea_list *nlistp, *flistp;
560
561        for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
562                for (flistp = file_list; flistp; flistp = flistp->next) {
563                        if (strequal(nlistp->ea.name, flistp->ea.name)) {
564                                break;
565                        }
566                }
567
568                if (flistp) {
569                        /* Copy the data from this entry. */
570                        nlistp->ea.flags = flistp->ea.flags;
571                        nlistp->ea.value = flistp->ea.value;
572                } else {
573                        /* Null entry. */
574                        nlistp->ea.flags = 0;
575                        ZERO_STRUCT(nlistp->ea.value);
576                }
577        }
578
579        *total_ea_len = ea_list_size(name_list);
580        return name_list;
581}
582
583/****************************************************************************
584  Send the required number of replies back.
585  We assume all fields other than the data fields are
586  set correctly for the type of call.
587  HACK ! Always assumes smb_setup field is zero.
588****************************************************************************/
589
590int send_trans2_replies(char *outbuf,
591                        int bufsize,
592                        const char *params, 
593                        int paramsize,
594                        const char *pdata,
595                        int datasize,
596                        int max_data_bytes)
597{
598        /* As we are using a protocol > LANMAN1 then the max_send
599         variable must have been set in the sessetupX call.
600         This takes precedence over the max_xmit field in the
601         global struct. These different max_xmit variables should
602         be merged as this is now too confusing */
603
604        int data_to_send = datasize;
605        int params_to_send = paramsize;
606        int useable_space;
607        const char *pp = params;
608        const char *pd = pdata;
609        int params_sent_thistime, data_sent_thistime, total_sent_thistime;
610        int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
611        int data_alignment_offset = 0;
612
613        /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
614       
615        set_message(outbuf,10,0,True);
616
617        /* Modify the data_to_send and datasize and set the error if
618           we're trying to send more than max_data_bytes. We still send
619           the part of the packet(s) that fit. Strange, but needed
620           for OS/2. */
621
622        if (max_data_bytes > 0 && datasize > max_data_bytes) {
623                DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
624                        max_data_bytes, datasize ));
625                datasize = data_to_send = max_data_bytes;
626                error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
627        }
628
629        /* If there genuinely are no parameters or data to send just send the empty packet */
630
631        if(params_to_send == 0 && data_to_send == 0) {
632                show_msg(outbuf);
633                if (!send_smb(smbd_server_fd(),outbuf))
634                        exit_server_cleanly("send_trans2_replies: send_smb failed.");
635                return 0;
636        }
637
638        /* When sending params and data ensure that both are nicely aligned */
639        /* Only do this alignment when there is also data to send - else
640                can cause NT redirector problems. */
641
642        if (((params_to_send % 4) != 0) && (data_to_send != 0))
643                data_alignment_offset = 4 - (params_to_send % 4);
644
645        /* Space is bufsize minus Netbios over TCP header minus SMB header */
646        /* The alignment_offset is to align the param bytes on an even byte
647                boundary. NT 4.0 Beta needs this to work correctly. */
648
649        useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
650
651        /* useable_space can never be more than max_send minus the alignment offset. */
652
653        useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
654
655        while (params_to_send || data_to_send) {
656                /* Calculate whether we will totally or partially fill this packet */
657
658                total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
659
660                /* We can never send more than useable_space */
661                /*
662                 * Note that 'useable_space' does not include the alignment offsets,
663                 * but we must include the alignment offsets in the calculation of
664                 * the length of the data we send over the wire, as the alignment offsets
665                 * are sent here. Fix from Marc_Jacobsen@hp.com.
666                 */
667
668                total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
669
670                set_message(outbuf, 10, total_sent_thistime, True);
671
672                /* Set total params and data to be sent */
673                SSVAL(outbuf,smb_tprcnt,paramsize);
674                SSVAL(outbuf,smb_tdrcnt,datasize);
675
676                /* Calculate how many parameters and data we can fit into
677                 * this packet. Parameters get precedence
678                 */
679
680                params_sent_thistime = MIN(params_to_send,useable_space);
681                data_sent_thistime = useable_space - params_sent_thistime;
682                data_sent_thistime = MIN(data_sent_thistime,data_to_send);
683
684                SSVAL(outbuf,smb_prcnt, params_sent_thistime);
685
686                /* smb_proff is the offset from the start of the SMB header to the
687                        parameter bytes, however the first 4 bytes of outbuf are
688                        the Netbios over TCP header. Thus use smb_base() to subtract
689                        them from the calculation */
690
691                SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
692
693                if(params_sent_thistime == 0)
694                        SSVAL(outbuf,smb_prdisp,0);
695                else
696                        /* Absolute displacement of param bytes sent in this packet */
697                        SSVAL(outbuf,smb_prdisp,pp - params);
698
699                SSVAL(outbuf,smb_drcnt, data_sent_thistime);
700                if(data_sent_thistime == 0) {
701                        SSVAL(outbuf,smb_droff,0);
702                        SSVAL(outbuf,smb_drdisp, 0);
703                } else {
704                        /* The offset of the data bytes is the offset of the
705                                parameter bytes plus the number of parameters being sent this time */
706                        SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
707                                smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
708                        SSVAL(outbuf,smb_drdisp, pd - pdata);
709                }
710
711                /* Copy the param bytes into the packet */
712
713                if(params_sent_thistime)
714                        memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
715
716                /* Copy in the data bytes */
717                if(data_sent_thistime)
718                        memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
719                                data_alignment_offset,pd,data_sent_thistime);
720
721                DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
722                        params_sent_thistime, data_sent_thistime, useable_space));
723                DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
724                        params_to_send, data_to_send, paramsize, datasize));
725
726                /* Send the packet */
727                show_msg(outbuf);
728                if (!send_smb(smbd_server_fd(),outbuf))
729                        exit_server_cleanly("send_trans2_replies: send_smb failed.");
730
731                pp += params_sent_thistime;
732                pd += data_sent_thistime;
733
734                params_to_send -= params_sent_thistime;
735                data_to_send -= data_sent_thistime;
736
737                /* Sanity check */
738                if(params_to_send < 0 || data_to_send < 0) {
739                        DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
740                                params_to_send, data_to_send));
741                        return -1;
742                }
743        }
744
745        return 0;
746}
747
748/****************************************************************************
749 Reply to a TRANSACT2_OPEN.
750****************************************************************************/
751
752static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, 
753                                char **pparams, int total_params, char **ppdata, int total_data,
754                                unsigned int max_data_bytes)
755{
756        char *params = *pparams;
757        char *pdata = *ppdata;
758        int deny_mode;
759        int32 open_attr;
760        BOOL oplock_request;
761#if 0
762        BOOL return_additional_info;
763        int16 open_sattr;
764        time_t open_time;
765#endif
766        int open_ofun;
767        uint32 open_size;
768        char *pname;
769        pstring fname;
770        SMB_OFF_T size=0;
771        int fattr=0,mtime=0;
772        SMB_INO_T inode = 0;
773        SMB_STRUCT_STAT sbuf;
774        int smb_action = 0;
775        files_struct *fsp;
776        struct ea_list *ea_list = NULL;
777        uint16 flags = 0;
778        NTSTATUS status;
779        uint32 access_mask;
780        uint32 share_mode;
781        uint32 create_disposition;
782        uint32 create_options = 0;
783
784        /*
785         * Ensure we have enough parameters to perform the operation.
786         */
787
788        if (total_params < 29) {
789                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
790        }
791
792        flags = SVAL(params, 0);
793        deny_mode = SVAL(params, 2);
794        open_attr = SVAL(params,6);
795        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
796        if (oplock_request) {
797                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
798        }
799
800#if 0
801        return_additional_info = BITSETW(params,0);
802        open_sattr = SVAL(params, 4);
803        open_time = make_unix_date3(params+8);
804#endif
805        open_ofun = SVAL(params,12);
806        open_size = IVAL(params,14);
807        pname = &params[28];
808
809        if (IS_IPC(conn)) {
810                return(ERROR_DOS(ERRSRV,ERRaccess));
811        }
812
813        srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
814        if (!NT_STATUS_IS_OK(status)) {
815                return ERROR_NT(status);
816        }
817
818        DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
819                fname, (unsigned int)deny_mode, (unsigned int)open_attr,
820                (unsigned int)open_ofun, open_size));
821
822        /* XXXX we need to handle passed times, sattr and flags */
823
824        status = unix_convert(conn, fname, False, NULL, &sbuf);
825        if (!NT_STATUS_IS_OK(status)) {
826                return ERROR_NT(status);
827        }
828   
829        status = check_name(conn, fname);
830        if (!NT_STATUS_IS_OK(status)) {
831                return ERROR_NT(status);
832        }
833
834        if (open_ofun == 0) {
835                return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
836        }
837
838        if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
839                                &access_mask,
840                                &share_mode,
841                                &create_disposition,
842                                &create_options)) {
843                return ERROR_DOS(ERRDOS, ERRbadaccess);
844        }
845
846        /* Any data in this call is an EA list. */
847        if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
848                return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
849        }
850
851        if (total_data != 4) {
852                if (total_data < 10) {
853                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
854                }
855
856                if (IVAL(pdata,0) > total_data) {
857                        DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
858                                IVAL(pdata,0), (unsigned int)total_data));
859                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
860                }
861
862                ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
863                                       total_data - 4);
864                if (!ea_list) {
865                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
866                }
867        } else if (IVAL(pdata,0) != 4) {
868                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
869        }
870
871        status = open_file_ntcreate(conn,fname,&sbuf,
872                access_mask,
873                share_mode,
874                create_disposition,
875                create_options,
876                open_attr,
877                oplock_request,
878                &smb_action, &fsp);
879     
880        if (!NT_STATUS_IS_OK(status)) {
881                if (open_was_deferred(SVAL(inbuf,smb_mid))) {
882                        /* We have re-scheduled this call. */
883                        return -1;
884                }
885                return ERROR_NT(status);
886        }
887
888        size = get_file_size(sbuf);
889        fattr = dos_mode(conn,fname,&sbuf);
890        mtime = sbuf.st_mtime;
891        inode = sbuf.st_ino;
892        if (fattr & aDIR) {
893                close_file(fsp,ERROR_CLOSE);
894                return(ERROR_DOS(ERRDOS,ERRnoaccess));
895        }
896
897        /* Save the requested allocation size. */
898        /* Allocate space for the file if a size hint is supplied */
899        if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
900                SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
901                if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
902                        fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
903                        if (fsp->is_directory) {
904                                close_file(fsp,ERROR_CLOSE);
905                                /* Can't set allocation size on a directory. */
906                                return ERROR_NT(NT_STATUS_ACCESS_DENIED);
907                        }
908                        if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
909                                close_file(fsp,ERROR_CLOSE);
910                                return ERROR_NT(NT_STATUS_DISK_FULL);
911                        }
912
913                        /* Adjust size here to return the right size in the reply.
914                           Windows does it this way. */
915                        size = fsp->initial_allocation_size;
916                } else {
917                        fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
918                }
919        }
920
921        if (ea_list && smb_action == FILE_WAS_CREATED) {
922                status = set_ea(conn, fsp, fname, ea_list);
923                if (!NT_STATUS_IS_OK(status)) {
924                        close_file(fsp,ERROR_CLOSE);
925                        return ERROR_NT(status);
926                }
927        }
928
929        /* Realloc the size of parameters and data we will return */
930        *pparams = (char *)SMB_REALLOC(*pparams, 30);
931        if(*pparams == NULL ) {
932                return ERROR_NT(NT_STATUS_NO_MEMORY);
933        }
934        params = *pparams;
935
936        SSVAL(params,0,fsp->fnum);
937        SSVAL(params,2,fattr);
938        srv_put_dos_date2(params,4, mtime);
939        SIVAL(params,8, (uint32)size);
940        SSVAL(params,12,deny_mode);
941        SSVAL(params,14,0); /* open_type - file or directory. */
942        SSVAL(params,16,0); /* open_state - only valid for IPC device. */
943
944        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
945                smb_action |= EXTENDED_OPLOCK_GRANTED;
946        }
947
948        SSVAL(params,18,smb_action);
949
950        /*
951         * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
952         */
953        SIVAL(params,20,inode);
954        SSVAL(params,24,0); /* Padding. */
955        if (flags & 8) {
956                uint32 ea_size = estimate_ea_size(conn, fsp, fname);
957                SIVAL(params, 26, ea_size);
958        } else {
959                SIVAL(params, 26, 0);
960        }
961
962        /* Send the required number of replies */
963        send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
964
965        return -1;
966}
967
968/*********************************************************
969 Routine to check if a given string matches exactly.
970 as a special case a mask of "." does NOT match. That
971 is required for correct wildcard semantics
972 Case can be significant or not.
973**********************************************************/
974
975static BOOL exact_match(connection_struct *conn, char *str, char *mask)
976{
977        if (mask[0] == '.' && mask[1] == 0)
978                return False;
979        if (conn->case_sensitive)
980                return strcmp(str,mask)==0;
981        if (StrCaseCmp(str,mask) != 0) {
982                return False;
983        }
984        if (dptr_has_wild(conn->dirptr)) {
985                return False;
986        }
987        return True;
988}
989
990/****************************************************************************
991 Return the filetype for UNIX extensions.
992****************************************************************************/
993
994static uint32 unix_filetype(mode_t mode)
995{
996        if(S_ISREG(mode))
997                return UNIX_TYPE_FILE;
998        else if(S_ISDIR(mode))
999                return UNIX_TYPE_DIR;
1000#ifdef S_ISLNK
1001        else if(S_ISLNK(mode))
1002                return UNIX_TYPE_SYMLINK;
1003#endif
1004#ifdef S_ISCHR
1005        else if(S_ISCHR(mode))
1006                return UNIX_TYPE_CHARDEV;
1007#endif
1008#ifdef S_ISBLK
1009        else if(S_ISBLK(mode))
1010                return UNIX_TYPE_BLKDEV;
1011#endif
1012#ifdef S_ISFIFO
1013        else if(S_ISFIFO(mode))
1014                return UNIX_TYPE_FIFO;
1015#endif
1016#ifdef S_ISSOCK
1017        else if(S_ISSOCK(mode))
1018                return UNIX_TYPE_SOCKET;
1019#endif
1020
1021        DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1022        return UNIX_TYPE_UNKNOWN;
1023}
1024
1025/****************************************************************************
1026 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1027****************************************************************************/
1028
1029enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1030
1031static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1032                                SMB_STRUCT_STAT *psbuf,
1033                                uint32 perms,
1034                                enum perm_type ptype,
1035                                mode_t *ret_perms)
1036{
1037        mode_t ret = 0;
1038
1039        if (perms == SMB_MODE_NO_CHANGE) {
1040                if (!VALID_STAT(*psbuf)) {
1041                        return NT_STATUS_INVALID_PARAMETER;
1042                } else {
1043                        *ret_perms = psbuf->st_mode;
1044                        return NT_STATUS_OK;
1045                }
1046        }
1047
1048        ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1049        ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1050        ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1051        ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1052        ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1053        ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1054        ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1055        ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1056        ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1057#ifdef S_ISVTX
1058        ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1059#endif
1060#ifdef S_ISGID
1061        ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1062#endif
1063#ifdef S_ISUID
1064        ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1065#endif
1066
1067        switch (ptype) {
1068        case PERM_NEW_FILE:
1069                /* Apply mode mask */
1070                ret &= lp_create_mask(SNUM(conn));
1071                /* Add in force bits */
1072                ret |= lp_force_create_mode(SNUM(conn));
1073                break;
1074        case PERM_NEW_DIR:
1075                ret &= lp_dir_mask(SNUM(conn));
1076                /* Add in force bits */
1077                ret |= lp_force_dir_mode(SNUM(conn));
1078                break;
1079        case PERM_EXISTING_FILE:
1080                /* Apply mode mask */
1081                ret &= lp_security_mask(SNUM(conn));
1082                /* Add in force bits */
1083                ret |= lp_force_security_mode(SNUM(conn));
1084                break;
1085        case PERM_EXISTING_DIR:
1086                /* Apply mode mask */
1087                ret &= lp_dir_security_mask(SNUM(conn));
1088                /* Add in force bits */
1089                ret |= lp_force_dir_security_mode(SNUM(conn));
1090                break;
1091        }
1092
1093        *ret_perms = ret;
1094        return NT_STATUS_OK;
1095}
1096
1097/****************************************************************************
1098 Get a level dependent lanman2 dir entry.
1099****************************************************************************/
1100
1101static BOOL get_lanman2_dir_entry(connection_struct *conn,
1102                                  void *inbuf, char *outbuf,
1103                                 char *path_mask,uint32 dirtype,int info_level,
1104                                 int requires_resume_key,
1105                                 BOOL dont_descend,char **ppdata, 
1106                                 char *base_data, int space_remaining, 
1107                                 BOOL *out_of_space, BOOL *got_exact_match,
1108                                 int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1109{
1110        const char *dname;
1111        BOOL found = False;
1112        SMB_STRUCT_STAT sbuf;
1113        pstring mask;
1114        pstring pathreal;
1115        pstring fname;
1116        char *p, *q, *pdata = *ppdata;
1117        uint32 reskey=0;
1118        long prev_dirpos=0;
1119        uint32 mode=0;
1120        SMB_OFF_T file_size = 0;
1121        SMB_BIG_UINT allocation_size = 0;
1122        uint32 len;
1123        struct timespec mdate_ts, adate_ts, create_date_ts;
1124        time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1125        char *nameptr;
1126        char *last_entry_ptr;
1127        BOOL was_8_3;
1128        uint32 nt_extmode; /* Used for NT connections instead of mode */
1129        BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1130        BOOL check_mangled_names = lp_manglednames(conn->params);
1131
1132        *fname = 0;
1133        *out_of_space = False;
1134        *got_exact_match = False;
1135
1136        ZERO_STRUCT(mdate_ts);
1137        ZERO_STRUCT(adate_ts);
1138        ZERO_STRUCT(create_date_ts);
1139
1140        if (!conn->dirptr)
1141                return(False);
1142
1143        p = strrchr_m(path_mask,'/');
1144        if(p != NULL) {
1145                if(p[1] == '\0')
1146                        pstrcpy(mask,"*.*");
1147                else
1148                        pstrcpy(mask, p+1);
1149        } else
1150                pstrcpy(mask, path_mask);
1151
1152
1153        while (!found) {
1154                BOOL got_match;
1155                BOOL ms_dfs_link = False;
1156
1157                /* Needed if we run out of space */
1158                long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1159                dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1160
1161                /*
1162                 * Due to bugs in NT client redirectors we are not using
1163                 * resume keys any more - set them to zero.
1164                 * Check out the related comments in findfirst/findnext.
1165                 * JRA.
1166                 */
1167
1168                reskey = 0;
1169
1170                DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1171                        (long)conn->dirptr,curr_dirpos));
1172     
1173                if (!dname) 
1174                        return(False);
1175
1176                pstrcpy(fname,dname);     
1177
1178                if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1179                        got_match = mask_match(fname, mask, conn->case_sensitive);
1180
1181                if(!got_match && check_mangled_names &&
1182                   !mangle_is_8_3(fname, False, conn->params)) {
1183
1184                        /*
1185                         * It turns out that NT matches wildcards against
1186                         * both long *and* short names. This may explain some
1187                         * of the wildcard wierdness from old DOS clients
1188                         * that some people have been seeing.... JRA.
1189                         */
1190
1191                        pstring newname;
1192                        pstrcpy( newname, fname);
1193                        mangle_map( newname, True, False, conn->params);
1194                        if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1195                                got_match = mask_match(newname, mask, conn->case_sensitive);
1196                }
1197
1198                if(got_match) {
1199                        BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1200                        if (dont_descend && !isdots)
1201                                continue;
1202         
1203                        pstrcpy(pathreal,conn->dirpath);
1204                        if(needslash)
1205                                pstrcat(pathreal,"/");
1206                        pstrcat(pathreal,dname);
1207
1208                        if (INFO_LEVEL_IS_UNIX(info_level)) {
1209                                if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1210                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1211                                                pathreal,strerror(errno)));
1212                                        continue;
1213                                }
1214                        } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1215                                pstring link_target;
1216
1217                                /* Needed to show the msdfs symlinks as
1218                                 * directories */
1219
1220                                if(lp_host_msdfs() && 
1221                                   lp_msdfs_root(SNUM(conn)) &&
1222                                   ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
1223                                        DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
1224                                                "as a directory\n",
1225                                                pathreal));
1226                                        sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1227
1228                                } else {
1229
1230                                        DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1231                                                pathreal,strerror(errno)));
1232                                        continue;
1233                                }
1234                        }
1235
1236                        if (ms_dfs_link) {
1237                                mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1238                        } else {
1239                                mode = dos_mode(conn,pathreal,&sbuf);
1240                        }
1241
1242                        if (!dir_check_ftype(conn,mode,dirtype)) {
1243                                DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1244                                continue;
1245                        }
1246
1247                        if (!(mode & aDIR))
1248                                file_size = get_file_size(sbuf);
1249                        allocation_size = get_allocation_size(conn,NULL,&sbuf);
1250
1251                        mdate_ts = get_mtimespec(&sbuf);
1252                        adate_ts = get_atimespec(&sbuf);
1253                        create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1254
1255                        if (lp_dos_filetime_resolution(SNUM(conn))) {
1256                                dos_filetime_timespec(&create_date_ts);
1257                                dos_filetime_timespec(&mdate_ts);
1258                                dos_filetime_timespec(&adate_ts);
1259                        }
1260
1261                        create_date = convert_timespec_to_time_t(create_date_ts);
1262                        mdate = convert_timespec_to_time_t(mdate_ts);
1263                        adate = convert_timespec_to_time_t(adate_ts);
1264                       
1265                        DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1266         
1267                        found = True;
1268
1269                        dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1270                }
1271        }
1272
1273        mangle_map(fname,False,True,conn->params);
1274
1275        p = pdata;
1276        last_entry_ptr = p;
1277
1278        nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1279
1280        switch (info_level) {
1281                case SMB_FIND_INFO_STANDARD:
1282                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1283                        if(requires_resume_key) {
1284                                SIVAL(p,0,reskey);
1285                                p += 4;
1286                        }
1287                        srv_put_dos_date2(p,0,create_date);
1288                        srv_put_dos_date2(p,4,adate);
1289                        srv_put_dos_date2(p,8,mdate);
1290                        SIVAL(p,12,(uint32)file_size);
1291                        SIVAL(p,16,(uint32)allocation_size);
1292                        SSVAL(p,20,mode);
1293                        p += 23;
1294                        nameptr = p;
1295                        p += align_string(outbuf, p, 0);
1296                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1297                        if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1298                                if (len > 2) {
1299                                        SCVAL(nameptr, -1, len - 2);
1300                                } else {
1301                                        SCVAL(nameptr, -1, 0);
1302                                }
1303                        } else {
1304                                if (len > 1) {
1305                                        SCVAL(nameptr, -1, len - 1);
1306                                } else {
1307                                        SCVAL(nameptr, -1, 0);
1308                                }
1309                        }
1310                        p += len;
1311                        break;
1312
1313                case SMB_FIND_EA_SIZE:
1314                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1315                        if(requires_resume_key) {
1316                                SIVAL(p,0,reskey);
1317                                p += 4;
1318                        }
1319                        srv_put_dos_date2(p,0,create_date);
1320                        srv_put_dos_date2(p,4,adate);
1321                        srv_put_dos_date2(p,8,mdate);
1322                        SIVAL(p,12,(uint32)file_size);
1323                        SIVAL(p,16,(uint32)allocation_size);
1324                        SSVAL(p,20,mode);
1325                        {
1326                                unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1327                                SIVAL(p,22,ea_size); /* Extended attributes */
1328                        }
1329                        p += 27;
1330                        nameptr = p - 1;
1331                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1332                        if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1333                                if (len > 2) {
1334                                        len -= 2;
1335                                } else {
1336                                        len = 0;
1337                                }
1338                        } else {
1339                                if (len > 1) {
1340                                        len -= 1;
1341                                } else {
1342                                        len = 0;
1343                                }
1344                        }
1345                        SCVAL(nameptr,0,len);
1346                        p += len;
1347                        SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1348                        break;
1349
1350                case SMB_FIND_EA_LIST:
1351                {
1352                        struct ea_list *file_list = NULL;
1353                        size_t ea_len = 0;
1354
1355                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1356                        if (!name_list) {
1357                                return False;
1358                        }
1359                        if(requires_resume_key) {
1360                                SIVAL(p,0,reskey);
1361                                p += 4;
1362                        }
1363                        srv_put_dos_date2(p,0,create_date);
1364                        srv_put_dos_date2(p,4,adate);
1365                        srv_put_dos_date2(p,8,mdate);
1366                        SIVAL(p,12,(uint32)file_size);
1367                        SIVAL(p,16,(uint32)allocation_size);
1368                        SSVAL(p,20,mode);
1369                        p += 22; /* p now points to the EA area. */
1370
1371                        file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1372                        name_list = ea_list_union(name_list, file_list, &ea_len);
1373
1374                        /* We need to determine if this entry will fit in the space available. */
1375                        /* Max string size is 255 bytes. */
1376                        if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1377                                /* Move the dirptr back to prev_dirpos */
1378                                dptr_SeekDir(conn->dirptr, prev_dirpos);
1379                                *out_of_space = True;
1380                                DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1381                                return False; /* Not finished - just out of space */
1382                        }
1383
1384                        /* Push the ea_data followed by the name. */
1385                        p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1386                        nameptr = p;
1387                        len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1388                        if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1389                                if (len > 2) {
1390                                        len -= 2;
1391                                } else {
1392                                        len = 0;
1393                                }
1394                        } else {
1395                                if (len > 1) {
1396                                        len -= 1;
1397                                } else {
1398                                        len = 0;
1399                                }
1400                        }
1401                        SCVAL(nameptr,0,len);
1402                        p += len + 1;
1403                        SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1404                        break;
1405                }
1406
1407                case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1408                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1409                        was_8_3 = mangle_is_8_3(fname, True, conn->params);
1410                        p += 4;
1411                        SIVAL(p,0,reskey); p += 4;
1412                        put_long_date_timespec(p,create_date_ts); p += 8;
1413                        put_long_date_timespec(p,adate_ts); p += 8;
1414                        put_long_date_timespec(p,mdate_ts); p += 8;
1415                        put_long_date_timespec(p,mdate_ts); p += 8;
1416                        SOFF_T(p,0,file_size); p += 8;
1417                        SOFF_T(p,0,allocation_size); p += 8;
1418                        SIVAL(p,0,nt_extmode); p += 4;
1419                        q = p; p += 4; /* q is placeholder for name length. */
1420                        {
1421                                unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1422                                SIVAL(p,0,ea_size); /* Extended attributes */
1423                                p += 4;
1424                        }
1425                        /* Clear the short name buffer. This is
1426                         * IMPORTANT as not doing so will trigger
1427                         * a Win2k client bug. JRA.
1428                         */
1429                        if (!was_8_3 && check_mangled_names) {
1430                                pstring mangled_name;
1431                                pstrcpy(mangled_name, fname);
1432                                mangle_map(mangled_name,True,True,
1433                                           conn->params);
1434                                mangled_name[12] = 0;
1435                                len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1436                                if (len < 24) {
1437                                        memset(p + 2 + len,'\0',24 - len);
1438                                }
1439                                SSVAL(p, 0, len);
1440                        } else {
1441                                memset(p,'\0',26);
1442                        }
1443                        p += 2 + 24;
1444                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1445                        SIVAL(q,0,len);
1446                        p += len;
1447                        SIVAL(p,0,0); /* Ensure any padding is null. */
1448                        len = PTR_DIFF(p, pdata);
1449                        len = (len + 3) & ~3;
1450                        SIVAL(pdata,0,len);
1451                        p = pdata + len;
1452                        break;
1453
1454                case SMB_FIND_FILE_DIRECTORY_INFO:
1455                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1456                        p += 4;
1457                        SIVAL(p,0,reskey); p += 4;
1458                        put_long_date_timespec(p,create_date_ts); p += 8;
1459                        put_long_date_timespec(p,adate_ts); p += 8;
1460                        put_long_date_timespec(p,mdate_ts); p += 8;
1461                        put_long_date_timespec(p,mdate_ts); p += 8;
1462                        SOFF_T(p,0,file_size); p += 8;
1463                        SOFF_T(p,0,allocation_size); p += 8;
1464                        SIVAL(p,0,nt_extmode); p += 4;
1465                        len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1466                        SIVAL(p,0,len);
1467                        p += 4 + len;
1468                        SIVAL(p,0,0); /* Ensure any padding is null. */
1469                        len = PTR_DIFF(p, pdata);
1470                        len = (len + 3) & ~3;
1471                        SIVAL(pdata,0,len);
1472                        p = pdata + len;
1473                        break;
1474     
1475                case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1476                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1477                        p += 4;
1478                        SIVAL(p,0,reskey); p += 4;
1479                        put_long_date_timespec(p,create_date_ts); p += 8;
1480                        put_long_date_timespec(p,adate_ts); p += 8;
1481                        put_long_date_timespec(p,mdate_ts); p += 8;
1482                        put_long_date_timespec(p,mdate_ts); p += 8;
1483                        SOFF_T(p,0,file_size); p += 8;
1484                        SOFF_T(p,0,allocation_size); p += 8;
1485                        SIVAL(p,0,nt_extmode); p += 4;
1486                        q = p; p += 4; /* q is placeholder for name length. */
1487                        {
1488                                unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1489                                SIVAL(p,0,ea_size); /* Extended attributes */
1490                                p +=4;
1491                        }
1492                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1493                        SIVAL(q, 0, len);
1494                        p += len;
1495
1496                        SIVAL(p,0,0); /* Ensure any padding is null. */
1497                        len = PTR_DIFF(p, pdata);
1498                        len = (len + 3) & ~3;
1499                        SIVAL(pdata,0,len);
1500                        p = pdata + len;
1501                        break;
1502
1503                case SMB_FIND_FILE_NAMES_INFO:
1504                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1505                        p += 4;
1506                        SIVAL(p,0,reskey); p += 4;
1507                        p += 4;
1508                        /* this must *not* be null terminated or w2k gets in a loop trying to set an
1509                           acl on a dir (tridge) */
1510                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1511                        SIVAL(p, -4, len);
1512                        p += len;
1513                        SIVAL(p,0,0); /* Ensure any padding is null. */
1514                        len = PTR_DIFF(p, pdata);
1515                        len = (len + 3) & ~3;
1516                        SIVAL(pdata,0,len);
1517                        p = pdata + len;
1518                        break;
1519
1520                case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1521                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1522                        p += 4;
1523                        SIVAL(p,0,reskey); p += 4;
1524                        put_long_date_timespec(p,create_date_ts); p += 8;
1525                        put_long_date_timespec(p,adate_ts); p += 8;
1526                        put_long_date_timespec(p,mdate_ts); p += 8;
1527                        put_long_date_timespec(p,mdate_ts); p += 8;
1528                        SOFF_T(p,0,file_size); p += 8;
1529                        SOFF_T(p,0,allocation_size); p += 8;
1530                        SIVAL(p,0,nt_extmode); p += 4;
1531                        q = p; p += 4; /* q is placeholder for name length. */
1532                        {
1533                                unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1534                                SIVAL(p,0,ea_size); /* Extended attributes */
1535                                p +=4;
1536                        }
1537                        SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1538                        SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1539                        SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1540                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1541                        SIVAL(q, 0, len);
1542                        p += len; 
1543                        SIVAL(p,0,0); /* Ensure any padding is null. */
1544                        len = PTR_DIFF(p, pdata);
1545                        len = (len + 3) & ~3;
1546                        SIVAL(pdata,0,len);
1547                        p = pdata + len;
1548                        break;
1549
1550                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1551                        DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1552                        was_8_3 = mangle_is_8_3(fname, True, conn->params);
1553                        p += 4;
1554                        SIVAL(p,0,reskey); p += 4;
1555                        put_long_date_timespec(p,create_date_ts); p += 8;
1556                        put_long_date_timespec(p,adate_ts); p += 8;
1557                        put_long_date_timespec(p,mdate_ts); p += 8;
1558                        put_long_date_timespec(p,mdate_ts); p += 8;
1559                        SOFF_T(p,0,file_size); p += 8;
1560                        SOFF_T(p,0,allocation_size); p += 8;
1561                        SIVAL(p,0,nt_extmode); p += 4;
1562                        q = p; p += 4; /* q is placeholder for name length */
1563                        {
1564                                unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1565                                SIVAL(p,0,ea_size); /* Extended attributes */
1566                                p +=4;
1567                        }
1568                        /* Clear the short name buffer. This is
1569                         * IMPORTANT as not doing so will trigger
1570                         * a Win2k client bug. JRA.
1571                         */
1572                        if (!was_8_3 && check_mangled_names) {
1573                                pstring mangled_name;
1574                                pstrcpy(mangled_name, fname);
1575                                mangle_map(mangled_name,True,True,
1576                                           conn->params);
1577                                mangled_name[12] = 0;
1578                                len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1579                                SSVAL(p, 0, len);
1580                                if (len < 24) {
1581                                        memset(p + 2 + len,'\0',24 - len);
1582                                }
1583                                SSVAL(p, 0, len);
1584                        } else {
1585                                memset(p,'\0',26);
1586                        }
1587                        p += 26;
1588                        SSVAL(p,0,0); p += 2; /* Reserved ? */
1589                        SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1590                        SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1591                        len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1592                        SIVAL(q,0,len);
1593                        p += len;
1594                        SIVAL(p,0,0); /* Ensure any padding is null. */
1595                        len = PTR_DIFF(p, pdata);
1596                        len = (len + 3) & ~3;
1597                        SIVAL(pdata,0,len);
1598                        p = pdata + len;
1599                        break;
1600
1601                /* CIFS UNIX Extension. */
1602
1603                case SMB_FIND_FILE_UNIX:
1604                case SMB_FIND_FILE_UNIX_INFO2:
1605                        p+= 4;
1606                        SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1607
1608                        /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1609
1610                        if (info_level == SMB_FIND_FILE_UNIX) {
1611                                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1612                                p = store_file_unix_basic(conn, p,
1613                                                        NULL, &sbuf);
1614                                len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1615                        } else {
1616                                DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1617                                p = store_file_unix_basic_info2(conn, p,
1618                                                        NULL, &sbuf);
1619                                nameptr = p;
1620                                p += 4;
1621                                len = srvstr_push(outbuf, p, fname, -1, 0);
1622                                SIVAL(nameptr, 0, len);
1623                        }
1624
1625                        p += len;
1626                        SIVAL(p,0,0); /* Ensure any padding is null. */
1627
1628                        len = PTR_DIFF(p, pdata);
1629                        len = (len + 3) & ~3;
1630                        SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1631                        p = pdata + len;
1632                        /* End of SMB_QUERY_FILE_UNIX_BASIC */
1633
1634                        break;
1635
1636                default:     
1637                        return(False);
1638        }
1639
1640
1641        if (PTR_DIFF(p,pdata) > space_remaining) {
1642                /* Move the dirptr back to prev_dirpos */
1643                dptr_SeekDir(conn->dirptr, prev_dirpos);
1644                *out_of_space = True;
1645                DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1646                return False; /* Not finished - just out of space */
1647        }
1648
1649        /* Setup the last entry pointer, as an offset from base_data */
1650        *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1651        /* Advance the data pointer to the next slot */
1652        *ppdata = p;
1653
1654        return(found);
1655}
1656
1657/****************************************************************************
1658 Reply to a TRANS2_FINDFIRST.
1659****************************************************************************/
1660
1661static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize, 
1662                                char **pparams, int total_params, char **ppdata, int total_data,
1663                                unsigned int max_data_bytes)
1664{
1665        /* We must be careful here that we don't return more than the
1666                allowed number of data bytes. If this means returning fewer than
1667                maxentries then so be it. We assume that the redirector has
1668                enough room for the fixed number of parameter bytes it has
1669                requested. */
1670        char *params = *pparams;
1671        char *pdata = *ppdata;
1672        uint32 dirtype;
1673        int maxentries;
1674        uint16 findfirst_flags;
1675        BOOL close_after_first;
1676        BOOL close_if_end;
1677        BOOL requires_resume_key;
1678        int info_level;
1679        pstring directory;
1680        pstring mask;
1681        char *p;
1682        int last_entry_off=0;
1683        int dptr_num = -1;
1684        int numentries = 0;
1685        int i;
1686        BOOL finished = False;
1687        BOOL dont_descend = False;
1688        BOOL out_of_space = False;
1689        int space_remaining;
1690        BOOL mask_contains_wcard = False;
1691        SMB_STRUCT_STAT sbuf;
1692        TALLOC_CTX *ea_ctx = NULL;
1693        struct ea_list *ea_list = NULL;
1694        NTSTATUS ntstatus = NT_STATUS_OK;
1695
1696        if (total_params < 13) {
1697                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698        }
1699
1700        dirtype = SVAL(params,0);
1701        maxentries = SVAL(params,2);
1702        findfirst_flags = SVAL(params,4);
1703        close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1704        close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1705        requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1706        info_level = SVAL(params,6);
1707
1708        *directory = *mask = 0;
1709
1710        DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1711close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1712                (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1713                info_level, max_data_bytes));
1714
1715        if (!maxentries) {
1716                /* W2K3 seems to treat zero as 1. */
1717                maxentries = 1;
1718        }
1719 
1720        switch (info_level) {
1721                case SMB_FIND_INFO_STANDARD:
1722                case SMB_FIND_EA_SIZE:
1723                case SMB_FIND_EA_LIST:
1724                case SMB_FIND_FILE_DIRECTORY_INFO:
1725                case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1726                case SMB_FIND_FILE_NAMES_INFO:
1727                case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1728                case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1729                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1730                        break;
1731                case SMB_FIND_FILE_UNIX:
1732                case SMB_FIND_FILE_UNIX_INFO2:
1733                        if (!lp_unix_extensions()) {
1734                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1735                        }
1736                        break;
1737                default:
1738                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1739        }
1740
1741        srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1742        if (!NT_STATUS_IS_OK(ntstatus)) {
1743                return ERROR_NT(ntstatus);
1744        }
1745
1746        ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
1747        if (!NT_STATUS_IS_OK(ntstatus)) {
1748                if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1749                        return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1750                }
1751                return ERROR_NT(ntstatus);
1752        }
1753
1754        ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1755        if (!NT_STATUS_IS_OK(ntstatus)) {
1756                return ERROR_NT(ntstatus);
1757        }
1758        ntstatus = check_name(conn, directory);
1759        if (!NT_STATUS_IS_OK(ntstatus)) {
1760                return ERROR_NT(ntstatus);
1761        }
1762
1763        p = strrchr_m(directory,'/');
1764        if(p == NULL) {
1765                /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1766                if((directory[0] == '.') && (directory[1] == '\0')) {
1767                        pstrcpy(mask,"*");
1768                        mask_contains_wcard = True;
1769                } else {
1770                        pstrcpy(mask,directory);
1771                }
1772                pstrcpy(directory,"./");
1773        } else {
1774                pstrcpy(mask,p+1);
1775                *p = 0;
1776        }
1777
1778        DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1779
1780        if (info_level == SMB_FIND_EA_LIST) {
1781                uint32 ea_size;
1782
1783                if (total_data < 4) {
1784                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1785                }
1786
1787                ea_size = IVAL(pdata,0);
1788                if (ea_size != total_data) {
1789                        DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1790total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1791                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1792                }
1793
1794                if (!lp_ea_support(SNUM(conn))) {
1795                        return ERROR_DOS(ERRDOS,ERReasnotsupported);
1796                }
1797                                                                                                                                                       
1798                if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1799                        return ERROR_NT(NT_STATUS_NO_MEMORY);
1800                }
1801
1802                /* Pull out the list of names. */
1803                ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1804                if (!ea_list) {
1805                        talloc_destroy(ea_ctx);
1806                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1807                }
1808        }
1809
1810        *ppdata = (char *)SMB_REALLOC(
1811                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1812        if(*ppdata == NULL ) {
1813                talloc_destroy(ea_ctx);
1814                return ERROR_NT(NT_STATUS_NO_MEMORY);
1815        }
1816        pdata = *ppdata;
1817
1818        /* Realloc the params space */
1819        *pparams = (char *)SMB_REALLOC(*pparams, 10);
1820        if (*pparams == NULL) {
1821                talloc_destroy(ea_ctx);
1822                return ERROR_NT(NT_STATUS_NO_MEMORY);
1823        }
1824        params = *pparams;
1825
1826        /* Save the wildcard match and attribs we are using on this directory -
1827                needed as lanman2 assumes these are being saved between calls */
1828
1829        ntstatus = dptr_create(conn,
1830                                directory,
1831                                False,
1832                                True,
1833                                SVAL(inbuf,smb_pid),
1834                                mask,
1835                                mask_contains_wcard,
1836                                dirtype,
1837                                &conn->dirptr);
1838
1839        if (!NT_STATUS_IS_OK(ntstatus)) {
1840                talloc_destroy(ea_ctx);
1841                return ERROR_NT(ntstatus);
1842        }
1843
1844        dptr_num = dptr_dnum(conn->dirptr);
1845        DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1846
1847        /* We don't need to check for VOL here as this is returned by
1848                a different TRANS2 call. */
1849 
1850        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1851        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1852                dont_descend = True;
1853   
1854        p = pdata;
1855        space_remaining = max_data_bytes;
1856        out_of_space = False;
1857
1858        for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1859                BOOL got_exact_match = False;
1860
1861                /* this is a heuristic to avoid seeking the dirptr except when
1862                        absolutely necessary. It allows for a filename of about 40 chars */
1863                if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1864                        out_of_space = True;
1865                        finished = False;
1866                } else {
1867                        finished = !get_lanman2_dir_entry(conn,
1868                                        inbuf, outbuf,
1869                                        mask,dirtype,info_level,
1870                                        requires_resume_key,dont_descend,
1871                                        &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1872                                        &last_entry_off, ea_list, ea_ctx);
1873                }
1874
1875                if (finished && out_of_space)
1876                        finished = False;
1877
1878                if (!finished && !out_of_space)
1879                        numentries++;
1880
1881                /*
1882                 * As an optimisation if we know we aren't looking
1883                 * for a wildcard name (ie. the name matches the wildcard exactly)
1884                 * then we can finish on any (first) match.
1885                 * This speeds up large directory searches. JRA.
1886                 */
1887
1888                if(got_exact_match)
1889                        finished = True;
1890
1891                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1892        }
1893 
1894        talloc_destroy(ea_ctx);
1895
1896        /* Check if we can close the dirptr */
1897        if(close_after_first || (finished && close_if_end)) {
1898                DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1899                dptr_close(&dptr_num);
1900        }
1901
1902        /*
1903         * If there are no matching entries we must return ERRDOS/ERRbadfile -
1904         * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1905         * the protocol level is less than NT1. Tested with smbclient. JRA.
1906         * This should fix the OS/2 client bug #2335.
1907         */
1908
1909        if(numentries == 0) {
1910                dptr_close(&dptr_num);
1911                if (Protocol < PROTOCOL_NT1) {
1912                        return ERROR_DOS(ERRDOS,ERRnofiles);
1913                } else {
1914                        return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1915                }
1916        }
1917
1918        /* At this point pdata points to numentries directory entries. */
1919
1920        /* Set up the return parameter block */
1921        SSVAL(params,0,dptr_num);
1922        SSVAL(params,2,numentries);
1923        SSVAL(params,4,finished);
1924        SSVAL(params,6,0); /* Never an EA error */
1925        SSVAL(params,8,last_entry_off);
1926
1927        send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1928
1929        if ((! *directory) && dptr_path(dptr_num))
1930                slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1931
1932        DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1933                smb_fn_name(CVAL(inbuf,smb_com)), 
1934                mask, directory, dirtype, numentries ) );
1935
1936        /*
1937         * Force a name mangle here to ensure that the
1938         * mask as an 8.3 name is top of the mangled cache.
1939         * The reasons for this are subtle. Don't remove
1940         * this code unless you know what you are doing
1941         * (see PR#13758). JRA.
1942         */
1943
1944        if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1945                mangle_map(mask, True, True, conn->params);
1946
1947        return(-1);
1948}
1949
1950/****************************************************************************
1951 Reply to a TRANS2_FINDNEXT.
1952****************************************************************************/
1953
1954static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1955                                        char **pparams, int total_params, char **ppdata, int total_data,
1956                                        unsigned int max_data_bytes)
1957{
1958        /* We must be careful here that we don't return more than the
1959                allowed number of data bytes. If this means returning fewer than
1960                maxentries then so be it. We assume that the redirector has
1961                enough room for the fixed number of parameter bytes it has
1962                requested. */
1963        char *params = *pparams;
1964        char *pdata = *ppdata;
1965        int dptr_num;
1966        int maxentries;
1967        uint16 info_level;
1968        uint32 resume_key;
1969        uint16 findnext_flags;
1970        BOOL close_after_request;
1971        BOOL close_if_end;
1972        BOOL requires_resume_key;
1973        BOOL continue_bit;
1974        BOOL mask_contains_wcard = False;
1975        pstring resume_name;
1976        pstring mask;
1977        pstring directory;
1978        char *p;
1979        uint16 dirtype;
1980        int numentries = 0;
1981        int i, last_entry_off=0;
1982        BOOL finished = False;
1983        BOOL dont_descend = False;
1984        BOOL out_of_space = False;
1985        int space_remaining;
1986        TALLOC_CTX *ea_ctx = NULL;
1987        struct ea_list *ea_list = NULL;
1988        NTSTATUS ntstatus = NT_STATUS_OK;
1989
1990        if (total_params < 13) {
1991                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1992        }
1993
1994        dptr_num = SVAL(params,0);
1995        maxentries = SVAL(params,2);
1996        info_level = SVAL(params,4);
1997        resume_key = IVAL(params,6);
1998        findnext_flags = SVAL(params,10);
1999        close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2000        close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2001        requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2002        continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2003
2004        *mask = *directory = *resume_name = 0;
2005
2006        srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2007        if (!NT_STATUS_IS_OK(ntstatus)) {
2008                /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2009                   complain (it thinks we're asking for the directory above the shared
2010                   path or an invalid name). Catch this as the resume name is only compared, never used in
2011                   a file access. JRA. */
2012                if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
2013                        pstrcpy(resume_name, "..");
2014                } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
2015                        pstrcpy(resume_name, ".");
2016                } else {
2017                        return ERROR_NT(ntstatus);
2018                }
2019        }
2020
2021        DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2022close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2023resume_key = %d resume name = %s continue=%d level = %d\n",
2024                dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2025                requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2026
2027        if (!maxentries) {
2028                /* W2K3 seems to treat zero as 1. */
2029                maxentries = 1;
2030        }
2031
2032        switch (info_level) {
2033                case SMB_FIND_INFO_STANDARD:
2034                case SMB_FIND_EA_SIZE:
2035                case SMB_FIND_EA_LIST:
2036                case SMB_FIND_FILE_DIRECTORY_INFO:
2037                case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2038                case SMB_FIND_FILE_NAMES_INFO:
2039                case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2040                case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2041                case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2042                        break;
2043                case SMB_FIND_FILE_UNIX:
2044                case SMB_FIND_FILE_UNIX_INFO2:
2045                        if (!lp_unix_extensions()) {
2046                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2047                        }
2048                        break;
2049                default:
2050                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2051        }
2052
2053        if (info_level == SMB_FIND_EA_LIST) {
2054                uint32 ea_size;
2055
2056                if (total_data < 4) {
2057                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2058                }
2059
2060                ea_size = IVAL(pdata,0);
2061                if (ea_size != total_data) {
2062                        DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2063total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2064                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2065                }
2066                                                                                                                                                     
2067                if (!lp_ea_support(SNUM(conn))) {
2068                        return ERROR_DOS(ERRDOS,ERReasnotsupported);
2069                }
2070                                                                                                                                                     
2071                if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2072                        return ERROR_NT(NT_STATUS_NO_MEMORY);
2073                }
2074
2075                /* Pull out the list of names. */
2076                ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2077                if (!ea_list) {
2078                        talloc_destroy(ea_ctx);
2079                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2080                }
2081        }
2082
2083        *ppdata = (char *)SMB_REALLOC(
2084                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2085        if(*ppdata == NULL) {
2086                talloc_destroy(ea_ctx);
2087                return ERROR_NT(NT_STATUS_NO_MEMORY);
2088        }
2089
2090        pdata = *ppdata;
2091
2092        /* Realloc the params space */
2093        *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2094        if(*pparams == NULL ) {
2095                talloc_destroy(ea_ctx);
2096                return ERROR_NT(NT_STATUS_NO_MEMORY);
2097        }
2098
2099        params = *pparams;
2100
2101        /* Check that the dptr is valid */
2102        if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2103                talloc_destroy(ea_ctx);
2104                return ERROR_DOS(ERRDOS,ERRnofiles);
2105        }
2106
2107        string_set(&conn->dirpath,dptr_path(dptr_num));
2108
2109        /* Get the wildcard mask from the dptr */
2110        if((p = dptr_wcard(dptr_num))== NULL) {
2111                DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2112                talloc_destroy(ea_ctx);
2113                return ERROR_DOS(ERRDOS,ERRnofiles);
2114        }
2115
2116        pstrcpy(mask, p);
2117        pstrcpy(directory,conn->dirpath);
2118
2119        /* Get the attr mask from the dptr */
2120        dirtype = dptr_attr(dptr_num);
2121
2122        DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2123                dptr_num, mask, dirtype, 
2124                (long)conn->dirptr,
2125                dptr_TellDir(conn->dirptr)));
2126
2127        /* We don't need to check for VOL here as this is returned by
2128                a different TRANS2 call. */
2129
2130        DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2131        if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2132                dont_descend = True;
2133   
2134        p = pdata;
2135        space_remaining = max_data_bytes;
2136        out_of_space = False;
2137
2138        /*
2139         * Seek to the correct position. We no longer use the resume key but
2140         * depend on the last file name instead.
2141         */
2142
2143        if(*resume_name && !continue_bit) {
2144                SMB_STRUCT_STAT st;
2145
2146                long current_pos = 0;
2147                /*
2148                 * Remember, mangle_map is called by
2149                 * get_lanman2_dir_entry(), so the resume name
2150                 * could be mangled. Ensure we check the unmangled name.
2151                 */
2152
2153                if (mangle_is_mangled(resume_name, conn->params)) {
2154                        mangle_check_cache(resume_name, sizeof(resume_name)-1,
2155                                           conn->params);
2156                }
2157
2158                /*
2159                 * Fix for NT redirector problem triggered by resume key indexes
2160                 * changing between directory scans. We now return a resume key of 0
2161                 * and instead look for the filename to continue from (also given
2162                 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2163                 * findfirst/findnext (as is usual) then the directory pointer
2164                 * should already be at the correct place.
2165                 */
2166
2167                finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2168        } /* end if resume_name && !continue_bit */
2169
2170        for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2171                BOOL got_exact_match = False;
2172
2173                /* this is a heuristic to avoid seeking the dirptr except when
2174                        absolutely necessary. It allows for a filename of about 40 chars */
2175                if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2176                        out_of_space = True;
2177                        finished = False;
2178                } else {
2179                        finished = !get_lanman2_dir_entry(conn,
2180                                                inbuf, outbuf,
2181                                                mask,dirtype,info_level,
2182                                                requires_resume_key,dont_descend,
2183                                                &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2184                                                &last_entry_off, ea_list, ea_ctx);
2185                }
2186
2187                if (finished && out_of_space)
2188                        finished = False;
2189
2190                if (!finished && !out_of_space)
2191                        numentries++;
2192
2193                /*
2194                 * As an optimisation if we know we aren't looking
2195                 * for a wildcard name (ie. the name matches the wildcard exactly)
2196                 * then we can finish on any (first) match.
2197                 * This speeds up large directory searches. JRA.
2198                 */
2199
2200                if(got_exact_match)
2201                        finished = True;
2202
2203                space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2204        }
2205 
2206        talloc_destroy(ea_ctx);
2207
2208        /* Check if we can close the dirptr */
2209        if(close_after_request || (finished && close_if_end)) {
2210                DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2211                dptr_close(&dptr_num); /* This frees up the saved mask */
2212        }
2213
2214        /* Set up the return parameter block */
2215        SSVAL(params,0,numentries);
2216        SSVAL(params,2,finished);
2217        SSVAL(params,4,0); /* Never an EA error */
2218        SSVAL(params,6,last_entry_off);
2219
2220        send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2221
2222        if ((! *directory) && dptr_path(dptr_num))
2223                slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2224
2225        DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2226                smb_fn_name(CVAL(inbuf,smb_com)), 
2227                mask, directory, dirtype, numentries ) );
2228
2229        return(-1);
2230}
2231
2232/****************************************************************************
2233 Reply to a TRANS2_QFSINFO (query filesystem info).
2234****************************************************************************/
2235
2236static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2237                                        char **pparams, int total_params, char **ppdata, int total_data,
2238                                        unsigned int max_data_bytes)
2239{
2240        char *pdata;
2241        char *params = *pparams;
2242        uint16 info_level;
2243        int data_len, len;
2244        SMB_STRUCT_STAT st;
2245        char *vname = volume_label(SNUM(conn));
2246        int snum = SNUM(conn);
2247        char *fstype = lp_fstype(SNUM(conn));
2248        int quota_flag = 0;
2249
2250        if (total_params < 2) {
2251                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2252        }
2253
2254        info_level = SVAL(params,0);
2255
2256        DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2257
2258        if(SMB_VFS_STAT(conn,".",&st)!=0) {
2259                DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2260                return ERROR_DOS(ERRSRV,ERRinvdevice);
2261        }
2262
2263        *ppdata = (char *)SMB_REALLOC(
2264                *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2265        if (*ppdata == NULL ) {
2266                return ERROR_NT(NT_STATUS_NO_MEMORY);
2267        }
2268
2269        pdata = *ppdata;
2270        memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2271
2272        switch (info_level) {
2273                case SMB_INFO_ALLOCATION:
2274                {
2275                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2276                        data_len = 18;
2277                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2278                                return(UNIXERROR(ERRHRD,ERRgeneral));
2279                        }
2280
2281                        block_size = lp_block_size(snum);
2282                        if (bsize < block_size) {
2283                                SMB_BIG_UINT factor = block_size/bsize;
2284                                bsize = block_size;
2285                                dsize /= factor;
2286                                dfree /= factor;
2287                        }
2288                        if (bsize > block_size) {
2289                                SMB_BIG_UINT factor = bsize/block_size;
2290                                bsize = block_size;
2291                                dsize *= factor;
2292                                dfree *= factor;
2293                        }
2294                        bytes_per_sector = 512;
2295                        sectors_per_unit = bsize/bytes_per_sector;
2296
2297                        DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2298cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2299                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2300
2301                        SIVAL(pdata,l1_idFileSystem,st.st_dev);
2302                        SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2303                        SIVAL(pdata,l1_cUnit,dsize);
2304                        SIVAL(pdata,l1_cUnitAvail,dfree);
2305                        SSVAL(pdata,l1_cbSector,bytes_per_sector);
2306                        break;
2307                }
2308
2309                case SMB_INFO_VOLUME:
2310                        /* Return volume name */
2311                        /*
2312                         * Add volume serial number - hash of a combination of
2313                         * the called hostname and the service name.
2314                         */
2315                        SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2316                        /*
2317                         * Win2k3 and previous mess this up by sending a name length
2318                         * one byte short. I believe only older clients (OS/2 Win9x) use
2319                         * this call so try fixing this by adding a terminating null to
2320                         * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2321                         */
2322                        len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2323                        SCVAL(pdata,l2_vol_cch,len);
2324                        data_len = l2_vol_szVolLabel + len;
2325                        DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2326                                (unsigned)st.st_ctime, len, vname));
2327                        break;
2328
2329                case SMB_QUERY_FS_ATTRIBUTE_INFO:
2330                case SMB_FS_ATTRIBUTE_INFORMATION:
2331
2332
2333#if defined(HAVE_SYS_QUOTAS)
2334                        quota_flag = FILE_VOLUME_QUOTAS;
2335#endif
2336
2337                        SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2338                                (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2339                                quota_flag); /* FS ATTRIBUTES */
2340
2341                        SIVAL(pdata,4,255); /* Max filename component length */
2342                        /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2343                                and will think we can't do long filenames */
2344                        len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2345                        SIVAL(pdata,8,len);
2346                        data_len = 12 + len;
2347                        break;
2348
2349                case SMB_QUERY_FS_LABEL_INFO:
2350                case SMB_FS_LABEL_INFORMATION:
2351                        len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2352                        data_len = 4 + len;
2353                        SIVAL(pdata,0,len);
2354                        break;
2355
2356                case SMB_QUERY_FS_VOLUME_INFO:     
2357                case SMB_FS_VOLUME_INFORMATION:
2358
2359                        /*
2360                         * Add volume serial number - hash of a combination of
2361                         * the called hostname and the service name.
2362                         */
2363                        SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2364                                (str_checksum(get_local_machine_name())<<16));
2365
2366                        len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2367                        SIVAL(pdata,12,len);
2368                        data_len = 18+len;
2369                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2370                                (int)strlen(vname),vname, lp_servicename(snum)));
2371                        break;
2372
2373                case SMB_QUERY_FS_SIZE_INFO:
2374                case SMB_FS_SIZE_INFORMATION:
2375                {
2376                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2377                        data_len = 24;
2378                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2379                                return(UNIXERROR(ERRHRD,ERRgeneral));
2380                        }
2381                        block_size = lp_block_size(snum);
2382                        if (bsize < block_size) {
2383                                SMB_BIG_UINT factor = block_size/bsize;
2384                                bsize = block_size;
2385                                dsize /= factor;
2386                                dfree /= factor;
2387                        }
2388                        if (bsize > block_size) {
2389                                SMB_BIG_UINT factor = bsize/block_size;
2390                                bsize = block_size;
2391                                dsize *= factor;
2392                                dfree *= factor;
2393                        }
2394                        bytes_per_sector = 512;
2395                        sectors_per_unit = bsize/bytes_per_sector;
2396                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2397cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2398                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2399                        SBIG_UINT(pdata,0,dsize);
2400                        SBIG_UINT(pdata,8,dfree);
2401                        SIVAL(pdata,16,sectors_per_unit);
2402                        SIVAL(pdata,20,bytes_per_sector);
2403                        break;
2404                }
2405
2406                case SMB_FS_FULL_SIZE_INFORMATION:
2407                {
2408                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2409                        data_len = 32;
2410                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2411                                return(UNIXERROR(ERRHRD,ERRgeneral));
2412                        }
2413                        block_size = lp_block_size(snum);
2414                        if (bsize < block_size) {
2415                                SMB_BIG_UINT factor = block_size/bsize;
2416                                bsize = block_size;
2417                                dsize /= factor;
2418                                dfree /= factor;
2419                        }
2420                        if (bsize > block_size) {
2421                                SMB_BIG_UINT factor = bsize/block_size;
2422                                bsize = block_size;
2423                                dsize *= factor;
2424                                dfree *= factor;
2425                        }
2426                        bytes_per_sector = 512;
2427                        sectors_per_unit = bsize/bytes_per_sector;
2428                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2429cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2430                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2431                        SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2432                        SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2433                        SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2434                        SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2435                        SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2436                        break;
2437                }
2438
2439                case SMB_QUERY_FS_DEVICE_INFO:
2440                case SMB_FS_DEVICE_INFORMATION:
2441                        data_len = 8;
2442                        SIVAL(pdata,0,0); /* dev type */
2443                        SIVAL(pdata,4,0); /* characteristics */
2444                        break;
2445
2446#ifdef HAVE_SYS_QUOTAS
2447                case SMB_FS_QUOTA_INFORMATION:
2448                /*
2449                 * what we have to send --metze:
2450                 *
2451                 * Unknown1:            24 NULL bytes
2452                 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2453                 * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2454                 * Quota Flags:         2 byte :
2455                 * Unknown3:            6 NULL bytes
2456                 *
2457                 * 48 bytes total
2458                 *
2459                 * details for Quota Flags:
2460                 *
2461                 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2462                 * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2463                 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2464                 * 0x0001 Enable Quotas: enable quota for this fs
2465                 *
2466                 */
2467                {
2468                        /* we need to fake up a fsp here,
2469                         * because its not send in this call
2470                         */
2471                        files_struct fsp;
2472                        SMB_NTQUOTA_STRUCT quotas;
2473                       
2474                        ZERO_STRUCT(fsp);
2475                        ZERO_STRUCT(quotas);
2476                       
2477                        fsp.conn = conn;
2478                        fsp.fnum = -1;
2479                       
2480                        /* access check */
2481                        if (current_user.ut.uid != 0) {
2482                                DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2483                                        lp_servicename(SNUM(conn)),conn->user));
2484                                return ERROR_DOS(ERRDOS,ERRnoaccess);
2485                        }
2486                       
2487                        if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2488                                DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2489                                return ERROR_DOS(ERRSRV,ERRerror);
2490                        }
2491
2492                        data_len = 48;
2493
2494                        DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));         
2495               
2496                        /* Unknown1 24 NULL bytes*/
2497                        SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2498                        SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2499                        SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2500               
2501                        /* Default Soft Quota 8 bytes */
2502                        SBIG_UINT(pdata,24,quotas.softlim);
2503
2504                        /* Default Hard Quota 8 bytes */
2505                        SBIG_UINT(pdata,32,quotas.hardlim);
2506       
2507                        /* Quota flag 2 bytes */
2508                        SSVAL(pdata,40,quotas.qflags);
2509               
2510                        /* Unknown3 6 NULL bytes */
2511                        SSVAL(pdata,42,0);
2512                        SIVAL(pdata,44,0);
2513                       
2514                        break;
2515                }
2516#endif /* HAVE_SYS_QUOTAS */
2517                case SMB_FS_OBJECTID_INFORMATION:
2518                        data_len = 64;
2519                        break;
2520
2521                /*
2522                 * Query the version and capabilities of the CIFS UNIX extensions
2523                 * in use.
2524                 */
2525
2526                case SMB_QUERY_CIFS_UNIX_INFO:
2527                        if (!lp_unix_extensions()) {
2528                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2529                        }
2530                        data_len = 12;
2531                        SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2532                        SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2533                        /* We have POSIX ACLs, pathname and locking capability. */
2534                        SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2535                                        CIFS_UNIX_POSIX_ACLS_CAP|
2536                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
2537                                        CIFS_UNIX_FCNTL_LOCKS_CAP|
2538                                        CIFS_UNIX_EXTATTR_CAP|
2539                                        CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2540                        break;
2541
2542                case SMB_QUERY_POSIX_FS_INFO:
2543                {
2544                        int rc;
2545                        vfs_statvfs_struct svfs;
2546
2547                        if (!lp_unix_extensions()) {
2548                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2549                        }
2550
2551                        rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2552
2553                        if (!rc) {
2554                                data_len = 56;
2555                                SIVAL(pdata,0,svfs.OptimalTransferSize);
2556                                SIVAL(pdata,4,svfs.BlockSize);
2557                                SBIG_UINT(pdata,8,svfs.TotalBlocks);
2558                                SBIG_UINT(pdata,16,svfs.BlocksAvail);
2559                                SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2560                                SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2561                                SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2562                                SBIG_UINT(pdata,48,svfs.FsIdentifier);
2563                                DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2564#ifdef EOPNOTSUPP
2565                        } else if (rc == EOPNOTSUPP) {
2566                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2567#endif /* EOPNOTSUPP */
2568                        } else {
2569                                DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2570                                return ERROR_DOS(ERRSRV,ERRerror);
2571                        }
2572                        break;
2573                }
2574
2575                case SMB_QUERY_POSIX_WHOAMI:
2576                {
2577                        uint32_t flags = 0;
2578                        uint32_t sid_bytes;
2579                        int i;
2580
2581                        if (!lp_unix_extensions()) {
2582                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2583                        }
2584
2585                        if (max_data_bytes < 40) {
2586                                return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2587                        }
2588
2589                        /* We ARE guest if global_sid_Builtin_Guests is
2590                         * in our list of SIDs.
2591                         */
2592                        if (nt_token_check_sid(&global_sid_Builtin_Guests,
2593                                    current_user.nt_user_token)) {
2594                                flags |= SMB_WHOAMI_GUEST;
2595                        }
2596
2597                        /* We are NOT guest if global_sid_Authenticated_Users
2598                         * is in our list of SIDs.
2599                         */
2600                        if (nt_token_check_sid(&global_sid_Authenticated_Users,
2601                                    current_user.nt_user_token)) {
2602                                flags &= ~SMB_WHOAMI_GUEST;
2603                        }
2604
2605                        /* NOTE: 8 bytes for UID/GID, irrespective of native
2606                         * platform size. This matches
2607                         * SMB_QUERY_FILE_UNIX_BASIC and friends.
2608                         */
2609                        data_len = 4 /* flags */
2610                            + 4 /* flag mask */
2611                            + 8 /* uid */
2612                            + 8 /* gid */
2613                            + 4 /* ngroups */
2614                            + 4 /* num_sids */
2615                            + 4 /* SID bytes */
2616                            + 4 /* pad/reserved */
2617                            + (current_user.ut.ngroups * 8)
2618                                /* groups list */
2619                            + (current_user.nt_user_token->num_sids *
2620                                    SID_MAX_SIZE)
2621                                /* SID list */;
2622
2623                        SIVAL(pdata, 0, flags);
2624                        SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2625                        SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2626                        SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2627
2628
2629                        if (data_len >= max_data_bytes) {
2630                                /* Potential overflow, skip the GIDs and SIDs. */
2631
2632                                SIVAL(pdata, 24, 0); /* num_groups */
2633                                SIVAL(pdata, 28, 0); /* num_sids */
2634                                SIVAL(pdata, 32, 0); /* num_sid_bytes */
2635                                SIVAL(pdata, 36, 0); /* reserved */
2636
2637                                data_len = 40;
2638                                break;
2639                        }
2640
2641                        SIVAL(pdata, 24, current_user.ut.ngroups);
2642                        SIVAL(pdata, 28,
2643                                current_user.nt_user_token->num_sids);
2644
2645                        /* We walk the SID list twice, but this call is fairly
2646                         * infrequent, and I don't expect that it's performance
2647                         * sensitive -- jpeach
2648                         */
2649                        for (i = 0, sid_bytes = 0;
2650                            i < current_user.nt_user_token->num_sids; ++i) {
2651                                sid_bytes +=
2652                                    sid_size(&current_user.nt_user_token->user_sids[i]);
2653                        }
2654
2655                        /* SID list byte count */
2656                        SIVAL(pdata, 32, sid_bytes);
2657
2658                        /* 4 bytes pad/reserved - must be zero */
2659                        SIVAL(pdata, 36, 0);
2660                        data_len = 40;
2661
2662                        /* GID list */
2663                        for (i = 0; i < current_user.ut.ngroups; ++i) {
2664                                SBIG_UINT(pdata, data_len,
2665                                        (SMB_BIG_UINT)current_user.ut.groups[i]);
2666                                data_len += 8;
2667                        }
2668
2669                        /* SID list */
2670                        for (i = 0;
2671                            i < current_user.nt_user_token->num_sids; ++i) {
2672                                int sid_len =
2673                                    sid_size(&current_user.nt_user_token->user_sids[i]);
2674
2675                                sid_linearize(pdata + data_len, sid_len,
2676                                    &current_user.nt_user_token->user_sids[i]);
2677                                data_len += sid_len;
2678                        }
2679
2680                        break;
2681                }
2682
2683                case SMB_MAC_QUERY_FS_INFO:
2684                        /*
2685                         * Thursby MAC extension... ONLY on NTFS filesystems
2686                         * once we do streams then we don't need this
2687                         */
2688                        if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2689                                data_len = 88;
2690                                SIVAL(pdata,84,0x100); /* Don't support mac... */
2691                                break;
2692                        }
2693                        /* drop through */
2694                default:
2695                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2696        }
2697
2698
2699        send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2700
2701        DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2702
2703        return -1;
2704}
2705
2706/****************************************************************************
2707 Reply to a TRANS2_SETFSINFO (set filesystem info).
2708****************************************************************************/
2709
2710static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2711                                        char **pparams, int total_params, char **ppdata, int total_data,
2712                                        unsigned int max_data_bytes)
2713{
2714        char *pdata = *ppdata;
2715        char *params = *pparams;
2716        uint16 info_level;
2717        int outsize;
2718
2719        DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2720
2721        /*  */
2722        if (total_params < 4) {
2723                DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2724                        total_params));
2725                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2726        }
2727
2728        info_level = SVAL(params,2);
2729
2730        switch(info_level) {
2731                case SMB_SET_CIFS_UNIX_INFO:
2732                        {
2733                                uint16 client_unix_major;
2734                                uint16 client_unix_minor;
2735                                uint32 client_unix_cap_low;
2736                                uint32 client_unix_cap_high;
2737
2738                                if (!lp_unix_extensions()) {
2739                                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2740                                }
2741
2742                                /* There should be 12 bytes of capabilities set. */
2743                                if (total_data < 8) {
2744                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2745                                }
2746                                client_unix_major = SVAL(pdata,0);
2747                                client_unix_minor = SVAL(pdata,2);
2748                                client_unix_cap_low = IVAL(pdata,4);
2749                                client_unix_cap_high = IVAL(pdata,8);
2750                                /* Just print these values for now. */
2751                                DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2752cap_low = 0x%x, cap_high = 0x%x\n",
2753                                        (unsigned int)client_unix_major,
2754                                        (unsigned int)client_unix_minor,
2755                                        (unsigned int)client_unix_cap_low,
2756                                        (unsigned int)client_unix_cap_high ));
2757
2758                                /* Here is where we must switch to posix pathname processing... */
2759                                if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2760                                        lp_set_posix_pathnames();
2761                                        mangle_change_to_posix();
2762                                }
2763
2764                                if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2765                                    !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2766                                        /* Client that knows how to do posix locks,
2767                                         * but not posix open/mkdir operations. Set a
2768                                         * default type for read/write checks. */
2769
2770                                        lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2771
2772                                }
2773                                break;
2774                        }
2775                case SMB_FS_QUOTA_INFORMATION:
2776                        {
2777                                files_struct *fsp = NULL;
2778                                SMB_NTQUOTA_STRUCT quotas;
2779       
2780                                ZERO_STRUCT(quotas);
2781
2782                                /* access check */
2783                                if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2784                                        DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2785                                                lp_servicename(SNUM(conn)),conn->user));
2786                                        return ERROR_DOS(ERRSRV,ERRaccess);
2787                                }
2788
2789                                /* note: normaly there're 48 bytes,
2790                                 * but we didn't use the last 6 bytes for now
2791                                 * --metze
2792                                 */
2793                                fsp = file_fsp(params,0);
2794                                if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2795                                        DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2796                                        return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2797                                }
2798
2799                                if (total_data < 42) {
2800                                        DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2801                                                total_data));
2802                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2803                                }
2804                       
2805                                /* unknown_1 24 NULL bytes in pdata*/
2806               
2807                                /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2808                                quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2809#ifdef LARGE_SMB_OFF_T
2810                                quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2811#else /* LARGE_SMB_OFF_T */
2812                                if ((IVAL(pdata,28) != 0)&&
2813                                        ((quotas.softlim != 0xFFFFFFFF)||
2814                                        (IVAL(pdata,28)!=0xFFFFFFFF))) {
2815                                        /* more than 32 bits? */
2816                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2817                                }
2818#endif /* LARGE_SMB_OFF_T */
2819               
2820                                /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2821                                quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2822#ifdef LARGE_SMB_OFF_T
2823                                quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2824#else /* LARGE_SMB_OFF_T */
2825                                if ((IVAL(pdata,36) != 0)&&
2826                                        ((quotas.hardlim != 0xFFFFFFFF)||
2827                                        (IVAL(pdata,36)!=0xFFFFFFFF))) {
2828                                        /* more than 32 bits? */
2829                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2830                                }
2831#endif /* LARGE_SMB_OFF_T */
2832               
2833                                /* quota_flags 2 bytes **/
2834                                quotas.qflags = SVAL(pdata,40);
2835               
2836                                /* unknown_2 6 NULL bytes follow*/
2837               
2838                                /* now set the quotas */
2839                                if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2840                                        DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2841                                        return ERROR_DOS(ERRSRV,ERRerror);
2842                                }
2843                       
2844                                break;
2845                        }
2846                default:
2847                        DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2848                                info_level));
2849                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2850                        break;
2851        }
2852
2853        /*
2854         * sending this reply works fine,
2855         * but I'm not sure it's the same
2856         * like windows do...
2857         * --metze
2858         */ 
2859        outsize = set_message(outbuf,10,0,True);
2860
2861        return outsize;
2862}
2863
2864#if defined(HAVE_POSIX_ACLS)
2865/****************************************************************************
2866 Utility function to count the number of entries in a POSIX acl.
2867****************************************************************************/
2868
2869static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2870{
2871        unsigned int ace_count = 0;
2872        int entry_id = SMB_ACL_FIRST_ENTRY;
2873        SMB_ACL_ENTRY_T entry;
2874
2875        while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2876                /* get_next... */
2877                if (entry_id == SMB_ACL_FIRST_ENTRY) {
2878                        entry_id = SMB_ACL_NEXT_ENTRY;
2879                }
2880                ace_count++;
2881        }
2882        return ace_count;
2883}
2884
2885/****************************************************************************
2886 Utility function to marshall a POSIX acl into wire format.
2887****************************************************************************/
2888
2889static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2890{
2891        int entry_id = SMB_ACL_FIRST_ENTRY;
2892        SMB_ACL_ENTRY_T entry;
2893
2894        while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2895                SMB_ACL_TAG_T tagtype;
2896                SMB_ACL_PERMSET_T permset;
2897                unsigned char perms = 0;
2898                unsigned int own_grp;
2899
2900                /* get_next... */
2901                if (entry_id == SMB_ACL_FIRST_ENTRY) {
2902                        entry_id = SMB_ACL_NEXT_ENTRY;
2903                }
2904
2905                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2906                        DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2907                        return False;
2908                }
2909
2910                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2911                        DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2912                        return False;
2913                }
2914
2915                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2916                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2917                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2918
2919                SCVAL(pdata,1,perms);
2920
2921                switch (tagtype) {
2922                        case SMB_ACL_USER_OBJ:
2923                                SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2924                                own_grp = (unsigned int)pst->st_uid;
2925                                SIVAL(pdata,2,own_grp);
2926                                SIVAL(pdata,6,0);
2927                                break;
2928                        case SMB_ACL_USER:
2929                                {
2930                                        uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2931                                        if (!puid) {
2932                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2933                                        }
2934                                        own_grp = (unsigned int)*puid;
2935                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2936                                        SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2937                                        SIVAL(pdata,2,own_grp);
2938                                        SIVAL(pdata,6,0);
2939                                        break;
2940                                }
2941                        case SMB_ACL_GROUP_OBJ:
2942                                SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2943                                own_grp = (unsigned int)pst->st_gid;
2944                                SIVAL(pdata,2,own_grp);
2945                                SIVAL(pdata,6,0);
2946                                break;
2947                        case SMB_ACL_GROUP:
2948                                {
2949                                        gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2950                                        if (!pgid) {
2951                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2952                                        }
2953                                        own_grp = (unsigned int)*pgid;
2954                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2955                                        SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2956                                        SIVAL(pdata,2,own_grp);
2957                                        SIVAL(pdata,6,0);
2958                                        break;
2959                                }
2960                        case SMB_ACL_MASK:
2961                                SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2962                                SIVAL(pdata,2,0xFFFFFFFF);
2963                                SIVAL(pdata,6,0xFFFFFFFF);
2964                                break;
2965                        case SMB_ACL_OTHER:
2966                                SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2967                                SIVAL(pdata,2,0xFFFFFFFF);
2968                                SIVAL(pdata,6,0xFFFFFFFF);
2969                                break;
2970                        default:
2971                                DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2972                                return False;
2973                }
2974                pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2975        }
2976
2977        return True;
2978}
2979#endif
2980
2981/****************************************************************************
2982 Store the FILE_UNIX_BASIC info.
2983****************************************************************************/
2984
2985static char *store_file_unix_basic(connection_struct *conn,
2986                                char *pdata,
2987                                files_struct *fsp,
2988                                const SMB_STRUCT_STAT *psbuf)
2989{
2990        DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2991        DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2992
2993        SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
2994        pdata += 8;
2995
2996        SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2997        pdata += 8;
2998
2999        put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3000        put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3001        put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3002        pdata += 24;
3003
3004        SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3005        SIVAL(pdata,4,0);
3006        pdata += 8;
3007
3008        SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3009        SIVAL(pdata,4,0);
3010        pdata += 8;
3011
3012        SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3013        pdata += 4;
3014
3015        SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3016        SIVAL(pdata,4,0);
3017        pdata += 8;
3018
3019        SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3020        SIVAL(pdata,4,0);
3021        pdata += 8;
3022
3023        SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3024        pdata += 8;
3025                               
3026        SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3027        SIVAL(pdata,4,0);
3028        pdata += 8;
3029
3030        SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3031        SIVAL(pdata,4,0);
3032        pdata += 8;
3033
3034        return pdata;
3035}
3036
3037/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3038 * the chflags(2) (or equivalent) flags.
3039 *
3040 * XXX: this really should be behind the VFS interface. To do this, we would
3041 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3042 * Each VFS module could then implement it's own mapping as appropriate for the
3043 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3044 */
3045static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3046        info2_flags_map[] =
3047{
3048#ifdef UF_NODUMP
3049    { UF_NODUMP, EXT_DO_NOT_BACKUP },
3050#endif
3051
3052#ifdef UF_IMMUTABLE
3053    { UF_IMMUTABLE, EXT_IMMUTABLE },
3054#endif
3055
3056#ifdef UF_APPEND
3057    { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3058#endif
3059
3060#ifdef UF_HIDDEN
3061    { UF_HIDDEN, EXT_HIDDEN },
3062#endif
3063
3064    /* Do not remove. We need to guarantee that this array has at least one
3065     * entry to build on HP-UX.
3066     */
3067    { 0, 0 }
3068
3069};
3070
3071static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3072                                uint32 *smb_fflags, uint32 *smb_fmask)
3073{
3074#ifdef HAVE_STAT_ST_FLAGS
3075        int i;
3076
3077        for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3078            *smb_fmask |= info2_flags_map[i].smb_fflag;
3079            if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3080                    *smb_fflags |= info2_flags_map[i].smb_fflag;
3081            }
3082        }
3083#endif /* HAVE_STAT_ST_FLAGS */
3084}
3085
3086static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3087                                const uint32 smb_fflags,
3088                                const uint32 smb_fmask,
3089                                int *stat_fflags)
3090{
3091#ifdef HAVE_STAT_ST_FLAGS
3092        uint32 max_fmask = 0;
3093        int i;
3094
3095        *stat_fflags = psbuf->st_flags;
3096
3097        /* For each flags requested in smb_fmask, check the state of the
3098         * corresponding flag in smb_fflags and set or clear the matching
3099         * stat flag.
3100         */
3101
3102        for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3103            max_fmask |= info2_flags_map[i].smb_fflag;
3104            if (smb_fmask & info2_flags_map[i].smb_fflag) {
3105                    if (smb_fflags & info2_flags_map[i].smb_fflag) {
3106                            *stat_fflags |= info2_flags_map[i].stat_fflag;
3107                    } else {
3108                            *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3109                    }
3110            }
3111        }
3112
3113        /* If smb_fmask is asking to set any bits that are not supported by
3114         * our flag mappings, we should fail.
3115         */
3116        if ((smb_fmask & max_fmask) != smb_fmask) {
3117                return False;
3118        }
3119
3120        return True;
3121#else
3122        return False;
3123#endif /* HAVE_STAT_ST_FLAGS */
3124}
3125
3126
3127/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3128 * of file flags and birth (create) time.
3129 */
3130static char *store_file_unix_basic_info2(connection_struct *conn,
3131                                char *pdata,
3132                                files_struct *fsp,
3133                                const SMB_STRUCT_STAT *psbuf)
3134{
3135        uint32 file_flags = 0;
3136        uint32 flags_mask = 0;
3137
3138        pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3139
3140        /* Create (birth) time 64 bit */
3141        put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3142        pdata += 8;
3143
3144        map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3145        SIVAL(pdata, 0, file_flags); /* flags */
3146        SIVAL(pdata, 4, flags_mask); /* mask */
3147        pdata += 8;
3148
3149        return pdata;
3150}
3151
3152/****************************************************************************
3153 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3154 file name or file id).
3155****************************************************************************/
3156
3157static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3158                                        unsigned int tran_call,
3159                                        char **pparams, int total_params, char **ppdata, int total_data,
3160                                        unsigned int max_data_bytes)
3161{
3162        char *params = *pparams;
3163        char *pdata = *ppdata;
3164        uint16 info_level;
3165        int mode=0;
3166        int nlink;
3167        SMB_OFF_T file_size=0;
3168        SMB_BIG_UINT allocation_size=0;
3169        unsigned int data_size = 0;
3170        unsigned int param_size = 2;
3171        SMB_STRUCT_STAT sbuf;
3172        pstring fname, dos_fname;
3173        char *fullpathname;
3174        char *base_name;
3175        char *p;
3176        SMB_OFF_T pos = 0;
3177        BOOL delete_pending = False;
3178        int len;
3179        time_t create_time, mtime, atime;
3180        struct timespec create_time_ts, mtime_ts, atime_ts;
3181        files_struct *fsp = NULL;
3182        TALLOC_CTX *data_ctx = NULL;
3183        struct ea_list *ea_list = NULL;
3184        uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3185        char *lock_data = NULL;
3186
3187        if (!params)
3188                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3189
3190        ZERO_STRUCT(sbuf);
3191
3192        if (tran_call == TRANSACT2_QFILEINFO) {
3193                if (total_params < 4) {
3194                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3195                }
3196
3197                fsp = file_fsp(params,0);
3198                info_level = SVAL(params,2);
3199
3200                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3201
3202                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3203                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3204                }
3205
3206                if(fsp && (fsp->fake_file_handle)) {
3207                        /*
3208                         * This is actually for the QUOTA_FAKE_FILE --metze
3209                         */
3210                                               
3211                        pstrcpy(fname, fsp->fsp_name);
3212                        /* We know this name is ok, it's already passed the checks. */
3213                       
3214                } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3215                        /*
3216                         * This is actually a QFILEINFO on a directory
3217                         * handle (returned from an NT SMB). NT5.0 seems
3218                         * to do this call. JRA.
3219                         */
3220                        /* We know this name is ok, it's already passed the checks. */
3221                        pstrcpy(fname, fsp->fsp_name);
3222                 
3223                        if (INFO_LEVEL_IS_UNIX(info_level)) {
3224                                /* Always do lstat for UNIX calls. */
3225                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3226                                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3227                                        return UNIXERROR(ERRDOS,ERRbadpath);
3228                                }
3229                        } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3230                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3231                                return UNIXERROR(ERRDOS,ERRbadpath);
3232                        }
3233
3234                        delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3235                } else {
3236                        /*
3237                         * Original code - this is an open file.
3238                         */
3239                        CHECK_FSP(fsp,conn);
3240
3241                        pstrcpy(fname, fsp->fsp_name);
3242                        if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3243                                DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3244                                return(UNIXERROR(ERRDOS,ERRbadfid));
3245                        }
3246                        pos = fsp->fh->position_information;
3247                        delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3248                        access_mask = fsp->access_mask;
3249                }
3250        } else {
3251                NTSTATUS status = NT_STATUS_OK;
3252
3253                /* qpathinfo */
3254                if (total_params < 7) {
3255                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3256                }
3257
3258                info_level = SVAL(params,0);
3259
3260                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3261
3262                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3263                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3264                }
3265
3266                srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3267                if (!NT_STATUS_IS_OK(status)) {
3268                        return ERROR_NT(status);
3269                }
3270
3271                status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3272                if (!NT_STATUS_IS_OK(status)) {
3273                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3274                                return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3275                        }
3276                        return ERROR_NT(status);
3277                }
3278
3279                status = unix_convert(conn, fname, False, NULL, &sbuf);
3280                if (!NT_STATUS_IS_OK(status)) {
3281                        return ERROR_NT(status);
3282                }
3283                status = check_name(conn, fname);
3284                if (!NT_STATUS_IS_OK(status)) {
3285                        DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3286                        return ERROR_NT(status);
3287                }
3288
3289                if (INFO_LEVEL_IS_UNIX(info_level)) {
3290                        /* Always do lstat for UNIX calls. */
3291                        if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3292                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3293                                return UNIXERROR(ERRDOS,ERRbadpath);
3294                        }
3295                } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3296                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3297                        return UNIXERROR(ERRDOS,ERRbadpath);
3298                }
3299
3300                delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3301                if (delete_pending) {
3302                        return ERROR_NT(NT_STATUS_DELETE_PENDING);
3303                }
3304        }
3305
3306        nlink = sbuf.st_nlink;
3307
3308        if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3309                /* NTFS does not seem to count ".." */
3310                nlink -= 1;
3311        }
3312
3313        if ((nlink > 0) && delete_pending) {
3314                nlink -= 1;
3315        }
3316
3317        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3318                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3319        }
3320
3321        DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3322                fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3323
3324        p = strrchr_m(fname,'/'); 
3325        if (!p)
3326                base_name = fname;
3327        else
3328                base_name = p+1;
3329
3330        mode = dos_mode(conn,fname,&sbuf);
3331        if (!mode)
3332                mode = FILE_ATTRIBUTE_NORMAL;
3333
3334        fullpathname = fname;
3335        if (!(mode & aDIR))
3336                file_size = get_file_size(sbuf);
3337
3338        /* Pull out any data sent here before we realloc. */
3339        switch (info_level) {
3340                case SMB_INFO_QUERY_EAS_FROM_LIST:
3341                {
3342                        /* Pull any EA list from the data portion. */
3343                        uint32 ea_size;
3344
3345                        if (total_data < 4) {
3346                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3347                        }
3348                        ea_size = IVAL(pdata,0);
3349
3350                        if (total_data > 0 && ea_size != total_data) {
3351                                DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3352total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3353                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3354                        }
3355
3356                        if (!lp_ea_support(SNUM(conn))) {
3357                                return ERROR_DOS(ERRDOS,ERReasnotsupported);
3358                        }
3359
3360                        if ((data_ctx = talloc_init("ea_list")) == NULL) {
3361                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3362                        }
3363
3364                        /* Pull out the list of names. */
3365                        ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3366                        if (!ea_list) {
3367                                talloc_destroy(data_ctx);
3368                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3369                        }
3370                        break;
3371                }
3372
3373                case SMB_QUERY_POSIX_LOCK:
3374                {
3375                        if (fsp == NULL || fsp->fh->fd == -1) {
3376                                return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3377                        }
3378
3379                        if (total_data != POSIX_LOCK_DATA_SIZE) {
3380                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3381                        }
3382
3383                        if ((data_ctx = talloc_init("lock_request")) == NULL) {
3384                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3385                        }
3386
3387                        /* Copy the lock range data. */
3388                        lock_data = (char *)talloc_memdup(
3389                                data_ctx, pdata, total_data);
3390                        if (!lock_data) {
3391                                talloc_destroy(data_ctx);
3392                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3393                        }
3394                }
3395                default:
3396                        break;
3397        }
3398
3399        *pparams = (char *)SMB_REALLOC(*pparams,2);
3400        if (*pparams == NULL) {
3401                talloc_destroy(data_ctx);
3402                return ERROR_NT(NT_STATUS_NO_MEMORY);
3403        }
3404        params = *pparams;
3405        SSVAL(params,0,0);
3406        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3407        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3408        if (*ppdata == NULL ) {
3409                talloc_destroy(data_ctx);
3410                return ERROR_NT(NT_STATUS_NO_MEMORY);
3411        }
3412        pdata = *ppdata;
3413
3414        create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3415        mtime_ts = get_mtimespec(&sbuf);
3416        atime_ts = get_atimespec(&sbuf);
3417
3418        allocation_size = get_allocation_size(conn,fsp,&sbuf);
3419
3420        if (fsp) {
3421                if (!null_timespec(fsp->pending_modtime)) {
3422                        /* the pending modtime overrides the current modtime */
3423                        mtime_ts = fsp->pending_modtime;
3424                }
3425        } else {
3426                /* Do we have this path open ? */
3427                files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3428                if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3429                        /* the pending modtime overrides the current modtime */
3430                        mtime_ts = fsp1->pending_modtime;
3431                }
3432                if (fsp1 && fsp1->initial_allocation_size) {
3433                        allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3434                }
3435        }
3436
3437        if (lp_dos_filetime_resolution(SNUM(conn))) {
3438                dos_filetime_timespec(&create_time_ts);
3439                dos_filetime_timespec(&mtime_ts);
3440                dos_filetime_timespec(&atime_ts);
3441        }
3442
3443        create_time = convert_timespec_to_time_t(create_time_ts);
3444        mtime = convert_timespec_to_time_t(mtime_ts);
3445        atime = convert_timespec_to_time_t(atime_ts);
3446
3447        /* NT expects the name to be in an exact form of the *full*
3448           filename. See the trans2 torture test */
3449        if (strequal(base_name,".")) {
3450                pstrcpy(dos_fname, "\\");
3451        } else {
3452                pstr_sprintf(dos_fname, "\\%s", fname);
3453                string_replace(dos_fname, '/', '\\');
3454        }
3455
3456        switch (info_level) {
3457                case SMB_INFO_STANDARD:
3458                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3459                        data_size = 22;
3460                        srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3461                        srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3462                        srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3463                        SIVAL(pdata,l1_cbFile,(uint32)file_size);
3464                        SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3465                        SSVAL(pdata,l1_attrFile,mode);
3466                        break;
3467
3468                case SMB_INFO_QUERY_EA_SIZE:
3469                {
3470                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3471                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3472                        data_size = 26;
3473                        srv_put_dos_date2(pdata,0,create_time);
3474                        srv_put_dos_date2(pdata,4,atime);
3475                        srv_put_dos_date2(pdata,8,mtime); /* write time */
3476                        SIVAL(pdata,12,(uint32)file_size);
3477                        SIVAL(pdata,16,(uint32)allocation_size);
3478                        SSVAL(pdata,20,mode);
3479                        SIVAL(pdata,22,ea_size);
3480                        break;
3481                }
3482
3483                case SMB_INFO_IS_NAME_VALID:
3484                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3485                        if (tran_call == TRANSACT2_QFILEINFO) {
3486                                /* os/2 needs this ? really ?*/     
3487                                return ERROR_DOS(ERRDOS,ERRbadfunc); 
3488                        }
3489                        data_size = 0;
3490                        param_size = 0;
3491                        break;
3492                       
3493                case SMB_INFO_QUERY_EAS_FROM_LIST:
3494                {
3495                        size_t total_ea_len = 0;
3496                        struct ea_list *ea_file_list = NULL;
3497
3498                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3499
3500                        ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3501                        ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3502
3503                        if (!ea_list || (total_ea_len > data_size)) {
3504                                talloc_destroy(data_ctx);
3505                                data_size = 4;
3506                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3507                                break;
3508                        }
3509
3510                        data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3511                        talloc_destroy(data_ctx);
3512                        break;
3513                }
3514
3515                case SMB_INFO_QUERY_ALL_EAS:
3516                {
3517                        /* We have data_size bytes to put EA's into. */
3518                        size_t total_ea_len = 0;
3519
3520                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3521
3522                        data_ctx = talloc_init("ea_ctx");
3523                        if (!data_ctx) {
3524                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3525                        }
3526
3527                        ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3528                        if (!ea_list || (total_ea_len > data_size)) {
3529                                talloc_destroy(data_ctx);
3530                                data_size = 4;
3531                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3532                                break;
3533                        }
3534
3535                        data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3536                        talloc_destroy(data_ctx);
3537                        break;
3538                }
3539
3540                case SMB_FILE_BASIC_INFORMATION:
3541                case SMB_QUERY_FILE_BASIC_INFO:
3542
3543                        if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3544                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3545                                data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3546                        } else {
3547                                DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3548                                data_size = 40;
3549                                SIVAL(pdata,36,0);
3550                        }
3551                        put_long_date_timespec(pdata,create_time_ts);
3552                        put_long_date_timespec(pdata+8,atime_ts);
3553                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3554                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3555                        SIVAL(pdata,32,mode);
3556
3557                        DEBUG(5,("SMB_QFBI - "));
3558                        DEBUG(5,("create: %s ", ctime(&create_time)));
3559                        DEBUG(5,("access: %s ", ctime(&atime)));
3560                        DEBUG(5,("write: %s ", ctime(&mtime)));
3561                        DEBUG(5,("change: %s ", ctime(&mtime)));
3562                        DEBUG(5,("mode: %x\n", mode));
3563                        break;
3564
3565                case SMB_FILE_STANDARD_INFORMATION:
3566                case SMB_QUERY_FILE_STANDARD_INFO:
3567
3568                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3569                        data_size = 24;
3570                        SOFF_T(pdata,0,allocation_size);
3571                        SOFF_T(pdata,8,file_size);
3572                        SIVAL(pdata,16,nlink);
3573                        SCVAL(pdata,20,delete_pending?1:0);
3574                        SCVAL(pdata,21,(mode&aDIR)?1:0);
3575                        SSVAL(pdata,22,0); /* Padding. */
3576                        break;
3577
3578                case SMB_FILE_EA_INFORMATION:
3579                case SMB_QUERY_FILE_EA_INFO:
3580                {
3581                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3582                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3583                        data_size = 4;
3584                        SIVAL(pdata,0,ea_size);
3585                        break;
3586                }
3587
3588                /* Get the 8.3 name - used if NT SMB was negotiated. */
3589                case SMB_QUERY_FILE_ALT_NAME_INFO:
3590                case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3591                {
3592                        pstring short_name;
3593
3594                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3595                        pstrcpy(short_name,base_name);
3596                        /* Mangle if not already 8.3 */
3597                        if(!mangle_is_8_3(short_name, True, conn->params)) {
3598                                mangle_map(short_name,True,True,conn->params);
3599                        }
3600                        len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3601                        data_size = 4 + len;
3602                        SIVAL(pdata,0,len);
3603                        break;
3604                }
3605
3606                case SMB_QUERY_FILE_NAME_INFO:
3607                        /*
3608                          this must be *exactly* right for ACLs on mapped drives to work
3609                         */
3610                        len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3611                        DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3612                        data_size = 4 + len;
3613                        SIVAL(pdata,0,len);
3614                        break;
3615
3616                case SMB_FILE_ALLOCATION_INFORMATION:
3617                case SMB_QUERY_FILE_ALLOCATION_INFO:
3618                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3619                        data_size = 8;
3620                        SOFF_T(pdata,0,allocation_size);
3621                        break;
3622
3623                case SMB_FILE_END_OF_FILE_INFORMATION:
3624                case SMB_QUERY_FILE_END_OF_FILEINFO:
3625                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3626                        data_size = 8;
3627                        SOFF_T(pdata,0,file_size);
3628                        break;
3629
3630                case SMB_QUERY_FILE_ALL_INFO:
3631                case SMB_FILE_ALL_INFORMATION:
3632                {
3633                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3634                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3635                        put_long_date_timespec(pdata,create_time_ts);
3636                        put_long_date_timespec(pdata+8,atime_ts);
3637                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3638                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3639                        SIVAL(pdata,32,mode);
3640                        SIVAL(pdata,36,0); /* padding. */
3641                        pdata += 40;
3642                        SOFF_T(pdata,0,allocation_size);
3643                        SOFF_T(pdata,8,file_size);
3644                        SIVAL(pdata,16,nlink);
3645                        SCVAL(pdata,20,delete_pending);
3646                        SCVAL(pdata,21,(mode&aDIR)?1:0);
3647                        SSVAL(pdata,22,0);
3648                        pdata += 24;
3649                        SIVAL(pdata,0,ea_size);
3650                        pdata += 4; /* EA info */
3651                        len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3652                        SIVAL(pdata,0,len);
3653                        pdata += 4 + len;
3654                        data_size = PTR_DIFF(pdata,(*ppdata));
3655                        break;
3656                }
3657                case SMB_FILE_INTERNAL_INFORMATION:
3658                        /* This should be an index number - looks like
3659                           dev/ino to me :-)
3660
3661                           I think this causes us to fail the IFSKIT
3662                           BasicFileInformationTest. -tpot */
3663
3664                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3665                        SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3666                        SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3667                        data_size = 8;
3668                        break;
3669
3670                case SMB_FILE_ACCESS_INFORMATION:
3671                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3672                        SIVAL(pdata,0,access_mask);
3673                        data_size = 4;
3674                        break;
3675
3676                case SMB_FILE_NAME_INFORMATION:
3677                        /* Pathname with leading '\'. */
3678                        {
3679                                size_t byte_len;
3680                                byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3681                                DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3682                                SIVAL(pdata,0,byte_len);
3683                                data_size = 4 + byte_len;
3684                                break;
3685                        }
3686
3687                case SMB_FILE_DISPOSITION_INFORMATION:
3688                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3689                        data_size = 1;
3690                        SCVAL(pdata,0,delete_pending);
3691                        break;
3692
3693                case SMB_FILE_POSITION_INFORMATION:
3694                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3695                        data_size = 8;
3696                        SOFF_T(pdata,0,pos);
3697                        break;
3698
3699                case SMB_FILE_MODE_INFORMATION:
3700                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3701                        SIVAL(pdata,0,mode);
3702                        data_size = 4;
3703                        break;
3704
3705                case SMB_FILE_ALIGNMENT_INFORMATION:
3706                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3707                        SIVAL(pdata,0,0); /* No alignment needed. */
3708                        data_size = 4;
3709                        break;
3710
3711#if 0
3712                /*
3713                 * NT4 server just returns "invalid query" to this - if we try to answer
3714                 * it then NTws gets a BSOD! (tridge).
3715                 * W2K seems to want this. JRA.
3716                 */
3717                case SMB_QUERY_FILE_STREAM_INFO:
3718#endif
3719                case SMB_FILE_STREAM_INFORMATION:
3720                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3721                        if (mode & aDIR) {
3722                                data_size = 0;
3723                        } else {
3724                                size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3725                                SIVAL(pdata,0,0); /* ??? */
3726                                SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3727                                SOFF_T(pdata,8,file_size);
3728                                SIVAL(pdata,16,allocation_size);
3729                                SIVAL(pdata,20,0); /* ??? */
3730                                data_size = 24 + byte_len;
3731                        }
3732                        break;
3733
3734                case SMB_QUERY_COMPRESSION_INFO:
3735                case SMB_FILE_COMPRESSION_INFORMATION:
3736                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3737                        SOFF_T(pdata,0,file_size);
3738                        SIVAL(pdata,8,0); /* ??? */
3739                        SIVAL(pdata,12,0); /* ??? */
3740                        data_size = 16;
3741                        break;
3742
3743                case SMB_FILE_NETWORK_OPEN_INFORMATION:
3744                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3745                        put_long_date_timespec(pdata,create_time_ts);
3746                        put_long_date_timespec(pdata+8,atime_ts);
3747                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3748                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3749                        SIVAL(pdata,32,allocation_size);
3750                        SOFF_T(pdata,40,file_size);
3751                        SIVAL(pdata,48,mode);
3752                        SIVAL(pdata,52,0); /* ??? */
3753                        data_size = 56;
3754                        break;
3755
3756                case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3757                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3758                        SIVAL(pdata,0,mode);
3759                        SIVAL(pdata,4,0);
3760                        data_size = 8;
3761                        break;
3762
3763                /*
3764                 * CIFS UNIX Extensions.
3765                 */
3766
3767                case SMB_QUERY_FILE_UNIX_BASIC:
3768
3769                        pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3770                        data_size = PTR_DIFF(pdata,(*ppdata));
3771
3772                        {
3773                                int i;
3774                                DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3775
3776                                for (i=0; i<100; i++)
3777                                        DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3778                                DEBUG(4,("\n"));
3779                        }
3780
3781                        break;
3782
3783                case SMB_QUERY_FILE_UNIX_INFO2:
3784
3785                        pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3786                        data_size = PTR_DIFF(pdata,(*ppdata));
3787
3788                        {
3789                                int i;
3790                                DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3791
3792                                for (i=0; i<100; i++)
3793                                        DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3794                                DEBUG(4,("\n"));
3795                        }
3796
3797                        break;
3798
3799                case SMB_QUERY_FILE_UNIX_LINK:
3800                        {
3801                                pstring buffer;
3802
3803                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3804#ifdef S_ISLNK
3805                                if(!S_ISLNK(sbuf.st_mode))
3806                                        return(UNIXERROR(ERRSRV,ERRbadlink));
3807#else
3808                                return(UNIXERROR(ERRDOS,ERRbadlink));
3809#endif
3810                                len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3811                                if (len == -1)
3812                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
3813                                buffer[len] = 0;
3814                                len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3815                                pdata += len;
3816                                data_size = PTR_DIFF(pdata,(*ppdata));
3817
3818                                break;
3819                        }
3820
3821#if defined(HAVE_POSIX_ACLS)
3822                case SMB_QUERY_POSIX_ACL:
3823                        {
3824                                SMB_ACL_T file_acl = NULL;
3825                                SMB_ACL_T def_acl = NULL;
3826                                uint16 num_file_acls = 0;
3827                                uint16 num_def_acls = 0;
3828
3829                                if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3830                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3831                                } else {
3832                                        file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3833                                }
3834
3835                                if (file_acl == NULL && no_acl_syscall_error(errno)) {
3836                                        DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3837                                                fname ));
3838                                        return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3839                                }
3840
3841                                if (S_ISDIR(sbuf.st_mode)) {
3842                                        if (fsp && fsp->is_directory) {
3843                                                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3844                                        } else {
3845                                                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3846                                        }
3847                                        def_acl = free_empty_sys_acl(conn, def_acl);
3848                                }
3849
3850                                num_file_acls = count_acl_entries(conn, file_acl);
3851                                num_def_acls = count_acl_entries(conn, def_acl);
3852
3853                                if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3854                                        DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3855                                                data_size,
3856                                                (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3857                                                        SMB_POSIX_ACL_HEADER_SIZE) ));
3858                                        if (file_acl) {
3859                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3860                                        }
3861                                        if (def_acl) {
3862                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3863                                        }
3864                                        return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3865                                }
3866
3867                                SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3868                                SSVAL(pdata,2,num_file_acls);
3869                                SSVAL(pdata,4,num_def_acls);
3870                                if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3871                                        if (file_acl) {
3872                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3873                                        }
3874                                        if (def_acl) {
3875                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3876                                        }
3877                                        return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3878                                }
3879                                if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3880                                        if (file_acl) {
3881                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3882                                        }
3883                                        if (def_acl) {
3884                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3885                                        }
3886                                        return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3887                                }
3888
3889                                if (file_acl) {
3890                                        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3891                                }
3892                                if (def_acl) {
3893                                        SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3894                                }
3895                                data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3896                                break;
3897                        }
3898#endif
3899
3900
3901                case SMB_QUERY_POSIX_LOCK:
3902                {
3903                        NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3904                        SMB_BIG_UINT count;
3905                        SMB_BIG_UINT offset;
3906                        uint32 lock_pid;
3907                        enum brl_type lock_type;
3908
3909                        if (total_data != POSIX_LOCK_DATA_SIZE) {
3910                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3911                        }
3912
3913                        switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3914                                case POSIX_LOCK_TYPE_READ:
3915                                        lock_type = READ_LOCK;
3916                                        break;
3917                                case POSIX_LOCK_TYPE_WRITE:
3918                                        lock_type = WRITE_LOCK;
3919                                        break;
3920                                case POSIX_LOCK_TYPE_UNLOCK:
3921                                default:
3922                                        /* There's no point in asking for an unlock... */
3923                                        talloc_destroy(data_ctx);
3924                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3925                        }
3926
3927                        lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3928#if defined(HAVE_LONGLONG)
3929                        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3930                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3931                        count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3932                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3933#else /* HAVE_LONGLONG */
3934                        offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3935                        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3936#endif /* HAVE_LONGLONG */
3937
3938                        status = query_lock(fsp,
3939                                        &lock_pid,
3940                                        &count,
3941                                        &offset,
3942                                        &lock_type,
3943                                        POSIX_LOCK);
3944
3945                        if (ERROR_WAS_LOCK_DENIED(status)) {
3946                                /* Here we need to report who has it locked... */
3947                                data_size = POSIX_LOCK_DATA_SIZE;
3948
3949                                SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3950                                SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3951                                SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3952#if defined(HAVE_LONGLONG)
3953                                SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3954                                SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3955                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3956                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3957#else /* HAVE_LONGLONG */
3958                                SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3959                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3960#endif /* HAVE_LONGLONG */
3961
3962                        } else if (NT_STATUS_IS_OK(status)) {
3963                                /* For success we just return a copy of what we sent
3964                                   with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3965                                data_size = POSIX_LOCK_DATA_SIZE;
3966                                memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3967                                SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3968                        } else {
3969                                return ERROR_NT(status);
3970                        }
3971                        break;
3972                }
3973
3974                default:
3975                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3976        }
3977
3978        send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3979
3980        return(-1);
3981}
3982
3983/****************************************************************************
3984 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3985 code.
3986****************************************************************************/
3987
3988NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3989{
3990        SMB_STRUCT_STAT sbuf1, sbuf2;
3991        pstring last_component_oldname;
3992        pstring last_component_newname;
3993        NTSTATUS status = NT_STATUS_OK;
3994
3995        ZERO_STRUCT(sbuf1);
3996        ZERO_STRUCT(sbuf2);
3997
3998        status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3999        if (!NT_STATUS_IS_OK(status)) {
4000                return status;
4001        }
4002
4003        status = check_name(conn, oldname);
4004        if (!NT_STATUS_IS_OK(status)) {
4005                return status;
4006        }
4007
4008        /* source must already exist. */
4009        if (!VALID_STAT(sbuf1)) {
4010                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4011        }
4012
4013        status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4014        if (!NT_STATUS_IS_OK(status)) {
4015                return status;
4016        }
4017
4018        status = check_name(conn, newname);
4019        if (!NT_STATUS_IS_OK(status)) {
4020                return status;
4021        }
4022
4023        /* Disallow if newname already exists. */
4024        if (VALID_STAT(sbuf2)) {
4025                return NT_STATUS_OBJECT_NAME_COLLISION;
4026        }
4027
4028        /* No links from a directory. */
4029        if (S_ISDIR(sbuf1.st_mode)) {
4030                return NT_STATUS_FILE_IS_A_DIRECTORY;
4031        }
4032
4033        /* Ensure this is within the share. */
4034        status = reduce_name(conn, oldname);
4035        if (!NT_STATUS_IS_OK(status)) {
4036                return status;
4037        }
4038
4039        DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4040
4041        if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4042                status = map_nt_error_from_unix(errno);
4043                DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4044                                nt_errstr(status), newname, oldname));
4045        }
4046
4047        return status;
4048}
4049
4050/****************************************************************************
4051 Deal with setting the time from any of the setfilepathinfo functions.
4052****************************************************************************/
4053
4054static NTSTATUS smb_set_file_time(connection_struct *conn,
4055                                files_struct *fsp,
4056                                const char *fname,
4057                                const SMB_STRUCT_STAT *psbuf,
4058                                struct timespec ts[2])
4059{
4060        uint32 action =
4061                FILE_NOTIFY_CHANGE_LAST_ACCESS
4062                |FILE_NOTIFY_CHANGE_LAST_WRITE;
4063
4064       
4065        if (!VALID_STAT(*psbuf)) {
4066                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4067        }
4068
4069        /* get some defaults (no modifications) if any info is zero or -1. */
4070        if (null_timespec(ts[0])) {
4071                ts[0] = get_atimespec(psbuf);
4072                action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4073        }
4074
4075        if (null_timespec(ts[1])) {
4076                ts[1] = get_mtimespec(psbuf);
4077                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4078        }
4079
4080        DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4081        DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4082
4083        /*
4084         * Try and set the times of this file if
4085         * they are different from the current values.
4086         */
4087
4088        {
4089                struct timespec mts = get_mtimespec(psbuf);
4090                struct timespec ats = get_atimespec(psbuf);
4091                if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4092                        return NT_STATUS_OK;
4093                }
4094        }
4095
4096        if(fsp != NULL) {
4097                /*
4098                 * This was a setfileinfo on an open file.
4099                 * NT does this a lot. We also need to
4100                 * set the time here, as it can be read by
4101                 * FindFirst/FindNext and with the patch for bug #2045
4102                 * in smbd/fileio.c it ensures that this timestamp is
4103                 * kept sticky even after a write. We save the request
4104                 * away and will set it on file close and after a write. JRA.
4105                 */
4106
4107                if (!null_timespec(ts[1])) {
4108                        DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4109                                time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4110                        fsp_set_pending_modtime(fsp, ts[1]);
4111                }
4112
4113        }
4114        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4115
4116        if(file_ntimes(conn, fname, ts)!=0) {
4117                return map_nt_error_from_unix(errno);
4118        }
4119        if (action != 0) {
4120                notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4121        }
4122        return NT_STATUS_OK;
4123}
4124
4125/****************************************************************************
4126 Deal with setting the dosmode from any of the setfilepathinfo functions.
4127****************************************************************************/
4128
4129static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4130                                const char *fname,
4131                                SMB_STRUCT_STAT *psbuf,
4132                                uint32 dosmode)
4133{
4134        if (!VALID_STAT(*psbuf)) {
4135                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4136        }
4137
4138        if (dosmode) {
4139                if (S_ISDIR(psbuf->st_mode)) {
4140                        dosmode |= aDIR;
4141                } else {
4142                        dosmode &= ~aDIR;
4143                }
4144        }
4145
4146        DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4147
4148        /* check the mode isn't different, before changing it */
4149        if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4150
4151                DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4152                                        fname, (unsigned int)dosmode ));
4153
4154                if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4155                        DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4156                                                fname, strerror(errno)));
4157                        return map_nt_error_from_unix(errno);
4158                }
4159        }
4160        return NT_STATUS_OK;
4161}
4162
4163/****************************************************************************
4164 Deal with setting the size from any of the setfilepathinfo functions.
4165****************************************************************************/
4166
4167static NTSTATUS smb_set_file_size(connection_struct *conn,
4168                                files_struct *fsp,
4169                                const char *fname,
4170                                SMB_STRUCT_STAT *psbuf,
4171                                SMB_OFF_T size)
4172{
4173        NTSTATUS status = NT_STATUS_OK;
4174        files_struct *new_fsp = NULL;
4175
4176        if (!VALID_STAT(*psbuf)) {
4177                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4178        }
4179
4180        DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4181
4182        if (size == get_file_size(*psbuf)) {
4183                return NT_STATUS_OK;
4184        }
4185
4186        DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4187                fname, (double)size ));
4188
4189        if (fsp && fsp->fh->fd != -1) {
4190                /* Handle based call. */
4191                if (vfs_set_filelen(fsp, size) == -1) {
4192                        return map_nt_error_from_unix(errno);
4193                }
4194                return NT_STATUS_OK;
4195        }
4196
4197        status = open_file_ntcreate(conn, fname, psbuf,
4198                                FILE_WRITE_DATA,
4199                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4200                                FILE_OPEN,
4201                                0,
4202                                FILE_ATTRIBUTE_NORMAL,
4203                                FORCE_OPLOCK_BREAK_TO_NONE,
4204                                NULL, &new_fsp);
4205       
4206        if (!NT_STATUS_IS_OK(status)) {
4207                /* NB. We check for open_was_deferred in the caller. */
4208                return status;
4209        }
4210
4211        if (vfs_set_filelen(new_fsp, size) == -1) {
4212                status = map_nt_error_from_unix(errno);
4213                close_file(new_fsp,NORMAL_CLOSE);
4214                return status;
4215        }
4216
4217        close_file(new_fsp,NORMAL_CLOSE);
4218        return NT_STATUS_OK;
4219}
4220
4221/****************************************************************************
4222 Deal with SMB_INFO_SET_EA.
4223****************************************************************************/
4224
4225static NTSTATUS smb_info_set_ea(connection_struct *conn,
4226                                const char *pdata,
4227                                int total_data,
4228                                files_struct *fsp,
4229                                const char *fname)
4230{
4231        struct ea_list *ea_list = NULL;
4232        TALLOC_CTX *ctx = NULL;
4233        NTSTATUS status = NT_STATUS_OK;
4234
4235        if (total_data < 10) {
4236
4237                /* OS/2 workplace shell seems to send SET_EA requests of "null"
4238                   length. They seem to have no effect. Bug #3212. JRA */
4239
4240                if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4241                        /* We're done. We only get EA info in this call. */
4242                        return NT_STATUS_OK;
4243                }
4244
4245                return NT_STATUS_INVALID_PARAMETER;
4246        }
4247
4248        if (IVAL(pdata,0) > total_data) {
4249                DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4250                        IVAL(pdata,0), (unsigned int)total_data));
4251                return NT_STATUS_INVALID_PARAMETER;
4252        }
4253
4254        ctx = talloc_init("SMB_INFO_SET_EA");
4255        if (!ctx) {
4256                return NT_STATUS_NO_MEMORY;
4257        }
4258        ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4259        if (!ea_list) {
4260                talloc_destroy(ctx);
4261                return NT_STATUS_INVALID_PARAMETER;
4262        }
4263        status = set_ea(conn, fsp, fname, ea_list);
4264        talloc_destroy(ctx);
4265
4266        return status;
4267}
4268
4269/****************************************************************************
4270 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4271****************************************************************************/
4272
4273static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4274                                const char *pdata,
4275                                int total_data,
4276                                files_struct *fsp,
4277                                const char *fname,
4278                                SMB_STRUCT_STAT *psbuf)
4279{
4280        NTSTATUS status = NT_STATUS_OK;
4281        BOOL delete_on_close;
4282        uint32 dosmode = 0;
4283
4284        if (total_data < 1) {
4285                return NT_STATUS_INVALID_PARAMETER;
4286        }
4287
4288        if (fsp == NULL) {
4289                return NT_STATUS_INVALID_HANDLE;
4290        }
4291
4292        delete_on_close = (CVAL(pdata,0) ? True : False);
4293        dosmode = dos_mode(conn, fname, psbuf);
4294
4295        DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4296                "delete_on_close = %u\n",
4297                fsp->fsp_name,
4298                (unsigned int)dosmode,
4299                (unsigned int)delete_on_close ));
4300
4301        status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4302 
4303        if (!NT_STATUS_IS_OK(status)) {
4304                return status;
4305        }
4306
4307        /* The set is across all open files on this dev/inode pair. */
4308        if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4309                return NT_STATUS_ACCESS_DENIED;
4310        }
4311        return NT_STATUS_OK;
4312}
4313
4314/****************************************************************************
4315 Deal with SMB_FILE_POSITION_INFORMATION.
4316****************************************************************************/
4317
4318static NTSTATUS smb_file_position_information(connection_struct *conn,
4319                                const char *pdata,
4320                                int total_data,
4321                                files_struct *fsp)
4322{
4323        SMB_BIG_UINT position_information;
4324
4325        if (total_data < 8) {
4326                return NT_STATUS_INVALID_PARAMETER;
4327        }
4328
4329        if (fsp == NULL) {
4330                /* Ignore on pathname based set. */
4331                return NT_STATUS_OK;
4332        }
4333
4334        position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4335#ifdef LARGE_SMB_OFF_T
4336        position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4337#else /* LARGE_SMB_OFF_T */
4338        if (IVAL(pdata,4) != 0) {
4339                /* more than 32 bits? */
4340                return NT_STATUS_INVALID_PARAMETER;
4341        }
4342#endif /* LARGE_SMB_OFF_T */
4343
4344        DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4345                fsp->fsp_name, (double)position_information ));
4346        fsp->fh->position_information = position_information;
4347        return NT_STATUS_OK;
4348}
4349
4350/****************************************************************************
4351 Deal with SMB_FILE_MODE_INFORMATION.
4352****************************************************************************/
4353
4354static NTSTATUS smb_file_mode_information(connection_struct *conn,
4355                                const char *pdata,
4356                                int total_data)
4357{
4358        uint32 mode;
4359
4360        if (total_data < 4) {
4361                return NT_STATUS_INVALID_PARAMETER;
4362        }
4363        mode = IVAL(pdata,0);
4364        if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4365                return NT_STATUS_INVALID_PARAMETER;
4366        }
4367        return NT_STATUS_OK;
4368}
4369
4370/****************************************************************************
4371 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4372****************************************************************************/
4373
4374static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4375                                char *inbuf,
4376                                const char *pdata,
4377                                int total_data,
4378                                const char *fname)
4379{
4380        pstring link_target;
4381        const char *newname = fname;
4382        NTSTATUS status = NT_STATUS_OK;
4383
4384        /* Set a symbolic link. */
4385        /* Don't allow this if follow links is false. */
4386
4387        if (total_data == 0) {
4388                return NT_STATUS_INVALID_PARAMETER;
4389        }
4390
4391        if (!lp_symlinks(SNUM(conn))) {
4392                return NT_STATUS_ACCESS_DENIED;
4393        }
4394
4395        srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4396
4397        /* !widelinks forces the target path to be within the share. */
4398        /* This means we can interpret the target as a pathname. */
4399        if (!lp_widelinks(SNUM(conn))) {
4400                pstring rel_name;
4401                char *last_dirp = NULL;
4402
4403                if (*link_target == '/') {
4404                        /* No absolute paths allowed. */
4405                        return NT_STATUS_ACCESS_DENIED;
4406                }
4407                pstrcpy(rel_name, newname);
4408                last_dirp = strrchr_m(rel_name, '/');
4409                if (last_dirp) {
4410                        last_dirp[1] = '\0';
4411                } else {
4412                        pstrcpy(rel_name, "./");
4413                }
4414                pstrcat(rel_name, link_target);
4415
4416                status = check_name(conn, rel_name);
4417                if (!NT_STATUS_IS_OK(status)) {
4418                        return status;
4419                }
4420        }
4421
4422        DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4423                        newname, link_target ));
4424
4425        if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4426                return map_nt_error_from_unix(errno);
4427        }
4428
4429        return NT_STATUS_OK;
4430}
4431
4432/****************************************************************************
4433 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4434****************************************************************************/
4435
4436static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4437                                char *inbuf,
4438                                char *outbuf,
4439                                const char *pdata,
4440                                int total_data,
4441                                pstring fname)
4442{
4443        pstring oldname;
4444        NTSTATUS status = NT_STATUS_OK;
4445
4446        /* Set a hard link. */
4447        if (total_data == 0) {
4448                return NT_STATUS_INVALID_PARAMETER;
4449        }
4450
4451        srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4452        if (!NT_STATUS_IS_OK(status)) {
4453                return status;
4454        }
4455
4456        status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4457        if (!NT_STATUS_IS_OK(status)) {
4458                return status;
4459        }
4460
4461        DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4462                fname, oldname));
4463
4464        return hardlink_internals(conn, oldname, fname);
4465}
4466
4467/****************************************************************************
4468 Deal with SMB_FILE_RENAME_INFORMATION.
4469****************************************************************************/
4470
4471static NTSTATUS smb_file_rename_information(connection_struct *conn,
4472                                char *inbuf,
4473                                char *outbuf,
4474                                const char *pdata,
4475                                int total_data,
4476                                files_struct *fsp,
4477                                pstring fname)
4478{
4479        BOOL overwrite;
4480        /* uint32 root_fid; */  /* Not used */
4481        uint32 len;
4482        pstring newname;
4483        pstring base_name;
4484        BOOL dest_has_wcard = False;
4485        NTSTATUS status = NT_STATUS_OK;
4486        char *p;
4487
4488        if (total_data < 13) {
4489                return NT_STATUS_INVALID_PARAMETER;
4490        }
4491
4492        overwrite = (CVAL(pdata,0) ? True : False);
4493        /* root_fid = IVAL(pdata,4); */
4494        len = IVAL(pdata,8);
4495
4496        if (len > (total_data - 12) || (len == 0)) {
4497                return NT_STATUS_INVALID_PARAMETER;
4498        }
4499
4500        srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4501        if (!NT_STATUS_IS_OK(status)) {
4502                return status;
4503        }
4504
4505        status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4506        if (!NT_STATUS_IS_OK(status)) {
4507                return status;
4508        }
4509
4510        /* Check the new name has no '/' characters. */
4511        if (strchr_m(newname, '/')) {
4512                return NT_STATUS_NOT_SUPPORTED;
4513        }
4514
4515        /* Create the base directory. */
4516        pstrcpy(base_name, fname);
4517        p = strrchr_m(base_name, '/');
4518        if (p) {
4519                *p = '\0';
4520        }
4521        /* Append the new name. */
4522        pstrcat(base_name, "/");
4523        pstrcat(base_name, newname);
4524
4525        if (fsp) {
4526                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4527                        fsp->fnum, fsp->fsp_name, base_name ));
4528                status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4529        } else {
4530                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4531                        fname, newname ));
4532                status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4533        }
4534
4535        return status;
4536}
4537
4538/****************************************************************************
4539 Deal with SMB_SET_POSIX_ACL.
4540****************************************************************************/
4541
4542#if defined(HAVE_POSIX_ACLS)
4543static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4544                                const char *pdata,
4545                                int total_data,
4546                                files_struct *fsp,
4547                                const char *fname,
4548                                SMB_STRUCT_STAT *psbuf)
4549{
4550        uint16 posix_acl_version;
4551        uint16 num_file_acls;
4552        uint16 num_def_acls;
4553        BOOL valid_file_acls = True;
4554        BOOL valid_def_acls = True;
4555
4556        if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4557                return NT_STATUS_INVALID_PARAMETER;
4558        }
4559        posix_acl_version = SVAL(pdata,0);
4560        num_file_acls = SVAL(pdata,2);
4561        num_def_acls = SVAL(pdata,4);
4562
4563        if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4564                valid_file_acls = False;
4565                num_file_acls = 0;
4566        }
4567
4568        if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4569                valid_def_acls = False;
4570                num_def_acls = 0;
4571        }
4572
4573        if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4574                return NT_STATUS_INVALID_PARAMETER;
4575        }
4576
4577        if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4578                        (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4579                return NT_STATUS_INVALID_PARAMETER;
4580        }
4581
4582        DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4583                fname ? fname : fsp->fsp_name,
4584                (unsigned int)num_file_acls,
4585                (unsigned int)num_def_acls));
4586
4587        if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4588                        pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4589                return map_nt_error_from_unix(errno);
4590        }
4591
4592        if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4593                        pdata + SMB_POSIX_ACL_HEADER_SIZE +
4594                        (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4595                return map_nt_error_from_unix(errno);
4596        }
4597        return NT_STATUS_OK;
4598}
4599#endif
4600
4601/****************************************************************************
4602 Deal with SMB_SET_POSIX_LOCK.
4603****************************************************************************/
4604
4605static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4606                                char *inbuf,
4607                                int length,
4608                                const char *pdata,
4609                                int total_data,
4610                                files_struct *fsp)
4611{
4612        SMB_BIG_UINT count;
4613        SMB_BIG_UINT offset;
4614        uint32 lock_pid;
4615        BOOL blocking_lock = False;
4616        enum brl_type lock_type;
4617        NTSTATUS status = NT_STATUS_OK;
4618
4619        if (fsp == NULL || fsp->fh->fd == -1) {
4620                return NT_STATUS_INVALID_HANDLE;
4621        }
4622
4623        if (total_data != POSIX_LOCK_DATA_SIZE) {
4624                return NT_STATUS_INVALID_PARAMETER;
4625        }
4626
4627        switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4628                case POSIX_LOCK_TYPE_READ:
4629                        lock_type = READ_LOCK;
4630                        break;
4631                case POSIX_LOCK_TYPE_WRITE:
4632                        /* Return the right POSIX-mappable error code for files opened read-only. */
4633                        if (!fsp->can_write) {
4634                                return NT_STATUS_INVALID_HANDLE;
4635                        }
4636                        lock_type = WRITE_LOCK;
4637                        break;
4638                case POSIX_LOCK_TYPE_UNLOCK:
4639                        lock_type = UNLOCK_LOCK;
4640                        break;
4641                default:
4642                        return NT_STATUS_INVALID_PARAMETER;
4643        }
4644
4645        if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4646                blocking_lock = False;
4647        } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4648                blocking_lock = True;
4649        } else {
4650                return NT_STATUS_INVALID_PARAMETER;
4651        }
4652
4653        if (!lp_blocking_locks(SNUM(conn))) { 
4654                blocking_lock = False;
4655        }
4656
4657        lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4658#if defined(HAVE_LONGLONG)
4659        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4660                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4661        count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4662                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4663#else /* HAVE_LONGLONG */
4664        offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4665        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4666#endif /* HAVE_LONGLONG */
4667
4668        DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4669                        "lock_pid = %u, count = %.0f, offset = %.0f\n",
4670                fsp->fsp_name,
4671                (unsigned int)lock_type,
4672                (unsigned int)lock_pid,
4673                (double)count,
4674                (double)offset ));
4675
4676        if (lock_type == UNLOCK_LOCK) {
4677                status = do_unlock(fsp,
4678                                lock_pid,
4679                                count,
4680                                offset,
4681                                POSIX_LOCK);
4682        } else {
4683                struct byte_range_lock *br_lck = do_lock(fsp,
4684                                                        lock_pid,
4685                                                        count,
4686                                                        offset,
4687                                                        lock_type,
4688                                                        POSIX_LOCK,
4689                                                        blocking_lock,
4690                                                        &status);
4691
4692                if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4693                        /*
4694                         * A blocking lock was requested. Package up
4695                         * this smb into a queued request and push it
4696                         * onto the blocking lock queue.
4697                         */
4698                        if(push_blocking_lock_request(br_lck,
4699                                                inbuf, length,
4700                                                fsp,
4701                                                -1, /* infinite timeout. */
4702                                                0,
4703                                                lock_pid,
4704                                                lock_type,
4705                                                POSIX_LOCK,
4706                                                offset,
4707                                                count)) {
4708                                TALLOC_FREE(br_lck);
4709                                return status;
4710                        }
4711                }
4712                TALLOC_FREE(br_lck);
4713        }
4714
4715        return status;
4716}
4717
4718/****************************************************************************
4719 Deal with SMB_INFO_STANDARD.
4720****************************************************************************/
4721
4722static NTSTATUS smb_set_info_standard(connection_struct *conn,
4723                                        const char *pdata,
4724                                        int total_data,
4725                                        files_struct *fsp,
4726                                        const char *fname,
4727                                        const SMB_STRUCT_STAT *psbuf)
4728{
4729        struct timespec ts[2];
4730
4731        if (total_data < 12) {
4732                return NT_STATUS_INVALID_PARAMETER;
4733        }
4734
4735        /* access time */
4736        ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4737        /* write time */
4738        ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4739
4740        DEBUG(10,("smb_set_info_standard: file %s\n",
4741                fname ? fname : fsp->fsp_name ));
4742
4743        return smb_set_file_time(conn,
4744                                fsp,
4745                                fname,
4746                                psbuf,
4747                                ts);
4748}
4749
4750/****************************************************************************
4751 Deal with SMB_SET_FILE_BASIC_INFO.
4752****************************************************************************/
4753
4754static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4755                                        const char *pdata,
4756                                        int total_data,
4757                                        files_struct *fsp,
4758                                        const char *fname,
4759                                        SMB_STRUCT_STAT *psbuf)
4760{
4761        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4762        struct timespec write_time;
4763        struct timespec changed_time;
4764        uint32 dosmode = 0;
4765        struct timespec ts[2];
4766        NTSTATUS status = NT_STATUS_OK;
4767
4768        if (total_data < 36) {
4769                return NT_STATUS_INVALID_PARAMETER;
4770        }
4771
4772        /* Set the attributes */
4773        dosmode = IVAL(pdata,32);
4774        status = smb_set_file_dosmode(conn,
4775                                        fname,
4776                                        psbuf,
4777                                        dosmode);
4778        if (!NT_STATUS_IS_OK(status)) {
4779                return status;
4780        }
4781
4782        /* Ignore create time at offset pdata. */
4783
4784        /* access time */
4785        ts[0] = interpret_long_date(pdata+8);
4786
4787        write_time = interpret_long_date(pdata+16);
4788        changed_time = interpret_long_date(pdata+24);
4789
4790        /* mtime */
4791        ts[1] = timespec_min(&write_time, &changed_time);
4792
4793        if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4794                ts[1] = write_time;
4795        }
4796
4797        /* Prefer a defined time to an undefined one. */
4798        if (null_timespec(ts[1])) {
4799                ts[1] = null_timespec(write_time) ? changed_time : write_time;
4800        }
4801
4802        DEBUG(10,("smb_set_file_basic_info: file %s\n",
4803                fname ? fname : fsp->fsp_name ));
4804
4805        return smb_set_file_time(conn,
4806                                fsp,
4807                                fname,
4808                                psbuf,
4809                                ts);
4810}
4811
4812/****************************************************************************
4813 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4814****************************************************************************/
4815
4816static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4817                                        const char *pdata,
4818                                        int total_data,
4819                                        files_struct *fsp,
4820                                        const char *fname,
4821                                        SMB_STRUCT_STAT *psbuf)
4822{
4823        SMB_BIG_UINT allocation_size = 0;
4824        NTSTATUS status = NT_STATUS_OK;
4825        files_struct *new_fsp = NULL;
4826
4827        if (!VALID_STAT(*psbuf)) {
4828                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4829        }
4830
4831        if (total_data < 8) {
4832                return NT_STATUS_INVALID_PARAMETER;
4833        }
4834
4835        allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4836#ifdef LARGE_SMB_OFF_T
4837        allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4838#else /* LARGE_SMB_OFF_T */
4839        if (IVAL(pdata,4) != 0) {
4840                /* more than 32 bits? */
4841                return NT_STATUS_INVALID_PARAMETER;
4842        }
4843#endif /* LARGE_SMB_OFF_T */
4844
4845        DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4846                        fname, (double)allocation_size ));
4847
4848        if (allocation_size) {
4849                allocation_size = smb_roundup(conn, allocation_size);
4850        }
4851
4852        if(allocation_size == get_file_size(*psbuf)) {
4853                return NT_STATUS_OK;
4854        }
4855 
4856        DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4857                        fname, (double)allocation_size ));
4858 
4859        if (fsp && fsp->fh->fd != -1) {
4860                /* Open file handle. */
4861                if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4862                        return map_nt_error_from_unix(errno);
4863                }
4864                return NT_STATUS_OK;
4865        }
4866
4867        /* Pathname or stat or directory file. */
4868
4869        status = open_file_ntcreate(conn, fname, psbuf,
4870                                FILE_WRITE_DATA,
4871                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4872                                FILE_OPEN,
4873                                0,
4874                                FILE_ATTRIBUTE_NORMAL,
4875                                FORCE_OPLOCK_BREAK_TO_NONE,
4876                                NULL, &new_fsp);
4877 
4878        if (!NT_STATUS_IS_OK(status)) {
4879                /* NB. We check for open_was_deferred in the caller. */
4880                return status;
4881        }
4882        if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4883                status = map_nt_error_from_unix(errno);
4884                close_file(new_fsp,NORMAL_CLOSE);
4885                return status;
4886        }
4887
4888        close_file(new_fsp,NORMAL_CLOSE);
4889        return NT_STATUS_OK;
4890}
4891
4892/****************************************************************************
4893 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4894****************************************************************************/
4895
4896static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4897                                        const char *pdata,
4898                                        int total_data,
4899                                        files_struct *fsp,
4900                                        const char *fname,
4901                                        SMB_STRUCT_STAT *psbuf)
4902{
4903        SMB_OFF_T size;
4904
4905        if (total_data < 8) {
4906                return NT_STATUS_INVALID_PARAMETER;
4907        }
4908
4909        size = IVAL(pdata,0);
4910#ifdef LARGE_SMB_OFF_T
4911        size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4912#else /* LARGE_SMB_OFF_T */
4913        if (IVAL(pdata,4) != 0) {
4914                /* more than 32 bits? */
4915                return NT_STATUS_INVALID_PARAMETER;
4916        }
4917#endif /* LARGE_SMB_OFF_T */
4918        DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4919                "file %s to %.0f\n", fname, (double)size ));
4920
4921        return smb_set_file_size(conn,
4922                                fsp,
4923                                fname,
4924                                psbuf,
4925                                size);
4926}
4927
4928/****************************************************************************
4929 Allow a UNIX info mknod.
4930****************************************************************************/
4931
4932static NTSTATUS smb_unix_mknod(connection_struct *conn,
4933                                        const char *pdata,
4934                                        int total_data,
4935                                        const char *fname,
4936                                        SMB_STRUCT_STAT *psbuf)
4937{
4938        uint32 file_type = IVAL(pdata,56);
4939#if defined(HAVE_MAKEDEV)
4940        uint32 dev_major = IVAL(pdata,60);
4941        uint32 dev_minor = IVAL(pdata,68);
4942#endif
4943        SMB_DEV_T dev = (SMB_DEV_T)0;
4944        uint32 raw_unixmode = IVAL(pdata,84);
4945        NTSTATUS status;
4946        mode_t unixmode;
4947
4948        if (total_data < 100) {
4949                return NT_STATUS_INVALID_PARAMETER;
4950        }
4951
4952        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4953        if (!NT_STATUS_IS_OK(status)) {
4954                return status;
4955        }
4956
4957#if defined(HAVE_MAKEDEV)
4958        dev = makedev(dev_major, dev_minor);
4959#endif
4960
4961        switch (file_type) {
4962#if defined(S_IFIFO)
4963                case UNIX_TYPE_FIFO:
4964                        unixmode |= S_IFIFO;
4965                        break;
4966#endif
4967#if defined(S_IFSOCK)
4968                case UNIX_TYPE_SOCKET:
4969                        unixmode |= S_IFSOCK;
4970                        break;
4971#endif
4972#if defined(S_IFCHR)
4973                case UNIX_TYPE_CHARDEV:
4974                        unixmode |= S_IFCHR;
4975                        break;
4976#endif
4977#if defined(S_IFBLK)
4978                case UNIX_TYPE_BLKDEV:
4979                        unixmode |= S_IFBLK;
4980                        break;
4981#endif
4982                default:
4983                        return NT_STATUS_INVALID_PARAMETER;
4984        }
4985
4986        DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
49870%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4988
4989        /* Ok - do the mknod. */
4990        if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4991                return map_nt_error_from_unix(errno);
4992        }
4993
4994        /* If any of the other "set" calls fail we
4995         * don't want to end up with a half-constructed mknod.
4996         */
4997
4998        if (lp_inherit_perms(SNUM(conn))) {
4999                inherit_access_acl(
5000                        conn, parent_dirname(fname),
5001                        fname, unixmode);
5002        }
5003
5004        if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5005                status = map_nt_error_from_unix(errno);
5006                SMB_VFS_UNLINK(conn,fname);
5007                return status;
5008        }
5009        return NT_STATUS_OK;
5010}
5011
5012/****************************************************************************
5013 Deal with SMB_SET_FILE_UNIX_BASIC.
5014****************************************************************************/
5015
5016static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5017                                        const char *pdata,
5018                                        int total_data,
5019                                        files_struct *fsp,
5020                                        const char *fname,
5021                                        SMB_STRUCT_STAT *psbuf)
5022{
5023        struct timespec ts[2];
5024        uint32 raw_unixmode;
5025        mode_t unixmode;
5026        SMB_OFF_T size = 0;
5027        uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5028        gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5029        NTSTATUS status = NT_STATUS_OK;
5030        BOOL delete_on_fail = False;
5031        enum perm_type ptype;
5032
5033        if (total_data < 100) {
5034                return NT_STATUS_INVALID_PARAMETER;
5035        }
5036
5037        if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5038           IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5039                size=IVAL(pdata,0); /* first 8 Bytes are size */
5040#ifdef LARGE_SMB_OFF_T
5041                size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5042#else /* LARGE_SMB_OFF_T */
5043                if (IVAL(pdata,4) != 0) {
5044                        /* more than 32 bits? */
5045                        return NT_STATUS_INVALID_PARAMETER;
5046                }
5047#endif /* LARGE_SMB_OFF_T */
5048        }
5049
5050        ts[0] = interpret_long_date(pdata+24); /* access_time */
5051        ts[1] = interpret_long_date(pdata+32); /* modification_time */
5052        set_owner = (uid_t)IVAL(pdata,40);
5053        set_grp = (gid_t)IVAL(pdata,48);
5054        raw_unixmode = IVAL(pdata,84);
5055
5056        if (VALID_STAT(*psbuf)) {
5057                if (S_ISDIR(psbuf->st_mode)) {
5058                        ptype = PERM_EXISTING_DIR;
5059                } else {
5060                        ptype = PERM_EXISTING_FILE;
5061                }
5062        } else {
5063                ptype = PERM_NEW_FILE;
5064        }
5065
5066        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5067        if (!NT_STATUS_IS_OK(status)) {
5068                return status;
5069        }
5070
5071        DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5072size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5073                fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5074
5075        if (!VALID_STAT(*psbuf)) {
5076                /*
5077                 * The only valid use of this is to create character and block
5078                 * devices, and named pipes. This is deprecated (IMHO) and
5079                 * a new info level should be used for mknod. JRA.
5080                 */
5081
5082                status = smb_unix_mknod(conn,
5083                                        pdata,
5084                                        total_data,
5085                                        fname,
5086                                        psbuf);
5087                if (!NT_STATUS_IS_OK(status)) {
5088                        return status;
5089                }
5090
5091                /* Ensure we don't try and change anything else. */
5092                raw_unixmode = SMB_MODE_NO_CHANGE;
5093                size = get_file_size(*psbuf);
5094                ts[0] = get_atimespec(psbuf);
5095                ts[1] = get_mtimespec(psbuf);
5096                /*
5097                 * We continue here as we might want to change the
5098                 * owner uid/gid.
5099                 */
5100                delete_on_fail = True;
5101        }
5102
5103#if 1
5104        /* Horrible backwards compatibility hack as an old server bug
5105         * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5106         * */
5107
5108        if (!size) {
5109                size = get_file_size(*psbuf);
5110        }
5111#endif
5112
5113        /*
5114         * Deal with the UNIX specific mode set.
5115         */
5116
5117        if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5118                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5119                        (unsigned int)unixmode, fname ));
5120                if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5121                        return map_nt_error_from_unix(errno);
5122                }
5123        }
5124
5125        /*
5126         * Deal with the UNIX specific uid set.
5127         */
5128
5129        if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5130                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5131                        (unsigned int)set_owner, fname ));
5132                if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5133                        status = map_nt_error_from_unix(errno);
5134                        if (delete_on_fail) {
5135                                SMB_VFS_UNLINK(conn,fname);
5136                        }
5137                        return status;
5138                }
5139        }
5140
5141        /*
5142         * Deal with the UNIX specific gid set.
5143         */
5144
5145        if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5146                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5147                        (unsigned int)set_owner, fname ));
5148                if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5149                        status = map_nt_error_from_unix(errno);
5150                        if (delete_on_fail) {
5151                                SMB_VFS_UNLINK(conn,fname);
5152                        }
5153                        return status;
5154                }
5155        }
5156
5157        /* Deal with any size changes. */
5158
5159        status = smb_set_file_size(conn,
5160                                fsp,
5161                                fname,
5162                                psbuf,
5163                                size);
5164        if (!NT_STATUS_IS_OK(status)) {
5165                return status;
5166        }
5167
5168        /* Deal with any time changes. */
5169
5170        return smb_set_file_time(conn,
5171                                fsp,
5172                                fname,
5173                                psbuf,
5174                                ts);
5175}
5176
5177/****************************************************************************
5178 Deal with SMB_SET_FILE_UNIX_INFO2.
5179****************************************************************************/
5180
5181static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5182                                        const char *pdata,
5183                                        int total_data,
5184                                        files_struct *fsp,
5185                                        const char *fname,
5186                                        SMB_STRUCT_STAT *psbuf)
5187{
5188        NTSTATUS status;
5189        uint32 smb_fflags;
5190        uint32 smb_fmask;
5191
5192        if (total_data < 116) {
5193                return NT_STATUS_INVALID_PARAMETER;
5194        }
5195
5196        /* Start by setting all the fields that are common between UNIX_BASIC
5197         * and UNIX_INFO2.
5198         */
5199        status = smb_set_file_unix_basic(conn, pdata, total_data,
5200                                fsp, fname, psbuf);
5201        if (!NT_STATUS_IS_OK(status)) {
5202                return status;
5203        }
5204
5205        smb_fflags = IVAL(pdata, 108);
5206        smb_fmask = IVAL(pdata, 112);
5207
5208        /* NB: We should only attempt to alter the file flags if the client
5209         * sends a non-zero mask.
5210         */
5211        if (smb_fmask != 0) {
5212                int stat_fflags = 0;
5213
5214                if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5215                            &stat_fflags)) {
5216                        /* Client asked to alter a flag we don't understand. */
5217                        return NT_STATUS_INVALID_PARAMETER;
5218                }
5219
5220                if (fsp && fsp->fh->fd != -1) {
5221                        /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5222                        return NT_STATUS_NOT_SUPPORTED;
5223                } else {
5224                        if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5225                                return map_nt_error_from_unix(errno);
5226                        }
5227                }
5228        }
5229
5230        /* XXX: need to add support for changing the create_time here. You
5231         * can do this for paths on Darwin with setattrlist(2). The right way
5232         * to hook this up is probably by extending the VFS utimes interface.
5233         */
5234
5235        return NT_STATUS_OK;
5236}
5237
5238/****************************************************************************
5239 Create a directory with POSIX semantics.
5240****************************************************************************/
5241
5242static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5243                                char **ppdata,
5244                                int total_data,
5245                                const char *fname,
5246                                SMB_STRUCT_STAT *psbuf,
5247                                int *pdata_return_size)
5248{
5249        NTSTATUS status = NT_STATUS_OK;
5250        uint32 raw_unixmode = 0;
5251        uint32 mod_unixmode = 0;
5252        mode_t unixmode = (mode_t)0;
5253        files_struct *fsp = NULL;
5254        uint16 info_level_return = 0;
5255        int info;
5256        char *pdata = *ppdata;
5257
5258        if (total_data < 18) {
5259                return NT_STATUS_INVALID_PARAMETER;
5260        }
5261
5262        raw_unixmode = IVAL(pdata,8);
5263        /* Next 4 bytes are not yet defined. */
5264
5265        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5266        if (!NT_STATUS_IS_OK(status)) {
5267                return status;
5268        }
5269
5270        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5271
5272        DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5273                fname, (unsigned int)unixmode ));
5274
5275        status = open_directory(conn,
5276                                fname,
5277                                psbuf,
5278                                FILE_READ_ATTRIBUTES, /* Just a stat open */
5279                                FILE_SHARE_NONE, /* Ignored for stat opens */
5280                                FILE_CREATE,
5281                                0,
5282                                mod_unixmode,
5283                                &info,
5284                                &fsp);
5285
5286        if (NT_STATUS_IS_OK(status)) {
5287                close_file(fsp, NORMAL_CLOSE);
5288        }
5289
5290        info_level_return = SVAL(pdata,16);
5291 
5292        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5293                *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5294        } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5295                *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5296        } else {
5297                *pdata_return_size = 12;
5298        }
5299
5300        /* Realloc the data size */
5301        *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5302        if (*ppdata == NULL) {
5303                *pdata_return_size = 0;
5304                return NT_STATUS_NO_MEMORY;
5305        }
5306
5307        SSVAL(pdata,0,NO_OPLOCK_RETURN);
5308        SSVAL(pdata,2,0); /* No fnum. */
5309        SIVAL(pdata,4,info); /* Was directory created. */
5310
5311        switch (info_level_return) {
5312                case SMB_QUERY_FILE_UNIX_BASIC:
5313                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5314                        SSVAL(pdata,10,0); /* Padding. */
5315                        store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5316                        break;
5317                case SMB_QUERY_FILE_UNIX_INFO2:
5318                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5319                        SSVAL(pdata,10,0); /* Padding. */
5320                        store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5321                        break;
5322                default:
5323                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5324                        SSVAL(pdata,10,0); /* Padding. */
5325                        break;
5326        }
5327
5328        return status;
5329}
5330
5331/****************************************************************************
5332 Open/Create a file with POSIX semantics.
5333****************************************************************************/
5334
5335static NTSTATUS smb_posix_open(connection_struct *conn,
5336                                char **ppdata,
5337                                int total_data,
5338                                const char *fname,
5339                                SMB_STRUCT_STAT *psbuf,
5340                                int *pdata_return_size)
5341{
5342        BOOL extended_oplock_granted = False;
5343        char *pdata = *ppdata;
5344        uint32 flags = 0;
5345        uint32 wire_open_mode = 0;
5346        uint32 raw_unixmode = 0;
5347        uint32 mod_unixmode = 0;
5348        uint32 create_disp = 0;
5349        uint32 access_mask = 0;
5350        uint32 create_options = 0;
5351        NTSTATUS status = NT_STATUS_OK;
5352        mode_t unixmode = (mode_t)0;
5353        files_struct *fsp = NULL;
5354        int oplock_request = 0;
5355        int info = 0;
5356        uint16 info_level_return = 0;
5357
5358        if (total_data < 18) {
5359                return NT_STATUS_INVALID_PARAMETER;
5360        }
5361
5362        flags = IVAL(pdata,0);
5363        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5364        if (oplock_request) {
5365                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5366        }
5367
5368        wire_open_mode = IVAL(pdata,4);
5369
5370        if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5371                return smb_posix_mkdir(conn,
5372                                        ppdata,
5373                                        total_data,
5374                                        fname,
5375                                        psbuf,
5376                                        pdata_return_size);
5377        }
5378
5379        switch (wire_open_mode & SMB_ACCMODE) {
5380                case SMB_O_RDONLY:
5381                        access_mask = FILE_READ_DATA;
5382                        break;
5383                case SMB_O_WRONLY:
5384                        access_mask = FILE_WRITE_DATA;
5385                        break;
5386                case SMB_O_RDWR:
5387                        access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5388                        break;
5389                default:
5390                        DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5391                                (unsigned int)wire_open_mode ));
5392                        return NT_STATUS_INVALID_PARAMETER;
5393        }
5394
5395        wire_open_mode &= ~SMB_ACCMODE;
5396
5397        if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5398                create_disp = FILE_CREATE;
5399        } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5400                create_disp = FILE_OVERWRITE_IF;
5401        } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5402                create_disp = FILE_OPEN_IF;
5403        } else {
5404                DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5405                        (unsigned int)wire_open_mode ));
5406                return NT_STATUS_INVALID_PARAMETER;
5407        }
5408
5409        raw_unixmode = IVAL(pdata,8);
5410        /* Next 4 bytes are not yet defined. */
5411
5412        status = unix_perms_from_wire(conn,
5413                                psbuf,
5414                                raw_unixmode,
5415                                VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5416                                &unixmode);
5417
5418        if (!NT_STATUS_IS_OK(status)) {
5419                return status;
5420        }
5421
5422        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5423
5424        if (wire_open_mode & SMB_O_SYNC) {
5425                create_options |= FILE_WRITE_THROUGH;
5426        }
5427        if (wire_open_mode & SMB_O_APPEND) {
5428                access_mask |= FILE_APPEND_DATA;
5429        }
5430        if (wire_open_mode & SMB_O_DIRECT) {
5431                mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5432        }
5433
5434        DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5435                fname,
5436                (unsigned int)wire_open_mode,
5437                (unsigned int)unixmode ));
5438
5439        status = open_file_ntcreate(conn,
5440                                fname,
5441                                psbuf,
5442                                access_mask,
5443                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5444                                create_disp,
5445                                0,              /* no create options yet. */
5446                                mod_unixmode,
5447                                oplock_request,
5448                                &info,
5449                                &fsp);
5450
5451        if (!NT_STATUS_IS_OK(status)) {
5452                return status;
5453        }
5454
5455        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5456                extended_oplock_granted = True;
5457        }
5458
5459        if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5460                extended_oplock_granted = True;
5461        }
5462
5463        info_level_return = SVAL(pdata,16);
5464 
5465        /* Allocate the correct return size. */
5466
5467        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5468                *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5469        } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5470                *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5471        } else {
5472                *pdata_return_size = 12;
5473        }
5474
5475        /* Realloc the data size */
5476        *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5477        if (*ppdata == NULL) {
5478                close_file(fsp,ERROR_CLOSE);
5479                *pdata_return_size = 0;
5480                return NT_STATUS_NO_MEMORY;
5481        }
5482
5483        if (extended_oplock_granted) {
5484                if (flags & REQUEST_BATCH_OPLOCK) {
5485                        SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5486                } else {
5487                        SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5488                }
5489        } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5490                SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5491        } else {
5492                SSVAL(pdata,0,NO_OPLOCK_RETURN);
5493        }
5494
5495        SSVAL(pdata,2,fsp->fnum);
5496        SIVAL(pdata,4,info); /* Was file created etc. */
5497
5498        switch (info_level_return) {
5499                case SMB_QUERY_FILE_UNIX_BASIC:
5500                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5501                        SSVAL(pdata,10,0); /* padding. */
5502                        store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5503                        break;
5504                case SMB_QUERY_FILE_UNIX_INFO2:
5505                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5506                        SSVAL(pdata,10,0); /* padding. */
5507                        store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5508                        break;
5509                default:
5510                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5511                        SSVAL(pdata,10,0); /* padding. */
5512                        break;
5513        }
5514        return NT_STATUS_OK;
5515}
5516
5517/****************************************************************************
5518 Delete a file with POSIX semantics.
5519****************************************************************************/
5520
5521static NTSTATUS smb_posix_unlink(connection_struct *conn,
5522                                const char *pdata,
5523                                int total_data,
5524                                const char *fname,
5525                                SMB_STRUCT_STAT *psbuf)
5526{
5527        NTSTATUS status = NT_STATUS_OK;
5528        files_struct *fsp = NULL;
5529        uint16 flags = 0;
5530        int info = 0;
5531
5532        if (total_data < 2) {
5533                return NT_STATUS_INVALID_PARAMETER;
5534        }
5535
5536        flags = SVAL(pdata,0);
5537
5538        if (!VALID_STAT(*psbuf)) {
5539                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5540        }
5541
5542        if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5543                        !VALID_STAT_OF_DIR(*psbuf)) {
5544                return NT_STATUS_NOT_A_DIRECTORY;
5545        }
5546
5547        DEBUG(10,("smb_posix_unlink: %s %s\n",
5548                (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5549                fname));
5550
5551        if (VALID_STAT_OF_DIR(*psbuf)) {
5552                status = open_directory(conn,
5553                                        fname,
5554                                        psbuf,
5555                                        DELETE_ACCESS,
5556                                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5557                                        FILE_OPEN,
5558                                        FILE_DELETE_ON_CLOSE,
5559                                        FILE_FLAG_POSIX_SEMANTICS|0777,
5560                                        &info,                         
5561                                        &fsp);
5562        } else {
5563                char del = 1;
5564
5565                status = open_file_ntcreate(conn,
5566                                fname,
5567                                psbuf,
5568                                DELETE_ACCESS,
5569                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5570                                FILE_OPEN,
5571                                0,
5572                                FILE_FLAG_POSIX_SEMANTICS|0777,
5573                                0, /* No oplock, but break existing ones. */
5574                                &info,
5575                                &fsp);
5576                /*
5577                 * For file opens we must set the delete on close
5578                 * after the open.
5579                 */
5580
5581                if (!NT_STATUS_IS_OK(status)) {
5582                        return status;
5583                }
5584
5585                status = smb_set_file_disposition_info(conn,
5586                                                        &del,
5587                                                        1,
5588                                                        fsp,
5589                                                        fname,
5590                                                        psbuf);
5591        }
5592
5593        if (!NT_STATUS_IS_OK(status)) {
5594                return status;
5595        }
5596        return close_file(fsp, NORMAL_CLOSE);
5597}
5598
5599/****************************************************************************
5600 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5601****************************************************************************/
5602
5603static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5604                                        unsigned int tran_call,
5605                                        char **pparams, int total_params, char **ppdata, int total_data,
5606                                        unsigned int max_data_bytes)
5607{
5608        char *params = *pparams;
5609        char *pdata = *ppdata;
5610        uint16 info_level;
5611        SMB_STRUCT_STAT sbuf;
5612        pstring fname;
5613        files_struct *fsp = NULL;
5614        NTSTATUS status = NT_STATUS_OK;
5615        int data_return_size = 0;
5616
5617        if (!params) {
5618                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5619        }
5620
5621        ZERO_STRUCT(sbuf);
5622
5623        if (tran_call == TRANSACT2_SETFILEINFO) {
5624                if (total_params < 4) {
5625                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5626                }
5627
5628                fsp = file_fsp(params,0);
5629                info_level = SVAL(params,2);   
5630
5631                if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5632                        /*
5633                         * This is actually a SETFILEINFO on a directory
5634                         * handle (returned from an NT SMB). NT5.0 seems
5635                         * to do this call. JRA.
5636                         */
5637                        pstrcpy(fname, fsp->fsp_name);
5638                        if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5639                                DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5640                                return UNIXERROR(ERRDOS,ERRbadpath);
5641                        }
5642