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

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

Code updated to Samba 3.0.25rc2 level

File size: 193.2 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        const 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                        /* Max label len is 32 characters. */
2367                        len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2368                        SIVAL(pdata,12,len);
2369                        data_len = 18+len;
2370
2371                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2372                                (int)strlen(vname),vname, lp_servicename(snum)));
2373                        break;
2374
2375                case SMB_QUERY_FS_SIZE_INFO:
2376                case SMB_FS_SIZE_INFORMATION:
2377                {
2378                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2379                        data_len = 24;
2380                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2381                                return(UNIXERROR(ERRHRD,ERRgeneral));
2382                        }
2383                        block_size = lp_block_size(snum);
2384                        if (bsize < block_size) {
2385                                SMB_BIG_UINT factor = block_size/bsize;
2386                                bsize = block_size;
2387                                dsize /= factor;
2388                                dfree /= factor;
2389                        }
2390                        if (bsize > block_size) {
2391                                SMB_BIG_UINT factor = bsize/block_size;
2392                                bsize = block_size;
2393                                dsize *= factor;
2394                                dfree *= factor;
2395                        }
2396                        bytes_per_sector = 512;
2397                        sectors_per_unit = bsize/bytes_per_sector;
2398                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2399cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2400                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2401                        SBIG_UINT(pdata,0,dsize);
2402                        SBIG_UINT(pdata,8,dfree);
2403                        SIVAL(pdata,16,sectors_per_unit);
2404                        SIVAL(pdata,20,bytes_per_sector);
2405                        break;
2406                }
2407
2408                case SMB_FS_FULL_SIZE_INFORMATION:
2409                {
2410                        SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2411                        data_len = 32;
2412                        if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2413                                return(UNIXERROR(ERRHRD,ERRgeneral));
2414                        }
2415                        block_size = lp_block_size(snum);
2416                        if (bsize < block_size) {
2417                                SMB_BIG_UINT factor = block_size/bsize;
2418                                bsize = block_size;
2419                                dsize /= factor;
2420                                dfree /= factor;
2421                        }
2422                        if (bsize > block_size) {
2423                                SMB_BIG_UINT factor = bsize/block_size;
2424                                bsize = block_size;
2425                                dsize *= factor;
2426                                dfree *= factor;
2427                        }
2428                        bytes_per_sector = 512;
2429                        sectors_per_unit = bsize/bytes_per_sector;
2430                        DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2431cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2432                                (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2433                        SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2434                        SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2435                        SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2436                        SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2437                        SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2438                        break;
2439                }
2440
2441                case SMB_QUERY_FS_DEVICE_INFO:
2442                case SMB_FS_DEVICE_INFORMATION:
2443                        data_len = 8;
2444                        SIVAL(pdata,0,0); /* dev type */
2445                        SIVAL(pdata,4,0); /* characteristics */
2446                        break;
2447
2448#ifdef HAVE_SYS_QUOTAS
2449                case SMB_FS_QUOTA_INFORMATION:
2450                /*
2451                 * what we have to send --metze:
2452                 *
2453                 * Unknown1:            24 NULL bytes
2454                 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2455                 * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2456                 * Quota Flags:         2 byte :
2457                 * Unknown3:            6 NULL bytes
2458                 *
2459                 * 48 bytes total
2460                 *
2461                 * details for Quota Flags:
2462                 *
2463                 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2464                 * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2465                 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2466                 * 0x0001 Enable Quotas: enable quota for this fs
2467                 *
2468                 */
2469                {
2470                        /* we need to fake up a fsp here,
2471                         * because its not send in this call
2472                         */
2473                        files_struct fsp;
2474                        SMB_NTQUOTA_STRUCT quotas;
2475                       
2476                        ZERO_STRUCT(fsp);
2477                        ZERO_STRUCT(quotas);
2478                       
2479                        fsp.conn = conn;
2480                        fsp.fnum = -1;
2481                       
2482                        /* access check */
2483                        if (current_user.ut.uid != 0) {
2484                                DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2485                                        lp_servicename(SNUM(conn)),conn->user));
2486                                return ERROR_DOS(ERRDOS,ERRnoaccess);
2487                        }
2488                       
2489                        if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2490                                DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2491                                return ERROR_DOS(ERRSRV,ERRerror);
2492                        }
2493
2494                        data_len = 48;
2495
2496                        DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));         
2497               
2498                        /* Unknown1 24 NULL bytes*/
2499                        SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2500                        SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2501                        SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2502               
2503                        /* Default Soft Quota 8 bytes */
2504                        SBIG_UINT(pdata,24,quotas.softlim);
2505
2506                        /* Default Hard Quota 8 bytes */
2507                        SBIG_UINT(pdata,32,quotas.hardlim);
2508       
2509                        /* Quota flag 2 bytes */
2510                        SSVAL(pdata,40,quotas.qflags);
2511               
2512                        /* Unknown3 6 NULL bytes */
2513                        SSVAL(pdata,42,0);
2514                        SIVAL(pdata,44,0);
2515                       
2516                        break;
2517                }
2518#endif /* HAVE_SYS_QUOTAS */
2519                case SMB_FS_OBJECTID_INFORMATION:
2520                        data_len = 64;
2521                        break;
2522
2523                /*
2524                 * Query the version and capabilities of the CIFS UNIX extensions
2525                 * in use.
2526                 */
2527
2528                case SMB_QUERY_CIFS_UNIX_INFO:
2529                        if (!lp_unix_extensions()) {
2530                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2531                        }
2532                        data_len = 12;
2533                        SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2534                        SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2535                        /* We have POSIX ACLs, pathname and locking capability. */
2536                        SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2537                                        CIFS_UNIX_POSIX_ACLS_CAP|
2538                                        CIFS_UNIX_POSIX_PATHNAMES_CAP|
2539                                        CIFS_UNIX_FCNTL_LOCKS_CAP|
2540                                        CIFS_UNIX_EXTATTR_CAP|
2541                                        CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2542                        break;
2543
2544                case SMB_QUERY_POSIX_FS_INFO:
2545                {
2546                        int rc;
2547                        vfs_statvfs_struct svfs;
2548
2549                        if (!lp_unix_extensions()) {
2550                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2551                        }
2552
2553                        rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2554
2555                        if (!rc) {
2556                                data_len = 56;
2557                                SIVAL(pdata,0,svfs.OptimalTransferSize);
2558                                SIVAL(pdata,4,svfs.BlockSize);
2559                                SBIG_UINT(pdata,8,svfs.TotalBlocks);
2560                                SBIG_UINT(pdata,16,svfs.BlocksAvail);
2561                                SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2562                                SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2563                                SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2564                                SBIG_UINT(pdata,48,svfs.FsIdentifier);
2565                                DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2566#ifdef EOPNOTSUPP
2567                        } else if (rc == EOPNOTSUPP) {
2568                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2569#endif /* EOPNOTSUPP */
2570                        } else {
2571                                DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2572                                return ERROR_DOS(ERRSRV,ERRerror);
2573                        }
2574                        break;
2575                }
2576
2577                case SMB_QUERY_POSIX_WHOAMI:
2578                {
2579                        uint32_t flags = 0;
2580                        uint32_t sid_bytes;
2581                        int i;
2582
2583                        if (!lp_unix_extensions()) {
2584                                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2585                        }
2586
2587                        if (max_data_bytes < 40) {
2588                                return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2589                        }
2590
2591                        /* We ARE guest if global_sid_Builtin_Guests is
2592                         * in our list of SIDs.
2593                         */
2594                        if (nt_token_check_sid(&global_sid_Builtin_Guests,
2595                                    current_user.nt_user_token)) {
2596                                flags |= SMB_WHOAMI_GUEST;
2597                        }
2598
2599                        /* We are NOT guest if global_sid_Authenticated_Users
2600                         * is in our list of SIDs.
2601                         */
2602                        if (nt_token_check_sid(&global_sid_Authenticated_Users,
2603                                    current_user.nt_user_token)) {
2604                                flags &= ~SMB_WHOAMI_GUEST;
2605                        }
2606
2607                        /* NOTE: 8 bytes for UID/GID, irrespective of native
2608                         * platform size. This matches
2609                         * SMB_QUERY_FILE_UNIX_BASIC and friends.
2610                         */
2611                        data_len = 4 /* flags */
2612                            + 4 /* flag mask */
2613                            + 8 /* uid */
2614                            + 8 /* gid */
2615                            + 4 /* ngroups */
2616                            + 4 /* num_sids */
2617                            + 4 /* SID bytes */
2618                            + 4 /* pad/reserved */
2619                            + (current_user.ut.ngroups * 8)
2620                                /* groups list */
2621                            + (current_user.nt_user_token->num_sids *
2622                                    SID_MAX_SIZE)
2623                                /* SID list */;
2624
2625                        SIVAL(pdata, 0, flags);
2626                        SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2627                        SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2628                        SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2629
2630
2631                        if (data_len >= max_data_bytes) {
2632                                /* Potential overflow, skip the GIDs and SIDs. */
2633
2634                                SIVAL(pdata, 24, 0); /* num_groups */
2635                                SIVAL(pdata, 28, 0); /* num_sids */
2636                                SIVAL(pdata, 32, 0); /* num_sid_bytes */
2637                                SIVAL(pdata, 36, 0); /* reserved */
2638
2639                                data_len = 40;
2640                                break;
2641                        }
2642
2643                        SIVAL(pdata, 24, current_user.ut.ngroups);
2644                        SIVAL(pdata, 28,
2645                                current_user.nt_user_token->num_sids);
2646
2647                        /* We walk the SID list twice, but this call is fairly
2648                         * infrequent, and I don't expect that it's performance
2649                         * sensitive -- jpeach
2650                         */
2651                        for (i = 0, sid_bytes = 0;
2652                            i < current_user.nt_user_token->num_sids; ++i) {
2653                                sid_bytes +=
2654                                    sid_size(&current_user.nt_user_token->user_sids[i]);
2655                        }
2656
2657                        /* SID list byte count */
2658                        SIVAL(pdata, 32, sid_bytes);
2659
2660                        /* 4 bytes pad/reserved - must be zero */
2661                        SIVAL(pdata, 36, 0);
2662                        data_len = 40;
2663
2664                        /* GID list */
2665                        for (i = 0; i < current_user.ut.ngroups; ++i) {
2666                                SBIG_UINT(pdata, data_len,
2667                                        (SMB_BIG_UINT)current_user.ut.groups[i]);
2668                                data_len += 8;
2669                        }
2670
2671                        /* SID list */
2672                        for (i = 0;
2673                            i < current_user.nt_user_token->num_sids; ++i) {
2674                                int sid_len =
2675                                    sid_size(&current_user.nt_user_token->user_sids[i]);
2676
2677                                sid_linearize(pdata + data_len, sid_len,
2678                                    &current_user.nt_user_token->user_sids[i]);
2679                                data_len += sid_len;
2680                        }
2681
2682                        break;
2683                }
2684
2685                case SMB_MAC_QUERY_FS_INFO:
2686                        /*
2687                         * Thursby MAC extension... ONLY on NTFS filesystems
2688                         * once we do streams then we don't need this
2689                         */
2690                        if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2691                                data_len = 88;
2692                                SIVAL(pdata,84,0x100); /* Don't support mac... */
2693                                break;
2694                        }
2695                        /* drop through */
2696                default:
2697                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2698        }
2699
2700
2701        send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2702
2703        DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2704
2705        return -1;
2706}
2707
2708/****************************************************************************
2709 Reply to a TRANS2_SETFSINFO (set filesystem info).
2710****************************************************************************/
2711
2712static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2713                                        char **pparams, int total_params, char **ppdata, int total_data,
2714                                        unsigned int max_data_bytes)
2715{
2716        char *pdata = *ppdata;
2717        char *params = *pparams;
2718        uint16 info_level;
2719        int outsize;
2720
2721        DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2722
2723        /*  */
2724        if (total_params < 4) {
2725                DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2726                        total_params));
2727                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2728        }
2729
2730        info_level = SVAL(params,2);
2731
2732        switch(info_level) {
2733                case SMB_SET_CIFS_UNIX_INFO:
2734                        {
2735                                uint16 client_unix_major;
2736                                uint16 client_unix_minor;
2737                                uint32 client_unix_cap_low;
2738                                uint32 client_unix_cap_high;
2739
2740                                if (!lp_unix_extensions()) {
2741                                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2742                                }
2743
2744                                /* There should be 12 bytes of capabilities set. */
2745                                if (total_data < 8) {
2746                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2747                                }
2748                                client_unix_major = SVAL(pdata,0);
2749                                client_unix_minor = SVAL(pdata,2);
2750                                client_unix_cap_low = IVAL(pdata,4);
2751                                client_unix_cap_high = IVAL(pdata,8);
2752                                /* Just print these values for now. */
2753                                DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2754cap_low = 0x%x, cap_high = 0x%x\n",
2755                                        (unsigned int)client_unix_major,
2756                                        (unsigned int)client_unix_minor,
2757                                        (unsigned int)client_unix_cap_low,
2758                                        (unsigned int)client_unix_cap_high ));
2759
2760                                /* Here is where we must switch to posix pathname processing... */
2761                                if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2762                                        lp_set_posix_pathnames();
2763                                        mangle_change_to_posix();
2764                                }
2765
2766                                if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2767                                    !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2768                                        /* Client that knows how to do posix locks,
2769                                         * but not posix open/mkdir operations. Set a
2770                                         * default type for read/write checks. */
2771
2772                                        lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2773
2774                                }
2775                                break;
2776                        }
2777                case SMB_FS_QUOTA_INFORMATION:
2778                        {
2779                                files_struct *fsp = NULL;
2780                                SMB_NTQUOTA_STRUCT quotas;
2781       
2782                                ZERO_STRUCT(quotas);
2783
2784                                /* access check */
2785                                if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2786                                        DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2787                                                lp_servicename(SNUM(conn)),conn->user));
2788                                        return ERROR_DOS(ERRSRV,ERRaccess);
2789                                }
2790
2791                                /* note: normaly there're 48 bytes,
2792                                 * but we didn't use the last 6 bytes for now
2793                                 * --metze
2794                                 */
2795                                fsp = file_fsp(params,0);
2796                                if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2797                                        DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2798                                        return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2799                                }
2800
2801                                if (total_data < 42) {
2802                                        DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2803                                                total_data));
2804                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2805                                }
2806                       
2807                                /* unknown_1 24 NULL bytes in pdata*/
2808               
2809                                /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2810                                quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2811#ifdef LARGE_SMB_OFF_T
2812                                quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2813#else /* LARGE_SMB_OFF_T */
2814                                if ((IVAL(pdata,28) != 0)&&
2815                                        ((quotas.softlim != 0xFFFFFFFF)||
2816                                        (IVAL(pdata,28)!=0xFFFFFFFF))) {
2817                                        /* more than 32 bits? */
2818                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2819                                }
2820#endif /* LARGE_SMB_OFF_T */
2821               
2822                                /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2823                                quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2824#ifdef LARGE_SMB_OFF_T
2825                                quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2826#else /* LARGE_SMB_OFF_T */
2827                                if ((IVAL(pdata,36) != 0)&&
2828                                        ((quotas.hardlim != 0xFFFFFFFF)||
2829                                        (IVAL(pdata,36)!=0xFFFFFFFF))) {
2830                                        /* more than 32 bits? */
2831                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2832                                }
2833#endif /* LARGE_SMB_OFF_T */
2834               
2835                                /* quota_flags 2 bytes **/
2836                                quotas.qflags = SVAL(pdata,40);
2837               
2838                                /* unknown_2 6 NULL bytes follow*/
2839               
2840                                /* now set the quotas */
2841                                if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2842                                        DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2843                                        return ERROR_DOS(ERRSRV,ERRerror);
2844                                }
2845                       
2846                                break;
2847                        }
2848                default:
2849                        DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2850                                info_level));
2851                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2852                        break;
2853        }
2854
2855        /*
2856         * sending this reply works fine,
2857         * but I'm not sure it's the same
2858         * like windows do...
2859         * --metze
2860         */ 
2861        outsize = set_message(outbuf,10,0,True);
2862
2863        return outsize;
2864}
2865
2866#if defined(HAVE_POSIX_ACLS)
2867/****************************************************************************
2868 Utility function to count the number of entries in a POSIX acl.
2869****************************************************************************/
2870
2871static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2872{
2873        unsigned int ace_count = 0;
2874        int entry_id = SMB_ACL_FIRST_ENTRY;
2875        SMB_ACL_ENTRY_T entry;
2876
2877        while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2878                /* get_next... */
2879                if (entry_id == SMB_ACL_FIRST_ENTRY) {
2880                        entry_id = SMB_ACL_NEXT_ENTRY;
2881                }
2882                ace_count++;
2883        }
2884        return ace_count;
2885}
2886
2887/****************************************************************************
2888 Utility function to marshall a POSIX acl into wire format.
2889****************************************************************************/
2890
2891static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2892{
2893        int entry_id = SMB_ACL_FIRST_ENTRY;
2894        SMB_ACL_ENTRY_T entry;
2895
2896        while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2897                SMB_ACL_TAG_T tagtype;
2898                SMB_ACL_PERMSET_T permset;
2899                unsigned char perms = 0;
2900                unsigned int own_grp;
2901
2902                /* get_next... */
2903                if (entry_id == SMB_ACL_FIRST_ENTRY) {
2904                        entry_id = SMB_ACL_NEXT_ENTRY;
2905                }
2906
2907                if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2908                        DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2909                        return False;
2910                }
2911
2912                if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2913                        DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2914                        return False;
2915                }
2916
2917                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2918                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2919                perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2920
2921                SCVAL(pdata,1,perms);
2922
2923                switch (tagtype) {
2924                        case SMB_ACL_USER_OBJ:
2925                                SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2926                                own_grp = (unsigned int)pst->st_uid;
2927                                SIVAL(pdata,2,own_grp);
2928                                SIVAL(pdata,6,0);
2929                                break;
2930                        case SMB_ACL_USER:
2931                                {
2932                                        uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2933                                        if (!puid) {
2934                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2935                                        }
2936                                        own_grp = (unsigned int)*puid;
2937                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2938                                        SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2939                                        SIVAL(pdata,2,own_grp);
2940                                        SIVAL(pdata,6,0);
2941                                        break;
2942                                }
2943                        case SMB_ACL_GROUP_OBJ:
2944                                SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2945                                own_grp = (unsigned int)pst->st_gid;
2946                                SIVAL(pdata,2,own_grp);
2947                                SIVAL(pdata,6,0);
2948                                break;
2949                        case SMB_ACL_GROUP:
2950                                {
2951                                        gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2952                                        if (!pgid) {
2953                                                DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2954                                        }
2955                                        own_grp = (unsigned int)*pgid;
2956                                        SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2957                                        SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2958                                        SIVAL(pdata,2,own_grp);
2959                                        SIVAL(pdata,6,0);
2960                                        break;
2961                                }
2962                        case SMB_ACL_MASK:
2963                                SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2964                                SIVAL(pdata,2,0xFFFFFFFF);
2965                                SIVAL(pdata,6,0xFFFFFFFF);
2966                                break;
2967                        case SMB_ACL_OTHER:
2968                                SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2969                                SIVAL(pdata,2,0xFFFFFFFF);
2970                                SIVAL(pdata,6,0xFFFFFFFF);
2971                                break;
2972                        default:
2973                                DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2974                                return False;
2975                }
2976                pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2977        }
2978
2979        return True;
2980}
2981#endif
2982
2983/****************************************************************************
2984 Store the FILE_UNIX_BASIC info.
2985****************************************************************************/
2986
2987static char *store_file_unix_basic(connection_struct *conn,
2988                                char *pdata,
2989                                files_struct *fsp,
2990                                const SMB_STRUCT_STAT *psbuf)
2991{
2992        DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2993        DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2994
2995        SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
2996        pdata += 8;
2997
2998        SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2999        pdata += 8;
3000
3001        put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3002        put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3003        put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3004        pdata += 24;
3005
3006        SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3007        SIVAL(pdata,4,0);
3008        pdata += 8;
3009
3010        SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3011        SIVAL(pdata,4,0);
3012        pdata += 8;
3013
3014        SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3015        pdata += 4;
3016
3017        SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3018        SIVAL(pdata,4,0);
3019        pdata += 8;
3020
3021        SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3022        SIVAL(pdata,4,0);
3023        pdata += 8;
3024
3025        SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3026        pdata += 8;
3027                               
3028        SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3029        SIVAL(pdata,4,0);
3030        pdata += 8;
3031
3032        SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3033        SIVAL(pdata,4,0);
3034        pdata += 8;
3035
3036        return pdata;
3037}
3038
3039/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3040 * the chflags(2) (or equivalent) flags.
3041 *
3042 * XXX: this really should be behind the VFS interface. To do this, we would
3043 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3044 * Each VFS module could then implement it's own mapping as appropriate for the
3045 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3046 */
3047static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3048        info2_flags_map[] =
3049{
3050#ifdef UF_NODUMP
3051    { UF_NODUMP, EXT_DO_NOT_BACKUP },
3052#endif
3053
3054#ifdef UF_IMMUTABLE
3055    { UF_IMMUTABLE, EXT_IMMUTABLE },
3056#endif
3057
3058#ifdef UF_APPEND
3059    { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3060#endif
3061
3062#ifdef UF_HIDDEN
3063    { UF_HIDDEN, EXT_HIDDEN },
3064#endif
3065
3066    /* Do not remove. We need to guarantee that this array has at least one
3067     * entry to build on HP-UX.
3068     */
3069    { 0, 0 }
3070
3071};
3072
3073static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3074                                uint32 *smb_fflags, uint32 *smb_fmask)
3075{
3076#ifdef HAVE_STAT_ST_FLAGS
3077        int i;
3078
3079        for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3080            *smb_fmask |= info2_flags_map[i].smb_fflag;
3081            if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3082                    *smb_fflags |= info2_flags_map[i].smb_fflag;
3083            }
3084        }
3085#endif /* HAVE_STAT_ST_FLAGS */
3086}
3087
3088static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3089                                const uint32 smb_fflags,
3090                                const uint32 smb_fmask,
3091                                int *stat_fflags)
3092{
3093#ifdef HAVE_STAT_ST_FLAGS
3094        uint32 max_fmask = 0;
3095        int i;
3096
3097        *stat_fflags = psbuf->st_flags;
3098
3099        /* For each flags requested in smb_fmask, check the state of the
3100         * corresponding flag in smb_fflags and set or clear the matching
3101         * stat flag.
3102         */
3103
3104        for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3105            max_fmask |= info2_flags_map[i].smb_fflag;
3106            if (smb_fmask & info2_flags_map[i].smb_fflag) {
3107                    if (smb_fflags & info2_flags_map[i].smb_fflag) {
3108                            *stat_fflags |= info2_flags_map[i].stat_fflag;
3109                    } else {
3110                            *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3111                    }
3112            }
3113        }
3114
3115        /* If smb_fmask is asking to set any bits that are not supported by
3116         * our flag mappings, we should fail.
3117         */
3118        if ((smb_fmask & max_fmask) != smb_fmask) {
3119                return False;
3120        }
3121
3122        return True;
3123#else
3124        return False;
3125#endif /* HAVE_STAT_ST_FLAGS */
3126}
3127
3128
3129/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3130 * of file flags and birth (create) time.
3131 */
3132static char *store_file_unix_basic_info2(connection_struct *conn,
3133                                char *pdata,
3134                                files_struct *fsp,
3135                                const SMB_STRUCT_STAT *psbuf)
3136{
3137        uint32 file_flags = 0;
3138        uint32 flags_mask = 0;
3139
3140        pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3141
3142        /* Create (birth) time 64 bit */
3143        put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3144        pdata += 8;
3145
3146        map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3147        SIVAL(pdata, 0, file_flags); /* flags */
3148        SIVAL(pdata, 4, flags_mask); /* mask */
3149        pdata += 8;
3150
3151        return pdata;
3152}
3153
3154/****************************************************************************
3155 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3156 file name or file id).
3157****************************************************************************/
3158
3159static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3160                                        unsigned int tran_call,
3161                                        char **pparams, int total_params, char **ppdata, int total_data,
3162                                        unsigned int max_data_bytes)
3163{
3164        char *params = *pparams;
3165        char *pdata = *ppdata;
3166        uint16 info_level;
3167        int mode=0;
3168        int nlink;
3169        SMB_OFF_T file_size=0;
3170        SMB_BIG_UINT allocation_size=0;
3171        unsigned int data_size = 0;
3172        unsigned int param_size = 2;
3173        SMB_STRUCT_STAT sbuf;
3174        pstring fname, dos_fname;
3175        char *fullpathname;
3176        char *base_name;
3177        char *p;
3178        SMB_OFF_T pos = 0;
3179        BOOL delete_pending = False;
3180        int len;
3181        time_t create_time, mtime, atime;
3182        struct timespec create_time_ts, mtime_ts, atime_ts;
3183        files_struct *fsp = NULL;
3184        TALLOC_CTX *data_ctx = NULL;
3185        struct ea_list *ea_list = NULL;
3186        uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3187        char *lock_data = NULL;
3188
3189        if (!params)
3190                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3191
3192        ZERO_STRUCT(sbuf);
3193
3194        if (tran_call == TRANSACT2_QFILEINFO) {
3195                if (total_params < 4) {
3196                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3197                }
3198
3199                fsp = file_fsp(params,0);
3200                info_level = SVAL(params,2);
3201
3202                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3203
3204                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3205                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3206                }
3207
3208                if(fsp && (fsp->fake_file_handle)) {
3209                        /*
3210                         * This is actually for the QUOTA_FAKE_FILE --metze
3211                         */
3212                                               
3213                        pstrcpy(fname, fsp->fsp_name);
3214                        /* We know this name is ok, it's already passed the checks. */
3215                       
3216                } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3217                        /*
3218                         * This is actually a QFILEINFO on a directory
3219                         * handle (returned from an NT SMB). NT5.0 seems
3220                         * to do this call. JRA.
3221                         */
3222                        /* We know this name is ok, it's already passed the checks. */
3223                        pstrcpy(fname, fsp->fsp_name);
3224                 
3225                        if (INFO_LEVEL_IS_UNIX(info_level)) {
3226                                /* Always do lstat for UNIX calls. */
3227                                if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3228                                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3229                                        return UNIXERROR(ERRDOS,ERRbadpath);
3230                                }
3231                        } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3232                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3233                                return UNIXERROR(ERRDOS,ERRbadpath);
3234                        }
3235
3236                        delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3237                } else {
3238                        /*
3239                         * Original code - this is an open file.
3240                         */
3241                        CHECK_FSP(fsp,conn);
3242
3243                        pstrcpy(fname, fsp->fsp_name);
3244                        if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3245                                DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3246                                return(UNIXERROR(ERRDOS,ERRbadfid));
3247                        }
3248                        pos = fsp->fh->position_information;
3249                        delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3250                        access_mask = fsp->access_mask;
3251                }
3252        } else {
3253                NTSTATUS status = NT_STATUS_OK;
3254
3255                /* qpathinfo */
3256                if (total_params < 7) {
3257                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3258                }
3259
3260                info_level = SVAL(params,0);
3261
3262                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3263
3264                if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3265                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3266                }
3267
3268                srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3269                if (!NT_STATUS_IS_OK(status)) {
3270                        return ERROR_NT(status);
3271                }
3272
3273                status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3274                if (!NT_STATUS_IS_OK(status)) {
3275                        if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3276                                return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3277                        }
3278                        return ERROR_NT(status);
3279                }
3280
3281                status = unix_convert(conn, fname, False, NULL, &sbuf);
3282                if (!NT_STATUS_IS_OK(status)) {
3283                        return ERROR_NT(status);
3284                }
3285                status = check_name(conn, fname);
3286                if (!NT_STATUS_IS_OK(status)) {
3287                        DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3288                        return ERROR_NT(status);
3289                }
3290
3291                if (INFO_LEVEL_IS_UNIX(info_level)) {
3292                        /* Always do lstat for UNIX calls. */
3293                        if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3294                                DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3295                                return UNIXERROR(ERRDOS,ERRbadpath);
3296                        }
3297                } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3298                        DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3299                        return UNIXERROR(ERRDOS,ERRbadpath);
3300                }
3301
3302                delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3303                if (delete_pending) {
3304                        return ERROR_NT(NT_STATUS_DELETE_PENDING);
3305                }
3306        }
3307
3308        nlink = sbuf.st_nlink;
3309
3310        if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3311                /* NTFS does not seem to count ".." */
3312                nlink -= 1;
3313        }
3314
3315        if ((nlink > 0) && delete_pending) {
3316                nlink -= 1;
3317        }
3318
3319        if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3320                return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3321        }
3322
3323        DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3324                fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3325
3326        p = strrchr_m(fname,'/'); 
3327        if (!p)
3328                base_name = fname;
3329        else
3330                base_name = p+1;
3331
3332        mode = dos_mode(conn,fname,&sbuf);
3333        if (!mode)
3334                mode = FILE_ATTRIBUTE_NORMAL;
3335
3336        fullpathname = fname;
3337        if (!(mode & aDIR))
3338                file_size = get_file_size(sbuf);
3339
3340        /* Pull out any data sent here before we realloc. */
3341        switch (info_level) {
3342                case SMB_INFO_QUERY_EAS_FROM_LIST:
3343                {
3344                        /* Pull any EA list from the data portion. */
3345                        uint32 ea_size;
3346
3347                        if (total_data < 4) {
3348                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3349                        }
3350                        ea_size = IVAL(pdata,0);
3351
3352                        if (total_data > 0 && ea_size != total_data) {
3353                                DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3354total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3355                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3356                        }
3357
3358                        if (!lp_ea_support(SNUM(conn))) {
3359                                return ERROR_DOS(ERRDOS,ERReasnotsupported);
3360                        }
3361
3362                        if ((data_ctx = talloc_init("ea_list")) == NULL) {
3363                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3364                        }
3365
3366                        /* Pull out the list of names. */
3367                        ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3368                        if (!ea_list) {
3369                                talloc_destroy(data_ctx);
3370                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3371                        }
3372                        break;
3373                }
3374
3375                case SMB_QUERY_POSIX_LOCK:
3376                {
3377                        if (fsp == NULL || fsp->fh->fd == -1) {
3378                                return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3379                        }
3380
3381                        if (total_data != POSIX_LOCK_DATA_SIZE) {
3382                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3383                        }
3384
3385                        if ((data_ctx = talloc_init("lock_request")) == NULL) {
3386                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3387                        }
3388
3389                        /* Copy the lock range data. */
3390                        lock_data = (char *)talloc_memdup(
3391                                data_ctx, pdata, total_data);
3392                        if (!lock_data) {
3393                                talloc_destroy(data_ctx);
3394                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3395                        }
3396                }
3397                default:
3398                        break;
3399        }
3400
3401        *pparams = (char *)SMB_REALLOC(*pparams,2);
3402        if (*pparams == NULL) {
3403                talloc_destroy(data_ctx);
3404                return ERROR_NT(NT_STATUS_NO_MEMORY);
3405        }
3406        params = *pparams;
3407        SSVAL(params,0,0);
3408        data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3409        *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3410        if (*ppdata == NULL ) {
3411                talloc_destroy(data_ctx);
3412                return ERROR_NT(NT_STATUS_NO_MEMORY);
3413        }
3414        pdata = *ppdata;
3415
3416        create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3417        mtime_ts = get_mtimespec(&sbuf);
3418        atime_ts = get_atimespec(&sbuf);
3419
3420        allocation_size = get_allocation_size(conn,fsp,&sbuf);
3421
3422        if (fsp) {
3423                if (!null_timespec(fsp->pending_modtime)) {
3424                        /* the pending modtime overrides the current modtime */
3425                        mtime_ts = fsp->pending_modtime;
3426                }
3427        } else {
3428                /* Do we have this path open ? */
3429                files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3430                if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3431                        /* the pending modtime overrides the current modtime */
3432                        mtime_ts = fsp1->pending_modtime;
3433                }
3434                if (fsp1 && fsp1->initial_allocation_size) {
3435                        allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3436                }
3437        }
3438
3439        if (lp_dos_filetime_resolution(SNUM(conn))) {
3440                dos_filetime_timespec(&create_time_ts);
3441                dos_filetime_timespec(&mtime_ts);
3442                dos_filetime_timespec(&atime_ts);
3443        }
3444
3445        create_time = convert_timespec_to_time_t(create_time_ts);
3446        mtime = convert_timespec_to_time_t(mtime_ts);
3447        atime = convert_timespec_to_time_t(atime_ts);
3448
3449        /* NT expects the name to be in an exact form of the *full*
3450           filename. See the trans2 torture test */
3451        if (strequal(base_name,".")) {
3452                pstrcpy(dos_fname, "\\");
3453        } else {
3454                pstr_sprintf(dos_fname, "\\%s", fname);
3455                string_replace(dos_fname, '/', '\\');
3456        }
3457
3458        switch (info_level) {
3459                case SMB_INFO_STANDARD:
3460                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3461                        data_size = 22;
3462                        srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3463                        srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3464                        srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3465                        SIVAL(pdata,l1_cbFile,(uint32)file_size);
3466                        SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3467                        SSVAL(pdata,l1_attrFile,mode);
3468                        break;
3469
3470                case SMB_INFO_QUERY_EA_SIZE:
3471                {
3472                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3473                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3474                        data_size = 26;
3475                        srv_put_dos_date2(pdata,0,create_time);
3476                        srv_put_dos_date2(pdata,4,atime);
3477                        srv_put_dos_date2(pdata,8,mtime); /* write time */
3478                        SIVAL(pdata,12,(uint32)file_size);
3479                        SIVAL(pdata,16,(uint32)allocation_size);
3480                        SSVAL(pdata,20,mode);
3481                        SIVAL(pdata,22,ea_size);
3482                        break;
3483                }
3484
3485                case SMB_INFO_IS_NAME_VALID:
3486                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3487                        if (tran_call == TRANSACT2_QFILEINFO) {
3488                                /* os/2 needs this ? really ?*/     
3489                                return ERROR_DOS(ERRDOS,ERRbadfunc); 
3490                        }
3491                        data_size = 0;
3492                        param_size = 0;
3493                        break;
3494                       
3495                case SMB_INFO_QUERY_EAS_FROM_LIST:
3496                {
3497                        size_t total_ea_len = 0;
3498                        struct ea_list *ea_file_list = NULL;
3499
3500                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3501
3502                        ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3503                        ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3504
3505                        if (!ea_list || (total_ea_len > data_size)) {
3506                                talloc_destroy(data_ctx);
3507                                data_size = 4;
3508                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3509                                break;
3510                        }
3511
3512                        data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3513                        talloc_destroy(data_ctx);
3514                        break;
3515                }
3516
3517                case SMB_INFO_QUERY_ALL_EAS:
3518                {
3519                        /* We have data_size bytes to put EA's into. */
3520                        size_t total_ea_len = 0;
3521
3522                        DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3523
3524                        data_ctx = talloc_init("ea_ctx");
3525                        if (!data_ctx) {
3526                                return ERROR_NT(NT_STATUS_NO_MEMORY);
3527                        }
3528
3529                        ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3530                        if (!ea_list || (total_ea_len > data_size)) {
3531                                talloc_destroy(data_ctx);
3532                                data_size = 4;
3533                                SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3534                                break;
3535                        }
3536
3537                        data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3538                        talloc_destroy(data_ctx);
3539                        break;
3540                }
3541
3542                case SMB_FILE_BASIC_INFORMATION:
3543                case SMB_QUERY_FILE_BASIC_INFO:
3544
3545                        if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3546                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3547                                data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3548                        } else {
3549                                DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3550                                data_size = 40;
3551                                SIVAL(pdata,36,0);
3552                        }
3553                        put_long_date_timespec(pdata,create_time_ts);
3554                        put_long_date_timespec(pdata+8,atime_ts);
3555                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3556                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3557                        SIVAL(pdata,32,mode);
3558
3559                        DEBUG(5,("SMB_QFBI - "));
3560                        DEBUG(5,("create: %s ", ctime(&create_time)));
3561                        DEBUG(5,("access: %s ", ctime(&atime)));
3562                        DEBUG(5,("write: %s ", ctime(&mtime)));
3563                        DEBUG(5,("change: %s ", ctime(&mtime)));
3564                        DEBUG(5,("mode: %x\n", mode));
3565                        break;
3566
3567                case SMB_FILE_STANDARD_INFORMATION:
3568                case SMB_QUERY_FILE_STANDARD_INFO:
3569
3570                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3571                        data_size = 24;
3572                        SOFF_T(pdata,0,allocation_size);
3573                        SOFF_T(pdata,8,file_size);
3574                        SIVAL(pdata,16,nlink);
3575                        SCVAL(pdata,20,delete_pending?1:0);
3576                        SCVAL(pdata,21,(mode&aDIR)?1:0);
3577                        SSVAL(pdata,22,0); /* Padding. */
3578                        break;
3579
3580                case SMB_FILE_EA_INFORMATION:
3581                case SMB_QUERY_FILE_EA_INFO:
3582                {
3583                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3584                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3585                        data_size = 4;
3586                        SIVAL(pdata,0,ea_size);
3587                        break;
3588                }
3589
3590                /* Get the 8.3 name - used if NT SMB was negotiated. */
3591                case SMB_QUERY_FILE_ALT_NAME_INFO:
3592                case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3593                {
3594                        pstring short_name;
3595
3596                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3597                        pstrcpy(short_name,base_name);
3598                        /* Mangle if not already 8.3 */
3599                        if(!mangle_is_8_3(short_name, True, conn->params)) {
3600                                mangle_map(short_name,True,True,conn->params);
3601                        }
3602                        len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3603                        data_size = 4 + len;
3604                        SIVAL(pdata,0,len);
3605                        break;
3606                }
3607
3608                case SMB_QUERY_FILE_NAME_INFO:
3609                        /*
3610                          this must be *exactly* right for ACLs on mapped drives to work
3611                         */
3612                        len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3613                        DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3614                        data_size = 4 + len;
3615                        SIVAL(pdata,0,len);
3616                        break;
3617
3618                case SMB_FILE_ALLOCATION_INFORMATION:
3619                case SMB_QUERY_FILE_ALLOCATION_INFO:
3620                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3621                        data_size = 8;
3622                        SOFF_T(pdata,0,allocation_size);
3623                        break;
3624
3625                case SMB_FILE_END_OF_FILE_INFORMATION:
3626                case SMB_QUERY_FILE_END_OF_FILEINFO:
3627                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3628                        data_size = 8;
3629                        SOFF_T(pdata,0,file_size);
3630                        break;
3631
3632                case SMB_QUERY_FILE_ALL_INFO:
3633                case SMB_FILE_ALL_INFORMATION:
3634                {
3635                        unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3636                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3637                        put_long_date_timespec(pdata,create_time_ts);
3638                        put_long_date_timespec(pdata+8,atime_ts);
3639                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3640                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3641                        SIVAL(pdata,32,mode);
3642                        SIVAL(pdata,36,0); /* padding. */
3643                        pdata += 40;
3644                        SOFF_T(pdata,0,allocation_size);
3645                        SOFF_T(pdata,8,file_size);
3646                        SIVAL(pdata,16,nlink);
3647                        SCVAL(pdata,20,delete_pending);
3648                        SCVAL(pdata,21,(mode&aDIR)?1:0);
3649                        SSVAL(pdata,22,0);
3650                        pdata += 24;
3651                        SIVAL(pdata,0,ea_size);
3652                        pdata += 4; /* EA info */
3653                        len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3654                        SIVAL(pdata,0,len);
3655                        pdata += 4 + len;
3656                        data_size = PTR_DIFF(pdata,(*ppdata));
3657                        break;
3658                }
3659                case SMB_FILE_INTERNAL_INFORMATION:
3660                        /* This should be an index number - looks like
3661                           dev/ino to me :-)
3662
3663                           I think this causes us to fail the IFSKIT
3664                           BasicFileInformationTest. -tpot */
3665
3666                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3667                        SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3668                        SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3669                        data_size = 8;
3670                        break;
3671
3672                case SMB_FILE_ACCESS_INFORMATION:
3673                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3674                        SIVAL(pdata,0,access_mask);
3675                        data_size = 4;
3676                        break;
3677
3678                case SMB_FILE_NAME_INFORMATION:
3679                        /* Pathname with leading '\'. */
3680                        {
3681                                size_t byte_len;
3682                                byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3683                                DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3684                                SIVAL(pdata,0,byte_len);
3685                                data_size = 4 + byte_len;
3686                                break;
3687                        }
3688
3689                case SMB_FILE_DISPOSITION_INFORMATION:
3690                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3691                        data_size = 1;
3692                        SCVAL(pdata,0,delete_pending);
3693                        break;
3694
3695                case SMB_FILE_POSITION_INFORMATION:
3696                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3697                        data_size = 8;
3698                        SOFF_T(pdata,0,pos);
3699                        break;
3700
3701                case SMB_FILE_MODE_INFORMATION:
3702                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3703                        SIVAL(pdata,0,mode);
3704                        data_size = 4;
3705                        break;
3706
3707                case SMB_FILE_ALIGNMENT_INFORMATION:
3708                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3709                        SIVAL(pdata,0,0); /* No alignment needed. */
3710                        data_size = 4;
3711                        break;
3712
3713#if 0
3714                /*
3715                 * NT4 server just returns "invalid query" to this - if we try to answer
3716                 * it then NTws gets a BSOD! (tridge).
3717                 * W2K seems to want this. JRA.
3718                 */
3719                case SMB_QUERY_FILE_STREAM_INFO:
3720#endif
3721                case SMB_FILE_STREAM_INFORMATION:
3722                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3723                        if (mode & aDIR) {
3724                                data_size = 0;
3725                        } else {
3726                                size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3727                                SIVAL(pdata,0,0); /* ??? */
3728                                SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3729                                SOFF_T(pdata,8,file_size);
3730                                SIVAL(pdata,16,allocation_size);
3731                                SIVAL(pdata,20,0); /* ??? */
3732                                data_size = 24 + byte_len;
3733                        }
3734                        break;
3735
3736                case SMB_QUERY_COMPRESSION_INFO:
3737                case SMB_FILE_COMPRESSION_INFORMATION:
3738                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3739                        SOFF_T(pdata,0,file_size);
3740                        SIVAL(pdata,8,0); /* ??? */
3741                        SIVAL(pdata,12,0); /* ??? */
3742                        data_size = 16;
3743                        break;
3744
3745                case SMB_FILE_NETWORK_OPEN_INFORMATION:
3746                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3747                        put_long_date_timespec(pdata,create_time_ts);
3748                        put_long_date_timespec(pdata+8,atime_ts);
3749                        put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3750                        put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3751                        SIVAL(pdata,32,allocation_size);
3752                        SOFF_T(pdata,40,file_size);
3753                        SIVAL(pdata,48,mode);
3754                        SIVAL(pdata,52,0); /* ??? */
3755                        data_size = 56;
3756                        break;
3757
3758                case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3759                        DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3760                        SIVAL(pdata,0,mode);
3761                        SIVAL(pdata,4,0);
3762                        data_size = 8;
3763                        break;
3764
3765                /*
3766                 * CIFS UNIX Extensions.
3767                 */
3768
3769                case SMB_QUERY_FILE_UNIX_BASIC:
3770
3771                        pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3772                        data_size = PTR_DIFF(pdata,(*ppdata));
3773
3774                        {
3775                                int i;
3776                                DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3777
3778                                for (i=0; i<100; i++)
3779                                        DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3780                                DEBUG(4,("\n"));
3781                        }
3782
3783                        break;
3784
3785                case SMB_QUERY_FILE_UNIX_INFO2:
3786
3787                        pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3788                        data_size = PTR_DIFF(pdata,(*ppdata));
3789
3790                        {
3791                                int i;
3792                                DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3793
3794                                for (i=0; i<100; i++)
3795                                        DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3796                                DEBUG(4,("\n"));
3797                        }
3798
3799                        break;
3800
3801                case SMB_QUERY_FILE_UNIX_LINK:
3802                        {
3803                                pstring buffer;
3804
3805                                DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3806#ifdef S_ISLNK
3807                                if(!S_ISLNK(sbuf.st_mode))
3808                                        return(UNIXERROR(ERRSRV,ERRbadlink));
3809#else
3810                                return(UNIXERROR(ERRDOS,ERRbadlink));
3811#endif
3812                                len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3813                                if (len == -1)
3814                                        return(UNIXERROR(ERRDOS,ERRnoaccess));
3815                                buffer[len] = 0;
3816                                len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3817                                pdata += len;
3818                                data_size = PTR_DIFF(pdata,(*ppdata));
3819
3820                                break;
3821                        }
3822
3823#if defined(HAVE_POSIX_ACLS)
3824                case SMB_QUERY_POSIX_ACL:
3825                        {
3826                                SMB_ACL_T file_acl = NULL;
3827                                SMB_ACL_T def_acl = NULL;
3828                                uint16 num_file_acls = 0;
3829                                uint16 num_def_acls = 0;
3830
3831                                if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3832                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3833                                } else {
3834                                        file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3835                                }
3836
3837                                if (file_acl == NULL && no_acl_syscall_error(errno)) {
3838                                        DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3839                                                fname ));
3840                                        return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3841                                }
3842
3843                                if (S_ISDIR(sbuf.st_mode)) {
3844                                        if (fsp && fsp->is_directory) {
3845                                                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3846                                        } else {
3847                                                def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3848                                        }
3849                                        def_acl = free_empty_sys_acl(conn, def_acl);
3850                                }
3851
3852                                num_file_acls = count_acl_entries(conn, file_acl);
3853                                num_def_acls = count_acl_entries(conn, def_acl);
3854
3855                                if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3856                                        DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3857                                                data_size,
3858                                                (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3859                                                        SMB_POSIX_ACL_HEADER_SIZE) ));
3860                                        if (file_acl) {
3861                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3862                                        }
3863                                        if (def_acl) {
3864                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3865                                        }
3866                                        return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3867                                }
3868
3869                                SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3870                                SSVAL(pdata,2,num_file_acls);
3871                                SSVAL(pdata,4,num_def_acls);
3872                                if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3873                                        if (file_acl) {
3874                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3875                                        }
3876                                        if (def_acl) {
3877                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3878                                        }
3879                                        return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3880                                }
3881                                if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3882                                        if (file_acl) {
3883                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3884                                        }
3885                                        if (def_acl) {
3886                                                SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3887                                        }
3888                                        return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3889                                }
3890
3891                                if (file_acl) {
3892                                        SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3893                                }
3894                                if (def_acl) {
3895                                        SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3896                                }
3897                                data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3898                                break;
3899                        }
3900#endif
3901
3902
3903                case SMB_QUERY_POSIX_LOCK:
3904                {
3905                        NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3906                        SMB_BIG_UINT count;
3907                        SMB_BIG_UINT offset;
3908                        uint32 lock_pid;
3909                        enum brl_type lock_type;
3910
3911                        if (total_data != POSIX_LOCK_DATA_SIZE) {
3912                                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3913                        }
3914
3915                        switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3916                                case POSIX_LOCK_TYPE_READ:
3917                                        lock_type = READ_LOCK;
3918                                        break;
3919                                case POSIX_LOCK_TYPE_WRITE:
3920                                        lock_type = WRITE_LOCK;
3921                                        break;
3922                                case POSIX_LOCK_TYPE_UNLOCK:
3923                                default:
3924                                        /* There's no point in asking for an unlock... */
3925                                        talloc_destroy(data_ctx);
3926                                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3927                        }
3928
3929                        lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3930#if defined(HAVE_LONGLONG)
3931                        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3932                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3933                        count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3934                                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3935#else /* HAVE_LONGLONG */
3936                        offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3937                        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3938#endif /* HAVE_LONGLONG */
3939
3940                        status = query_lock(fsp,
3941                                        &lock_pid,
3942                                        &count,
3943                                        &offset,
3944                                        &lock_type,
3945                                        POSIX_LOCK);
3946
3947                        if (ERROR_WAS_LOCK_DENIED(status)) {
3948                                /* Here we need to report who has it locked... */
3949                                data_size = POSIX_LOCK_DATA_SIZE;
3950
3951                                SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3952                                SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3953                                SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3954#if defined(HAVE_LONGLONG)
3955                                SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3956                                SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3957                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3958                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3959#else /* HAVE_LONGLONG */
3960                                SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3961                                SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3962#endif /* HAVE_LONGLONG */
3963
3964                        } else if (NT_STATUS_IS_OK(status)) {
3965                                /* For success we just return a copy of what we sent
3966                                   with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3967                                data_size = POSIX_LOCK_DATA_SIZE;
3968                                memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3969                                SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3970                        } else {
3971                                return ERROR_NT(status);
3972                        }
3973                        break;
3974                }
3975
3976                default:
3977                        return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3978        }
3979
3980        send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3981
3982        return(-1);
3983}
3984
3985/****************************************************************************
3986 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3987 code.
3988****************************************************************************/
3989
3990NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3991{
3992        SMB_STRUCT_STAT sbuf1, sbuf2;
3993        pstring last_component_oldname;
3994        pstring last_component_newname;
3995        NTSTATUS status = NT_STATUS_OK;
3996
3997        ZERO_STRUCT(sbuf1);
3998        ZERO_STRUCT(sbuf2);
3999
4000        status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4001        if (!NT_STATUS_IS_OK(status)) {
4002                return status;
4003        }
4004
4005        status = check_name(conn, oldname);
4006        if (!NT_STATUS_IS_OK(status)) {
4007                return status;
4008        }
4009
4010        /* source must already exist. */
4011        if (!VALID_STAT(sbuf1)) {
4012                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4013        }
4014
4015        status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4016        if (!NT_STATUS_IS_OK(status)) {
4017                return status;
4018        }
4019
4020        status = check_name(conn, newname);
4021        if (!NT_STATUS_IS_OK(status)) {
4022                return status;
4023        }
4024
4025        /* Disallow if newname already exists. */
4026        if (VALID_STAT(sbuf2)) {
4027                return NT_STATUS_OBJECT_NAME_COLLISION;
4028        }
4029
4030        /* No links from a directory. */
4031        if (S_ISDIR(sbuf1.st_mode)) {
4032                return NT_STATUS_FILE_IS_A_DIRECTORY;
4033        }
4034
4035        /* Ensure this is within the share. */
4036        status = reduce_name(conn, oldname);
4037        if (!NT_STATUS_IS_OK(status)) {
4038                return status;
4039        }
4040
4041        DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4042
4043        if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4044                status = map_nt_error_from_unix(errno);
4045                DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4046                                nt_errstr(status), newname, oldname));
4047        }
4048
4049        return status;
4050}
4051
4052/****************************************************************************
4053 Deal with setting the time from any of the setfilepathinfo functions.
4054****************************************************************************/
4055
4056static NTSTATUS smb_set_file_time(connection_struct *conn,
4057                                files_struct *fsp,
4058                                const char *fname,
4059                                const SMB_STRUCT_STAT *psbuf,
4060                                struct timespec ts[2])
4061{
4062        uint32 action =
4063                FILE_NOTIFY_CHANGE_LAST_ACCESS
4064                |FILE_NOTIFY_CHANGE_LAST_WRITE;
4065
4066       
4067        if (!VALID_STAT(*psbuf)) {
4068                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4069        }
4070
4071        /* get some defaults (no modifications) if any info is zero or -1. */
4072        if (null_timespec(ts[0])) {
4073                ts[0] = get_atimespec(psbuf);
4074                action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4075        }
4076
4077        if (null_timespec(ts[1])) {
4078                ts[1] = get_mtimespec(psbuf);
4079                action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4080        }
4081
4082        DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4083        DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4084
4085        /*
4086         * Try and set the times of this file if
4087         * they are different from the current values.
4088         */
4089
4090        {
4091                struct timespec mts = get_mtimespec(psbuf);
4092                struct timespec ats = get_atimespec(psbuf);
4093                if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4094                        return NT_STATUS_OK;
4095                }
4096        }
4097
4098        if(fsp != NULL) {
4099                /*
4100                 * This was a setfileinfo on an open file.
4101                 * NT does this a lot. We also need to
4102                 * set the time here, as it can be read by
4103                 * FindFirst/FindNext and with the patch for bug #2045
4104                 * in smbd/fileio.c it ensures that this timestamp is
4105                 * kept sticky even after a write. We save the request
4106                 * away and will set it on file close and after a write. JRA.
4107                 */
4108
4109                if (!null_timespec(ts[1])) {
4110                        DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4111                                time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4112                        fsp_set_pending_modtime(fsp, ts[1]);
4113                }
4114
4115        }
4116        DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4117
4118        if(file_ntimes(conn, fname, ts)!=0) {
4119                return map_nt_error_from_unix(errno);
4120        }
4121        if (action != 0) {
4122                notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4123        }
4124        return NT_STATUS_OK;
4125}
4126
4127/****************************************************************************
4128 Deal with setting the dosmode from any of the setfilepathinfo functions.
4129****************************************************************************/
4130
4131static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4132                                const char *fname,
4133                                SMB_STRUCT_STAT *psbuf,
4134                                uint32 dosmode)
4135{
4136        if (!VALID_STAT(*psbuf)) {
4137                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4138        }
4139
4140        if (dosmode) {
4141                if (S_ISDIR(psbuf->st_mode)) {
4142                        dosmode |= aDIR;
4143                } else {
4144                        dosmode &= ~aDIR;
4145                }
4146        }
4147
4148        DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4149
4150        /* check the mode isn't different, before changing it */
4151        if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4152
4153                DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4154                                        fname, (unsigned int)dosmode ));
4155
4156                if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4157                        DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4158                                                fname, strerror(errno)));
4159                        return map_nt_error_from_unix(errno);
4160                }
4161        }
4162        return NT_STATUS_OK;
4163}
4164
4165/****************************************************************************
4166 Deal with setting the size from any of the setfilepathinfo functions.
4167****************************************************************************/
4168
4169static NTSTATUS smb_set_file_size(connection_struct *conn,
4170                                files_struct *fsp,
4171                                const char *fname,
4172                                SMB_STRUCT_STAT *psbuf,
4173                                SMB_OFF_T size)
4174{
4175        NTSTATUS status = NT_STATUS_OK;
4176        files_struct *new_fsp = NULL;
4177
4178        if (!VALID_STAT(*psbuf)) {
4179                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4180        }
4181
4182        DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4183
4184        if (size == get_file_size(*psbuf)) {
4185                return NT_STATUS_OK;
4186        }
4187
4188        DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4189                fname, (double)size ));
4190
4191        if (fsp && fsp->fh->fd != -1) {
4192                /* Handle based call. */
4193                if (vfs_set_filelen(fsp, size) == -1) {
4194                        return map_nt_error_from_unix(errno);
4195                }
4196                return NT_STATUS_OK;
4197        }
4198
4199        status = open_file_ntcreate(conn, fname, psbuf,
4200                                FILE_WRITE_DATA,
4201                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4202                                FILE_OPEN,
4203                                0,
4204                                FILE_ATTRIBUTE_NORMAL,
4205                                FORCE_OPLOCK_BREAK_TO_NONE,
4206                                NULL, &new_fsp);
4207       
4208        if (!NT_STATUS_IS_OK(status)) {
4209                /* NB. We check for open_was_deferred in the caller. */
4210                return status;
4211        }
4212
4213        if (vfs_set_filelen(new_fsp, size) == -1) {
4214                status = map_nt_error_from_unix(errno);
4215                close_file(new_fsp,NORMAL_CLOSE);
4216                return status;
4217        }
4218
4219        close_file(new_fsp,NORMAL_CLOSE);
4220        return NT_STATUS_OK;
4221}
4222
4223/****************************************************************************
4224 Deal with SMB_INFO_SET_EA.
4225****************************************************************************/
4226
4227static NTSTATUS smb_info_set_ea(connection_struct *conn,
4228                                const char *pdata,
4229                                int total_data,
4230                                files_struct *fsp,
4231                                const char *fname)
4232{
4233        struct ea_list *ea_list = NULL;
4234        TALLOC_CTX *ctx = NULL;
4235        NTSTATUS status = NT_STATUS_OK;
4236
4237        if (total_data < 10) {
4238
4239                /* OS/2 workplace shell seems to send SET_EA requests of "null"
4240                   length. They seem to have no effect. Bug #3212. JRA */
4241
4242                if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4243                        /* We're done. We only get EA info in this call. */
4244                        return NT_STATUS_OK;
4245                }
4246
4247                return NT_STATUS_INVALID_PARAMETER;
4248        }
4249
4250        if (IVAL(pdata,0) > total_data) {
4251                DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4252                        IVAL(pdata,0), (unsigned int)total_data));
4253                return NT_STATUS_INVALID_PARAMETER;
4254        }
4255
4256        ctx = talloc_init("SMB_INFO_SET_EA");
4257        if (!ctx) {
4258                return NT_STATUS_NO_MEMORY;
4259        }
4260        ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4261        if (!ea_list) {
4262                talloc_destroy(ctx);
4263                return NT_STATUS_INVALID_PARAMETER;
4264        }
4265        status = set_ea(conn, fsp, fname, ea_list);
4266        talloc_destroy(ctx);
4267
4268        return status;
4269}
4270
4271/****************************************************************************
4272 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4273****************************************************************************/
4274
4275static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4276                                const char *pdata,
4277                                int total_data,
4278                                files_struct *fsp,
4279                                const char *fname,
4280                                SMB_STRUCT_STAT *psbuf)
4281{
4282        NTSTATUS status = NT_STATUS_OK;
4283        BOOL delete_on_close;
4284        uint32 dosmode = 0;
4285
4286        if (total_data < 1) {
4287                return NT_STATUS_INVALID_PARAMETER;
4288        }
4289
4290        if (fsp == NULL) {
4291                return NT_STATUS_INVALID_HANDLE;
4292        }
4293
4294        delete_on_close = (CVAL(pdata,0) ? True : False);
4295        dosmode = dos_mode(conn, fname, psbuf);
4296
4297        DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4298                "delete_on_close = %u\n",
4299                fsp->fsp_name,
4300                (unsigned int)dosmode,
4301                (unsigned int)delete_on_close ));
4302
4303        status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4304 
4305        if (!NT_STATUS_IS_OK(status)) {
4306                return status;
4307        }
4308
4309        /* The set is across all open files on this dev/inode pair. */
4310        if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4311                return NT_STATUS_ACCESS_DENIED;
4312        }
4313        return NT_STATUS_OK;
4314}
4315
4316/****************************************************************************
4317 Deal with SMB_FILE_POSITION_INFORMATION.
4318****************************************************************************/
4319
4320static NTSTATUS smb_file_position_information(connection_struct *conn,
4321                                const char *pdata,
4322                                int total_data,
4323                                files_struct *fsp)
4324{
4325        SMB_BIG_UINT position_information;
4326
4327        if (total_data < 8) {
4328                return NT_STATUS_INVALID_PARAMETER;
4329        }
4330
4331        if (fsp == NULL) {
4332                /* Ignore on pathname based set. */
4333                return NT_STATUS_OK;
4334        }
4335
4336        position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4337#ifdef LARGE_SMB_OFF_T
4338        position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4339#else /* LARGE_SMB_OFF_T */
4340        if (IVAL(pdata,4) != 0) {
4341                /* more than 32 bits? */
4342                return NT_STATUS_INVALID_PARAMETER;
4343        }
4344#endif /* LARGE_SMB_OFF_T */
4345
4346        DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4347                fsp->fsp_name, (double)position_information ));
4348        fsp->fh->position_information = position_information;
4349        return NT_STATUS_OK;
4350}
4351
4352/****************************************************************************
4353 Deal with SMB_FILE_MODE_INFORMATION.
4354****************************************************************************/
4355
4356static NTSTATUS smb_file_mode_information(connection_struct *conn,
4357                                const char *pdata,
4358                                int total_data)
4359{
4360        uint32 mode;
4361
4362        if (total_data < 4) {
4363                return NT_STATUS_INVALID_PARAMETER;
4364        }
4365        mode = IVAL(pdata,0);
4366        if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4367                return NT_STATUS_INVALID_PARAMETER;
4368        }
4369        return NT_STATUS_OK;
4370}
4371
4372/****************************************************************************
4373 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4374****************************************************************************/
4375
4376static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4377                                char *inbuf,
4378                                const char *pdata,
4379                                int total_data,
4380                                const char *fname)
4381{
4382        pstring link_target;
4383        const char *newname = fname;
4384        NTSTATUS status = NT_STATUS_OK;
4385
4386        /* Set a symbolic link. */
4387        /* Don't allow this if follow links is false. */
4388
4389        if (total_data == 0) {
4390                return NT_STATUS_INVALID_PARAMETER;
4391        }
4392
4393        if (!lp_symlinks(SNUM(conn))) {
4394                return NT_STATUS_ACCESS_DENIED;
4395        }
4396
4397        srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4398
4399        /* !widelinks forces the target path to be within the share. */
4400        /* This means we can interpret the target as a pathname. */
4401        if (!lp_widelinks(SNUM(conn))) {
4402                pstring rel_name;
4403                char *last_dirp = NULL;
4404
4405                if (*link_target == '/') {
4406                        /* No absolute paths allowed. */
4407                        return NT_STATUS_ACCESS_DENIED;
4408                }
4409                pstrcpy(rel_name, newname);
4410                last_dirp = strrchr_m(rel_name, '/');
4411                if (last_dirp) {
4412                        last_dirp[1] = '\0';
4413                } else {
4414                        pstrcpy(rel_name, "./");
4415                }
4416                pstrcat(rel_name, link_target);
4417
4418                status = check_name(conn, rel_name);
4419                if (!NT_STATUS_IS_OK(status)) {
4420                        return status;
4421                }
4422        }
4423
4424        DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4425                        newname, link_target ));
4426
4427        if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4428                return map_nt_error_from_unix(errno);
4429        }
4430
4431        return NT_STATUS_OK;
4432}
4433
4434/****************************************************************************
4435 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4436****************************************************************************/
4437
4438static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4439                                char *inbuf,
4440                                char *outbuf,
4441                                const char *pdata,
4442                                int total_data,
4443                                pstring fname)
4444{
4445        pstring oldname;
4446        NTSTATUS status = NT_STATUS_OK;
4447
4448        /* Set a hard link. */
4449        if (total_data == 0) {
4450                return NT_STATUS_INVALID_PARAMETER;
4451        }
4452
4453        srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4454        if (!NT_STATUS_IS_OK(status)) {
4455                return status;
4456        }
4457
4458        status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4459        if (!NT_STATUS_IS_OK(status)) {
4460                return status;
4461        }
4462
4463        DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4464                fname, oldname));
4465
4466        return hardlink_internals(conn, oldname, fname);
4467}
4468
4469/****************************************************************************
4470 Deal with SMB_FILE_RENAME_INFORMATION.
4471****************************************************************************/
4472
4473static NTSTATUS smb_file_rename_information(connection_struct *conn,
4474                                char *inbuf,
4475                                char *outbuf,
4476                                const char *pdata,
4477                                int total_data,
4478                                files_struct *fsp,
4479                                pstring fname)
4480{
4481        BOOL overwrite;
4482        /* uint32 root_fid; */  /* Not used */
4483        uint32 len;
4484        pstring newname;
4485        pstring base_name;
4486        BOOL dest_has_wcard = False;
4487        NTSTATUS status = NT_STATUS_OK;
4488        char *p;
4489
4490        if (total_data < 13) {
4491                return NT_STATUS_INVALID_PARAMETER;
4492        }
4493
4494        overwrite = (CVAL(pdata,0) ? True : False);
4495        /* root_fid = IVAL(pdata,4); */
4496        len = IVAL(pdata,8);
4497
4498        if (len > (total_data - 12) || (len == 0)) {
4499                return NT_STATUS_INVALID_PARAMETER;
4500        }
4501
4502        srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4503        if (!NT_STATUS_IS_OK(status)) {
4504                return status;
4505        }
4506
4507        status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4508        if (!NT_STATUS_IS_OK(status)) {
4509                return status;
4510        }
4511
4512        /* Check the new name has no '/' characters. */
4513        if (strchr_m(newname, '/')) {
4514                return NT_STATUS_NOT_SUPPORTED;
4515        }
4516
4517        /* Create the base directory. */
4518        pstrcpy(base_name, fname);
4519        p = strrchr_m(base_name, '/');
4520        if (p) {
4521                *p = '\0';
4522        }
4523        /* Append the new name. */
4524        pstrcat(base_name, "/");
4525        pstrcat(base_name, newname);
4526
4527        if (fsp) {
4528                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4529                        fsp->fnum, fsp->fsp_name, base_name ));
4530                status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4531        } else {
4532                DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4533                        fname, newname ));
4534                status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4535        }
4536
4537        return status;
4538}
4539
4540/****************************************************************************
4541 Deal with SMB_SET_POSIX_ACL.
4542****************************************************************************/
4543
4544#if defined(HAVE_POSIX_ACLS)
4545static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4546                                const char *pdata,
4547                                int total_data,
4548                                files_struct *fsp,
4549                                const char *fname,
4550                                SMB_STRUCT_STAT *psbuf)
4551{
4552        uint16 posix_acl_version;
4553        uint16 num_file_acls;
4554        uint16 num_def_acls;
4555        BOOL valid_file_acls = True;
4556        BOOL valid_def_acls = True;
4557
4558        if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4559                return NT_STATUS_INVALID_PARAMETER;
4560        }
4561        posix_acl_version = SVAL(pdata,0);
4562        num_file_acls = SVAL(pdata,2);
4563        num_def_acls = SVAL(pdata,4);
4564
4565        if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4566                valid_file_acls = False;
4567                num_file_acls = 0;
4568        }
4569
4570        if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4571                valid_def_acls = False;
4572                num_def_acls = 0;
4573        }
4574
4575        if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4576                return NT_STATUS_INVALID_PARAMETER;
4577        }
4578
4579        if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4580                        (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4581                return NT_STATUS_INVALID_PARAMETER;
4582        }
4583
4584        DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4585                fname ? fname : fsp->fsp_name,
4586                (unsigned int)num_file_acls,
4587                (unsigned int)num_def_acls));
4588
4589        if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4590                        pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4591                return map_nt_error_from_unix(errno);
4592        }
4593
4594        if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4595                        pdata + SMB_POSIX_ACL_HEADER_SIZE +
4596                        (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4597                return map_nt_error_from_unix(errno);
4598        }
4599        return NT_STATUS_OK;
4600}
4601#endif
4602
4603/****************************************************************************
4604 Deal with SMB_SET_POSIX_LOCK.
4605****************************************************************************/
4606
4607static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4608                                char *inbuf,
4609                                int length,
4610                                const char *pdata,
4611                                int total_data,
4612                                files_struct *fsp)
4613{
4614        SMB_BIG_UINT count;
4615        SMB_BIG_UINT offset;
4616        uint32 lock_pid;
4617        BOOL blocking_lock = False;
4618        enum brl_type lock_type;
4619        NTSTATUS status = NT_STATUS_OK;
4620
4621        if (fsp == NULL || fsp->fh->fd == -1) {
4622                return NT_STATUS_INVALID_HANDLE;
4623        }
4624
4625        if (total_data != POSIX_LOCK_DATA_SIZE) {
4626                return NT_STATUS_INVALID_PARAMETER;
4627        }
4628
4629        switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4630                case POSIX_LOCK_TYPE_READ:
4631                        lock_type = READ_LOCK;
4632                        break;
4633                case POSIX_LOCK_TYPE_WRITE:
4634                        /* Return the right POSIX-mappable error code for files opened read-only. */
4635                        if (!fsp->can_write) {
4636                                return NT_STATUS_INVALID_HANDLE;
4637                        }
4638                        lock_type = WRITE_LOCK;
4639                        break;
4640                case POSIX_LOCK_TYPE_UNLOCK:
4641                        lock_type = UNLOCK_LOCK;
4642                        break;
4643                default:
4644                        return NT_STATUS_INVALID_PARAMETER;
4645        }
4646
4647        if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4648                blocking_lock = False;
4649        } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4650                blocking_lock = True;
4651        } else {
4652                return NT_STATUS_INVALID_PARAMETER;
4653        }
4654
4655        if (!lp_blocking_locks(SNUM(conn))) { 
4656                blocking_lock = False;
4657        }
4658
4659        lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4660#if defined(HAVE_LONGLONG)
4661        offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4662                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4663        count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4664                        ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4665#else /* HAVE_LONGLONG */
4666        offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4667        count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4668#endif /* HAVE_LONGLONG */
4669
4670        DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4671                        "lock_pid = %u, count = %.0f, offset = %.0f\n",
4672                fsp->fsp_name,
4673                (unsigned int)lock_type,
4674                (unsigned int)lock_pid,
4675                (double)count,
4676                (double)offset ));
4677
4678        if (lock_type == UNLOCK_LOCK) {
4679                status = do_unlock(fsp,
4680                                lock_pid,
4681                                count,
4682                                offset,
4683                                POSIX_LOCK);
4684        } else {
4685                struct byte_range_lock *br_lck = do_lock(fsp,
4686                                                        lock_pid,
4687                                                        count,
4688                                                        offset,
4689                                                        lock_type,
4690                                                        POSIX_LOCK,
4691                                                        blocking_lock,
4692                                                        &status);
4693
4694                if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4695                        /*
4696                         * A blocking lock was requested. Package up
4697                         * this smb into a queued request and push it
4698                         * onto the blocking lock queue.
4699                         */
4700                        if(push_blocking_lock_request(br_lck,
4701                                                inbuf, length,
4702                                                fsp,
4703                                                -1, /* infinite timeout. */
4704                                                0,
4705                                                lock_pid,
4706                                                lock_type,
4707                                                POSIX_LOCK,
4708                                                offset,
4709                                                count)) {
4710                                TALLOC_FREE(br_lck);
4711                                return status;
4712                        }
4713                }
4714                TALLOC_FREE(br_lck);
4715        }
4716
4717        return status;
4718}
4719
4720/****************************************************************************
4721 Deal with SMB_INFO_STANDARD.
4722****************************************************************************/
4723
4724static NTSTATUS smb_set_info_standard(connection_struct *conn,
4725                                        const char *pdata,
4726                                        int total_data,
4727                                        files_struct *fsp,
4728                                        const char *fname,
4729                                        const SMB_STRUCT_STAT *psbuf)
4730{
4731        struct timespec ts[2];
4732
4733        if (total_data < 12) {
4734                return NT_STATUS_INVALID_PARAMETER;
4735        }
4736
4737        /* access time */
4738        ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4739        /* write time */
4740        ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4741
4742        DEBUG(10,("smb_set_info_standard: file %s\n",
4743                fname ? fname : fsp->fsp_name ));
4744
4745        return smb_set_file_time(conn,
4746                                fsp,
4747                                fname,
4748                                psbuf,
4749                                ts);
4750}
4751
4752/****************************************************************************
4753 Deal with SMB_SET_FILE_BASIC_INFO.
4754****************************************************************************/
4755
4756static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4757                                        const char *pdata,
4758                                        int total_data,
4759                                        files_struct *fsp,
4760                                        const char *fname,
4761                                        SMB_STRUCT_STAT *psbuf)
4762{
4763        /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4764        struct timespec write_time;
4765        struct timespec changed_time;
4766        uint32 dosmode = 0;
4767        struct timespec ts[2];
4768        NTSTATUS status = NT_STATUS_OK;
4769
4770        if (total_data < 36) {
4771                return NT_STATUS_INVALID_PARAMETER;
4772        }
4773
4774        /* Set the attributes */
4775        dosmode = IVAL(pdata,32);
4776        status = smb_set_file_dosmode(conn,
4777                                        fname,
4778                                        psbuf,
4779                                        dosmode);
4780        if (!NT_STATUS_IS_OK(status)) {
4781                return status;
4782        }
4783
4784        /* Ignore create time at offset pdata. */
4785
4786        /* access time */
4787        ts[0] = interpret_long_date(pdata+8);
4788
4789        write_time = interpret_long_date(pdata+16);
4790        changed_time = interpret_long_date(pdata+24);
4791
4792        /* mtime */
4793        ts[1] = timespec_min(&write_time, &changed_time);
4794
4795        if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4796                ts[1] = write_time;
4797        }
4798
4799        /* Prefer a defined time to an undefined one. */
4800        if (null_timespec(ts[1])) {
4801                ts[1] = null_timespec(write_time) ? changed_time : write_time;
4802        }
4803
4804        DEBUG(10,("smb_set_file_basic_info: file %s\n",
4805                fname ? fname : fsp->fsp_name ));
4806
4807        return smb_set_file_time(conn,
4808                                fsp,
4809                                fname,
4810                                psbuf,
4811                                ts);
4812}
4813
4814/****************************************************************************
4815 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4816****************************************************************************/
4817
4818static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4819                                        const char *pdata,
4820                                        int total_data,
4821                                        files_struct *fsp,
4822                                        const char *fname,
4823                                        SMB_STRUCT_STAT *psbuf)
4824{
4825        SMB_BIG_UINT allocation_size = 0;
4826        NTSTATUS status = NT_STATUS_OK;
4827        files_struct *new_fsp = NULL;
4828
4829        if (!VALID_STAT(*psbuf)) {
4830                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4831        }
4832
4833        if (total_data < 8) {
4834                return NT_STATUS_INVALID_PARAMETER;
4835        }
4836
4837        allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4838#ifdef LARGE_SMB_OFF_T
4839        allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4840#else /* LARGE_SMB_OFF_T */
4841        if (IVAL(pdata,4) != 0) {
4842                /* more than 32 bits? */
4843                return NT_STATUS_INVALID_PARAMETER;
4844        }
4845#endif /* LARGE_SMB_OFF_T */
4846
4847        DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4848                        fname, (double)allocation_size ));
4849
4850        if (allocation_size) {
4851                allocation_size = smb_roundup(conn, allocation_size);
4852        }
4853
4854        if(allocation_size == get_file_size(*psbuf)) {
4855                return NT_STATUS_OK;
4856        }
4857 
4858        DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4859                        fname, (double)allocation_size ));
4860 
4861        if (fsp && fsp->fh->fd != -1) {
4862                /* Open file handle. */
4863                if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4864                        return map_nt_error_from_unix(errno);
4865                }
4866                return NT_STATUS_OK;
4867        }
4868
4869        /* Pathname or stat or directory file. */
4870
4871        status = open_file_ntcreate(conn, fname, psbuf,
4872                                FILE_WRITE_DATA,
4873                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4874                                FILE_OPEN,
4875                                0,
4876                                FILE_ATTRIBUTE_NORMAL,
4877                                FORCE_OPLOCK_BREAK_TO_NONE,
4878                                NULL, &new_fsp);
4879 
4880        if (!NT_STATUS_IS_OK(status)) {
4881                /* NB. We check for open_was_deferred in the caller. */
4882                return status;
4883        }
4884        if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4885                status = map_nt_error_from_unix(errno);
4886                close_file(new_fsp,NORMAL_CLOSE);
4887                return status;
4888        }
4889
4890        close_file(new_fsp,NORMAL_CLOSE);
4891        return NT_STATUS_OK;
4892}
4893
4894/****************************************************************************
4895 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4896****************************************************************************/
4897
4898static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4899                                        const char *pdata,
4900                                        int total_data,
4901                                        files_struct *fsp,
4902                                        const char *fname,
4903                                        SMB_STRUCT_STAT *psbuf)
4904{
4905        SMB_OFF_T size;
4906
4907        if (total_data < 8) {
4908                return NT_STATUS_INVALID_PARAMETER;
4909        }
4910
4911        size = IVAL(pdata,0);
4912#ifdef LARGE_SMB_OFF_T
4913        size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4914#else /* LARGE_SMB_OFF_T */
4915        if (IVAL(pdata,4) != 0) {
4916                /* more than 32 bits? */
4917                return NT_STATUS_INVALID_PARAMETER;
4918        }
4919#endif /* LARGE_SMB_OFF_T */
4920        DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4921                "file %s to %.0f\n", fname, (double)size ));
4922
4923        return smb_set_file_size(conn,
4924                                fsp,
4925                                fname,
4926                                psbuf,
4927                                size);
4928}
4929
4930/****************************************************************************
4931 Allow a UNIX info mknod.
4932****************************************************************************/
4933
4934static NTSTATUS smb_unix_mknod(connection_struct *conn,
4935                                        const char *pdata,
4936                                        int total_data,
4937                                        const char *fname,
4938                                        SMB_STRUCT_STAT *psbuf)
4939{
4940        uint32 file_type = IVAL(pdata,56);
4941#if defined(HAVE_MAKEDEV)
4942        uint32 dev_major = IVAL(pdata,60);
4943        uint32 dev_minor = IVAL(pdata,68);
4944#endif
4945        SMB_DEV_T dev = (SMB_DEV_T)0;
4946        uint32 raw_unixmode = IVAL(pdata,84);
4947        NTSTATUS status;
4948        mode_t unixmode;
4949
4950        if (total_data < 100) {
4951                return NT_STATUS_INVALID_PARAMETER;
4952        }
4953
4954        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4955        if (!NT_STATUS_IS_OK(status)) {
4956                return status;
4957        }
4958
4959#if defined(HAVE_MAKEDEV)
4960        dev = makedev(dev_major, dev_minor);
4961#endif
4962
4963        switch (file_type) {
4964#if defined(S_IFIFO)
4965                case UNIX_TYPE_FIFO:
4966                        unixmode |= S_IFIFO;
4967                        break;
4968#endif
4969#if defined(S_IFSOCK)
4970                case UNIX_TYPE_SOCKET:
4971                        unixmode |= S_IFSOCK;
4972                        break;
4973#endif
4974#if defined(S_IFCHR)
4975                case UNIX_TYPE_CHARDEV:
4976                        unixmode |= S_IFCHR;
4977                        break;
4978#endif
4979#if defined(S_IFBLK)
4980                case UNIX_TYPE_BLKDEV:
4981                        unixmode |= S_IFBLK;
4982                        break;
4983#endif
4984                default:
4985                        return NT_STATUS_INVALID_PARAMETER;
4986        }
4987
4988        DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
49890%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4990
4991        /* Ok - do the mknod. */
4992        if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4993                return map_nt_error_from_unix(errno);
4994        }
4995
4996        /* If any of the other "set" calls fail we
4997         * don't want to end up with a half-constructed mknod.
4998         */
4999
5000        if (lp_inherit_perms(SNUM(conn))) {
5001                inherit_access_acl(
5002                        conn, parent_dirname(fname),
5003                        fname, unixmode);
5004        }
5005
5006        if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5007                status = map_nt_error_from_unix(errno);
5008                SMB_VFS_UNLINK(conn,fname);
5009                return status;
5010        }
5011        return NT_STATUS_OK;
5012}
5013
5014/****************************************************************************
5015 Deal with SMB_SET_FILE_UNIX_BASIC.
5016****************************************************************************/
5017
5018static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5019                                        const char *pdata,
5020                                        int total_data,
5021                                        files_struct *fsp,
5022                                        const char *fname,
5023                                        SMB_STRUCT_STAT *psbuf)
5024{
5025        struct timespec ts[2];
5026        uint32 raw_unixmode;
5027        mode_t unixmode;
5028        SMB_OFF_T size = 0;
5029        uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5030        gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5031        NTSTATUS status = NT_STATUS_OK;
5032        BOOL delete_on_fail = False;
5033        enum perm_type ptype;
5034
5035        if (total_data < 100) {
5036                return NT_STATUS_INVALID_PARAMETER;
5037        }
5038
5039        if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5040           IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5041                size=IVAL(pdata,0); /* first 8 Bytes are size */
5042#ifdef LARGE_SMB_OFF_T
5043                size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5044#else /* LARGE_SMB_OFF_T */
5045                if (IVAL(pdata,4) != 0) {
5046                        /* more than 32 bits? */
5047                        return NT_STATUS_INVALID_PARAMETER;
5048                }
5049#endif /* LARGE_SMB_OFF_T */
5050        }
5051
5052        ts[0] = interpret_long_date(pdata+24); /* access_time */
5053        ts[1] = interpret_long_date(pdata+32); /* modification_time */
5054        set_owner = (uid_t)IVAL(pdata,40);
5055        set_grp = (gid_t)IVAL(pdata,48);
5056        raw_unixmode = IVAL(pdata,84);
5057
5058        if (VALID_STAT(*psbuf)) {
5059                if (S_ISDIR(psbuf->st_mode)) {
5060                        ptype = PERM_EXISTING_DIR;
5061                } else {
5062                        ptype = PERM_EXISTING_FILE;
5063                }
5064        } else {
5065                ptype = PERM_NEW_FILE;
5066        }
5067
5068        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5069        if (!NT_STATUS_IS_OK(status)) {
5070                return status;
5071        }
5072
5073        DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5074size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5075                fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5076
5077        if (!VALID_STAT(*psbuf)) {
5078                /*
5079                 * The only valid use of this is to create character and block
5080                 * devices, and named pipes. This is deprecated (IMHO) and
5081                 * a new info level should be used for mknod. JRA.
5082                 */
5083
5084                status = smb_unix_mknod(conn,
5085                                        pdata,
5086                                        total_data,
5087                                        fname,
5088                                        psbuf);
5089                if (!NT_STATUS_IS_OK(status)) {
5090                        return status;
5091                }
5092
5093                /* Ensure we don't try and change anything else. */
5094                raw_unixmode = SMB_MODE_NO_CHANGE;
5095                size = get_file_size(*psbuf);
5096                ts[0] = get_atimespec(psbuf);
5097                ts[1] = get_mtimespec(psbuf);
5098                /*
5099                 * We continue here as we might want to change the
5100                 * owner uid/gid.
5101                 */
5102                delete_on_fail = True;
5103        }
5104
5105#if 1
5106        /* Horrible backwards compatibility hack as an old server bug
5107         * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5108         * */
5109
5110        if (!size) {
5111                size = get_file_size(*psbuf);
5112        }
5113#endif
5114
5115        /*
5116         * Deal with the UNIX specific mode set.
5117         */
5118
5119        if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5120                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5121                        (unsigned int)unixmode, fname ));
5122                if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5123                        return map_nt_error_from_unix(errno);
5124                }
5125        }
5126
5127        /*
5128         * Deal with the UNIX specific uid set.
5129         */
5130
5131        if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5132                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5133                        (unsigned int)set_owner, fname ));
5134                if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5135                        status = map_nt_error_from_unix(errno);
5136                        if (delete_on_fail) {
5137                                SMB_VFS_UNLINK(conn,fname);
5138                        }
5139                        return status;
5140                }
5141        }
5142
5143        /*
5144         * Deal with the UNIX specific gid set.
5145         */
5146
5147        if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5148                DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5149                        (unsigned int)set_owner, fname ));
5150                if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5151                        status = map_nt_error_from_unix(errno);
5152                        if (delete_on_fail) {
5153                                SMB_VFS_UNLINK(conn,fname);
5154                        }
5155                        return status;
5156                }
5157        }
5158
5159        /* Deal with any size changes. */
5160
5161        status = smb_set_file_size(conn,
5162                                fsp,
5163                                fname,
5164                                psbuf,
5165                                size);
5166        if (!NT_STATUS_IS_OK(status)) {
5167                return status;
5168        }
5169
5170        /* Deal with any time changes. */
5171
5172        return smb_set_file_time(conn,
5173                                fsp,
5174                                fname,
5175                                psbuf,
5176                                ts);
5177}
5178
5179/****************************************************************************
5180 Deal with SMB_SET_FILE_UNIX_INFO2.
5181****************************************************************************/
5182
5183static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5184                                        const char *pdata,
5185                                        int total_data,
5186                                        files_struct *fsp,
5187                                        const char *fname,
5188                                        SMB_STRUCT_STAT *psbuf)
5189{
5190        NTSTATUS status;
5191        uint32 smb_fflags;
5192        uint32 smb_fmask;
5193
5194        if (total_data < 116) {
5195                return NT_STATUS_INVALID_PARAMETER;
5196        }
5197
5198        /* Start by setting all the fields that are common between UNIX_BASIC
5199         * and UNIX_INFO2.
5200         */
5201        status = smb_set_file_unix_basic(conn, pdata, total_data,
5202                                fsp, fname, psbuf);
5203        if (!NT_STATUS_IS_OK(status)) {
5204                return status;
5205        }
5206
5207        smb_fflags = IVAL(pdata, 108);
5208        smb_fmask = IVAL(pdata, 112);
5209
5210        /* NB: We should only attempt to alter the file flags if the client
5211         * sends a non-zero mask.
5212         */
5213        if (smb_fmask != 0) {
5214                int stat_fflags = 0;
5215
5216                if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5217                            &stat_fflags)) {
5218                        /* Client asked to alter a flag we don't understand. */
5219                        return NT_STATUS_INVALID_PARAMETER;
5220                }
5221
5222                if (fsp && fsp->fh->fd != -1) {
5223                        /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5224                        return NT_STATUS_NOT_SUPPORTED;
5225                } else {
5226                        if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5227                                return map_nt_error_from_unix(errno);
5228                        }
5229                }
5230        }
5231
5232        /* XXX: need to add support for changing the create_time here. You
5233         * can do this for paths on Darwin with setattrlist(2). The right way
5234         * to hook this up is probably by extending the VFS utimes interface.
5235         */
5236
5237        return NT_STATUS_OK;
5238}
5239
5240/****************************************************************************
5241 Create a directory with POSIX semantics.
5242****************************************************************************/
5243
5244static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5245                                char **ppdata,
5246                                int total_data,
5247                                const char *fname,
5248                                SMB_STRUCT_STAT *psbuf,
5249                                int *pdata_return_size)
5250{
5251        NTSTATUS status = NT_STATUS_OK;
5252        uint32 raw_unixmode = 0;
5253        uint32 mod_unixmode = 0;
5254        mode_t unixmode = (mode_t)0;
5255        files_struct *fsp = NULL;
5256        uint16 info_level_return = 0;
5257        int info;
5258        char *pdata = *ppdata;
5259
5260        if (total_data < 18) {
5261                return NT_STATUS_INVALID_PARAMETER;
5262        }
5263
5264        raw_unixmode = IVAL(pdata,8);
5265        /* Next 4 bytes are not yet defined. */
5266
5267        status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5268        if (!NT_STATUS_IS_OK(status)) {
5269                return status;
5270        }
5271
5272        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5273
5274        DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5275                fname, (unsigned int)unixmode ));
5276
5277        status = open_directory(conn,
5278                                fname,
5279                                psbuf,
5280                                FILE_READ_ATTRIBUTES, /* Just a stat open */
5281                                FILE_SHARE_NONE, /* Ignored for stat opens */
5282                                FILE_CREATE,
5283                                0,
5284                                mod_unixmode,
5285                                &info,
5286                                &fsp);
5287
5288        if (NT_STATUS_IS_OK(status)) {
5289                close_file(fsp, NORMAL_CLOSE);
5290        }
5291
5292        info_level_return = SVAL(pdata,16);
5293 
5294        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5295                *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5296        } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5297                *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5298        } else {
5299                *pdata_return_size = 12;
5300        }
5301
5302        /* Realloc the data size */
5303        *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5304        if (*ppdata == NULL) {
5305                *pdata_return_size = 0;
5306                return NT_STATUS_NO_MEMORY;
5307        }
5308
5309        SSVAL(pdata,0,NO_OPLOCK_RETURN);
5310        SSVAL(pdata,2,0); /* No fnum. */
5311        SIVAL(pdata,4,info); /* Was directory created. */
5312
5313        switch (info_level_return) {
5314                case SMB_QUERY_FILE_UNIX_BASIC:
5315                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5316                        SSVAL(pdata,10,0); /* Padding. */
5317                        store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5318                        break;
5319                case SMB_QUERY_FILE_UNIX_INFO2:
5320                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5321                        SSVAL(pdata,10,0); /* Padding. */
5322                        store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5323                        break;
5324                default:
5325                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5326                        SSVAL(pdata,10,0); /* Padding. */
5327                        break;
5328        }
5329
5330        return status;
5331}
5332
5333/****************************************************************************
5334 Open/Create a file with POSIX semantics.
5335****************************************************************************/
5336
5337static NTSTATUS smb_posix_open(connection_struct *conn,
5338                                char **ppdata,
5339                                int total_data,
5340                                const char *fname,
5341                                SMB_STRUCT_STAT *psbuf,
5342                                int *pdata_return_size)
5343{
5344        BOOL extended_oplock_granted = False;
5345        char *pdata = *ppdata;
5346        uint32 flags = 0;
5347        uint32 wire_open_mode = 0;
5348        uint32 raw_unixmode = 0;
5349        uint32 mod_unixmode = 0;
5350        uint32 create_disp = 0;
5351        uint32 access_mask = 0;
5352        uint32 create_options = 0;
5353        NTSTATUS status = NT_STATUS_OK;
5354        mode_t unixmode = (mode_t)0;
5355        files_struct *fsp = NULL;
5356        int oplock_request = 0;
5357        int info = 0;
5358        uint16 info_level_return = 0;
5359
5360        if (total_data < 18) {
5361                return NT_STATUS_INVALID_PARAMETER;
5362        }
5363
5364        flags = IVAL(pdata,0);
5365        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5366        if (oplock_request) {
5367                oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5368        }
5369
5370        wire_open_mode = IVAL(pdata,4);
5371
5372        if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5373                return smb_posix_mkdir(conn,
5374                                        ppdata,
5375                                        total_data,
5376                                        fname,
5377                                        psbuf,
5378                                        pdata_return_size);
5379        }
5380
5381        switch (wire_open_mode & SMB_ACCMODE) {
5382                case SMB_O_RDONLY:
5383                        access_mask = FILE_READ_DATA;
5384                        break;
5385                case SMB_O_WRONLY:
5386                        access_mask = FILE_WRITE_DATA;
5387                        break;
5388                case SMB_O_RDWR:
5389                        access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5390                        break;
5391                default:
5392                        DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5393                                (unsigned int)wire_open_mode ));
5394                        return NT_STATUS_INVALID_PARAMETER;
5395        }
5396
5397        wire_open_mode &= ~SMB_ACCMODE;
5398
5399        if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5400                create_disp = FILE_CREATE;
5401        } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5402                create_disp = FILE_OVERWRITE_IF;
5403        } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5404                create_disp = FILE_OPEN_IF;
5405        } else {
5406                DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5407                        (unsigned int)wire_open_mode ));
5408                return NT_STATUS_INVALID_PARAMETER;
5409        }
5410
5411        raw_unixmode = IVAL(pdata,8);
5412        /* Next 4 bytes are not yet defined. */
5413
5414        status = unix_perms_from_wire(conn,
5415                                psbuf,
5416                                raw_unixmode,
5417                                VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5418                                &unixmode);
5419
5420        if (!NT_STATUS_IS_OK(status)) {
5421                return status;
5422        }
5423
5424        mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5425
5426        if (wire_open_mode & SMB_O_SYNC) {
5427                create_options |= FILE_WRITE_THROUGH;
5428        }
5429        if (wire_open_mode & SMB_O_APPEND) {
5430                access_mask |= FILE_APPEND_DATA;
5431        }
5432        if (wire_open_mode & SMB_O_DIRECT) {
5433                mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5434        }
5435
5436        DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5437                fname,
5438                (unsigned int)wire_open_mode,
5439                (unsigned int)unixmode ));
5440
5441        status = open_file_ntcreate(conn,
5442                                fname,
5443                                psbuf,
5444                                access_mask,
5445                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5446                                create_disp,
5447                                0,              /* no create options yet. */
5448                                mod_unixmode,
5449                                oplock_request,
5450                                &info,
5451                                &fsp);
5452
5453        if (!NT_STATUS_IS_OK(status)) {
5454                return status;
5455        }
5456
5457        if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5458                extended_oplock_granted = True;
5459        }
5460
5461        if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5462                extended_oplock_granted = True;
5463        }
5464
5465        info_level_return = SVAL(pdata,16);
5466 
5467        /* Allocate the correct return size. */
5468
5469        if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5470                *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5471        } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5472                *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5473        } else {
5474                *pdata_return_size = 12;
5475        }
5476
5477        /* Realloc the data size */
5478        *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5479        if (*ppdata == NULL) {
5480                close_file(fsp,ERROR_CLOSE);
5481                *pdata_return_size = 0;
5482                return NT_STATUS_NO_MEMORY;
5483        }
5484
5485        if (extended_oplock_granted) {
5486                if (flags & REQUEST_BATCH_OPLOCK) {
5487                        SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5488                } else {
5489                        SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5490                }
5491        } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5492                SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5493        } else {
5494                SSVAL(pdata,0,NO_OPLOCK_RETURN);
5495        }
5496
5497        SSVAL(pdata,2,fsp->fnum);
5498        SIVAL(pdata,4,info); /* Was file created etc. */
5499
5500        switch (info_level_return) {
5501                case SMB_QUERY_FILE_UNIX_BASIC:
5502                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5503                        SSVAL(pdata,10,0); /* padding. */
5504                        store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5505                        break;
5506                case SMB_QUERY_FILE_UNIX_INFO2:
5507                        SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5508                        SSVAL(pdata,10,0); /* padding. */
5509                        store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5510                        break;
5511                default:
5512                        SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5513                        SSVAL(pdata,10,0); /* padding. */
5514                        break;
5515        }
5516        return NT_STATUS_OK;
5517}
5518
5519/****************************************************************************
5520 Delete a file with POSIX semantics.
5521****************************************************************************/
5522
5523static NTSTATUS smb_posix_unlink(connection_struct *conn,
5524                                const char *pdata,
5525                                int total_data,
5526                                const char *fname,
5527                                SMB_STRUCT_STAT *psbuf)
5528{
5529        NTSTATUS status = NT_STATUS_OK;
5530        files_struct *fsp = NULL;
5531        uint16 flags = 0;
5532        int info = 0;
5533
5534        if (total_data < 2) {
5535                return NT_STATUS_INVALID_PARAMETER;
5536        }
5537
5538        flags = SVAL(pdata,0);
5539
5540        if (!VALID_STAT(*psbuf)) {
5541                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5542        }
5543
5544        if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5545                        !VALID_STAT_OF_DIR(*psbuf)) {
5546                return NT_STATUS_NOT_A_DIRECTORY;
5547        }
5548
5549        DEBUG(10,("smb_posix_unlink: %s %s\n",
5550                (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5551                fname));
5552
5553        if (VALID_STAT_OF_DIR(*psbuf)) {
5554                status = open_directory(conn,
5555                                        fname,
5556                                        psbuf,
5557                                        DELETE_ACCESS,
5558                                        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5559                                        FILE_OPEN,
5560                                        FILE_DELETE_ON_CLOSE,
5561                                        FILE_FLAG_POSIX_SEMANTICS|0777,
5562                                        &info,                         
5563                                        &fsp);
5564        } else {
5565                char del = 1;
5566
5567                status = open_file_ntcreate(conn,
5568                                fname,
5569                                psbuf,
5570                                DELETE_ACCESS,
5571                                FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5572                                FILE_OPEN,
5573                                0,
5574                                FILE_FLAG_POSIX_SEMANTICS|0777,
5575                                0, /* No oplock, but break existing ones. */
5576                                &info,
5577                                &fsp);
5578                /*
5579                 * For file opens we must set the delete on close
5580                 * after the open.
5581                 */
5582
5583                if (!NT_STATUS_IS_OK(status)) {
5584                        return status;
5585                }
5586
5587                status = smb_set_file_disposition_info(conn,
5588                                                        &del,
5589                                                        1,
5590                                                        fsp,
5591                                                        fname,
5592                                                        psbuf);
5593        }
5594
5595        if (!NT_STATUS_IS_OK(status)) {
5596                return status;
5597        }
5598        return close_file(fsp, NORMAL_CLOSE);
5599}
5600
5601/****************************************************************************
5602 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5603****************************************************************************/
5604
5605static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5606                                        unsigned int tran_call,
5607                                        char **pparams, int total_params, char **ppdata, int total_data,
5608                                        unsigned int max_data_bytes)
5609{
5610        char *params = *pparams;
5611        char *pdata = *ppdata;
5612        uint16 info_level;
5613        SMB_STRUCT_STAT sbuf;
5614        pstring fname;
5615        files_struct *fsp = NULL;
5616        NTSTATUS status = NT_STATUS_OK;
5617        int data_return_size = 0;
5618
5619        if (!params) {
5620                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5621        }
5622
5623        ZERO_STRUCT(sbuf);
5624
5625        if (tran_call == TRANSACT2_SETFILEINFO) {
5626                if (total_params < 4) {
5627                        return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5628                }
5629
5630                fsp = file_fsp(params,0);
5631                info_level = SVAL(params,2);   
5632
5633                if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5634                        /*
5635                         * This is actually a SETFILEINFO on a directory
5636                         * handle (returned from an NT SMB). NT5.0 seems
5637                         * to do this call. JRA.
5638                         */
5639                        pstrcpy(fname, fsp->fsp_name);
5640                        if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5641                                DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5642                                return UNIXERROR(ERRDOS