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