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