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