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