r5872: Restructure ea list code to start to fix the EA_LIST calls. This does not
[abartlet/samba.git/.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6
7    Extensively modified by Andrew Tridgell, 1995
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 extern enum protocol_types Protocol;
27 extern int smb_read_error;
28 extern int global_oplock_break;
29 extern uint32 global_client_caps;
30 extern struct current_user current_user;
31
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
34
35 /********************************************************************
36  Roundup a value to the nearest allocation roundup size boundary.
37  Only do this for Windows clients.
38 ********************************************************************/
39
40 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
41 {
42         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
43
44         /* Only roundup for Windows clients. */
45         enum remote_arch_types ra_type = get_remote_arch();
46         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
47                 val = SMB_ROUNDUP(val,rval);
48         }
49         return val;
50 }
51
52 /********************************************************************
53  Given a stat buffer return the allocated size on disk, taking into
54  account sparse files.
55 ********************************************************************/
56
57 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
58 {
59         SMB_BIG_UINT ret;
60
61 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
62         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
63 #else
64         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
65 #endif
66
67         if (!ret && fsp && fsp->initial_allocation_size)
68                 ret = fsp->initial_allocation_size;
69
70         return smb_roundup(conn, ret);
71 }
72
73 /****************************************************************************
74  Utility functions for dealing with extended attributes.
75 ****************************************************************************/
76
77 static const char *prohibited_ea_names[] = {
78         SAMBA_POSIX_INHERITANCE_EA_NAME,
79         SAMBA_XATTR_DOS_ATTRIB,
80         NULL
81 };
82
83 /****************************************************************************
84  Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
86
87 static BOOL samba_private_attr_name(const char *unix_ea_name)
88 {
89         int i;
90
91         for (i = 0; prohibited_ea_names[i]; i++) {
92                 if (strequal( prohibited_ea_names[i], unix_ea_name))
93                         return True;
94         }
95         return False;
96 }
97
98 struct ea_list {
99         struct ea_list *next, *prev;
100         struct ea_struct ea;
101 };
102
103 /****************************************************************************
104  Get one EA value. Fill in a struct ea_struct.
105 ****************************************************************************/
106
107 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
108                                 const char *fname, char *ea_name, struct ea_struct *pea)
109 {
110         /* Get the value of this xattr. Max size is 64k. */
111         size_t attr_size = 256;
112         char *val = NULL;
113         ssize_t sizeret;
114
115  again:
116
117         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
118         if (!val) {
119                 return False;
120         }
121
122         if (fsp && fsp->fd != -1) {
123                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
124         } else {
125                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
126         }
127
128         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
129                 attr_size = 65536;
130                 goto again;
131         }
132
133         if (sizeret == -1) {
134                 return False;
135         }
136
137         DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
138         dump_data(10, val, sizeret);
139
140         pea->flags = 0;
141         if (strnequal(ea_name, "user.", 5)) {
142                 pea->name = &ea_name[5];
143         } else {
144                 pea->name = ea_name;
145         }
146         pea->value.data = (unsigned char *)val;
147         pea->value.length = (size_t)sizeret;
148         return True;
149 }
150
151 /****************************************************************************
152  Return a linked list of the total EA's. Plus the total size
153 ****************************************************************************/
154
155 static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
156 {
157         /* Get a list of all xattrs. Max namesize is 64k. */
158         size_t ea_namelist_size = 1024;
159         char *ea_namelist;
160         char *p;
161         ssize_t sizeret;
162         int i;
163         struct ea_list *ea_list_head = NULL;
164
165         *pea_total_len = 0;
166
167         if (!lp_ea_support(SNUM(conn))) {
168                 return NULL;
169         }
170
171         for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
172                         ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
173                 if (fsp && fsp->fd != -1) {
174                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
175                 } else {
176                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
177                 }
178
179                 if (sizeret == -1 && errno == ERANGE) {
180                         ea_namelist_size *= 2;
181                 } else {
182                         break;
183                 }
184         }
185
186         if (sizeret == -1)
187                 return NULL;
188
189         DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
190
191         if (sizeret) {
192                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
193                         struct ea_list *listp, *tmp;
194
195                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
196                                 continue;
197                 
198                         listp = TALLOC_P(mem_ctx, struct ea_list);
199                         if (!listp)
200                                 return NULL;
201
202                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
203                                 return NULL;
204                         }
205
206                         {
207                                 fstring dos_ea_name;
208                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
209                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
210                                 DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
211                                         *pea_total_len, dos_ea_name,
212                                         (unsigned int)listp->ea.value.length ));
213                         }
214                         DLIST_ADD_END(ea_list_head, listp, tmp);
215                 }
216                 /* Add on 4 for total length. */
217                 if (*pea_total_len) {
218                         *pea_total_len += 4;
219                 }
220         }
221
222         DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
223         return ea_list_head;
224 }
225
226 /****************************************************************************
227  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
228  that was filled.
229 ****************************************************************************/
230
231 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
232         connection_struct *conn, struct ea_list *ea_list)
233 {
234         unsigned int ret_data_size = 4;
235         char *p = pdata;
236
237         SMB_ASSERT(total_data_size >= 4);
238
239         SIVAL(pdata,0,0);
240         if (!lp_ea_support(SNUM(conn))) {
241                 return 4;
242         }
243
244         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
245                 size_t dos_namelen;
246                 fstring dos_ea_name;
247                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
248                 dos_namelen = strlen(dos_ea_name);
249                 if (dos_namelen > 255 || dos_namelen == 0) {
250                         break;
251                 }
252                 if (ea_list->ea.value.length > 65535) {
253                         break;
254                 }
255                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
256                         break;
257                 }
258
259                 /* We know we have room. */
260                 SCVAL(p,0,ea_list->ea.flags);
261                 SCVAL(p,1,dos_namelen);
262                 SSVAL(p,2,ea_list->ea.value.length);
263                 fstrcpy(p+4, dos_ea_name);
264                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
265
266                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
267                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
268         }
269
270         ret_data_size = PTR_DIFF(p, pdata);
271         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
272         SIVAL(pdata,0,ret_data_size);
273         return ret_data_size;
274 }
275
276 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
277 {
278         size_t total_ea_len = 0;
279         TALLOC_CTX *mem_ctx = NULL;
280
281         if (!lp_ea_support(SNUM(conn))) {
282                 return 0;
283         }
284         mem_ctx = talloc_init("estimate_ea_size");
285         (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
286         talloc_destroy(mem_ctx);
287         return total_ea_len;
288 }
289
290 /****************************************************************************
291  Ensure the EA name is case insensitive by matching any existing EA name.
292 ****************************************************************************/
293
294 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
295 {
296         size_t total_ea_len;
297         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
298         struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
299
300         for (; ea_list; ea_list = ea_list->next) {
301                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
302                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
303                                 &unix_ea_name[5], ea_list->ea.name));
304                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
305                         break;
306                 }
307         }
308         talloc_destroy(mem_ctx);
309 }
310
311 /****************************************************************************
312  Set or delete an extended attribute.
313 ****************************************************************************/
314
315 static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
316                         char *pdata, int total_data)
317 {
318         unsigned int namelen;
319         unsigned int ealen;
320         int ret;
321         fstring unix_ea_name;
322
323         if (!lp_ea_support(SNUM(conn))) {
324                 return NT_STATUS_EAS_NOT_SUPPORTED;
325         }
326
327         if (total_data < 8) {
328                 return NT_STATUS_INVALID_PARAMETER;
329         }
330
331         if (IVAL(pdata,0) > total_data) {
332                 DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
333                 return NT_STATUS_INVALID_PARAMETER;
334         }
335
336         pdata += 4;
337         namelen = CVAL(pdata,1);
338         ealen = SVAL(pdata,2);
339         pdata += 4;
340         if (total_data < 8 + namelen + 1 + ealen) {
341                 DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
342                         (unsigned int)total_data, namelen, ealen));
343                 return NT_STATUS_INVALID_PARAMETER;
344         }
345
346         if (pdata[namelen] != '\0') {
347                 DEBUG(10,("set_ea: ea name not null terminated\n"));
348                 return NT_STATUS_INVALID_PARAMETER;
349         }
350
351         fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
352         pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
353         pdata += (namelen + 1);
354
355         canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
356
357         DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
358         if (ealen) {
359                 DEBUG(10,("set_ea: data :\n"));
360                 dump_data(10, pdata, ealen);
361         }
362
363         if (samba_private_attr_name(unix_ea_name)) {
364                 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
365                 return NT_STATUS_ACCESS_DENIED;
366         }
367
368         if (ealen == 0) {
369                 /* Remove the attribute. */
370                 if (fsp && (fsp->fd != -1)) {
371                         DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
372                                 unix_ea_name, fsp->fsp_name));
373                         ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
374                 } else {
375                         DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
376                                 unix_ea_name, fname));
377                         ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
378                 }
379 #ifdef ENOATTR
380                 /* Removing a non existent attribute always succeeds. */
381                 if (ret == -1 && errno == ENOATTR) {
382                         DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
383                         ret = 0;
384                 }
385 #endif
386         } else {
387                 if (fsp && (fsp->fd != -1)) {
388                         DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
389                                 unix_ea_name, fsp->fsp_name));
390                         ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
391                 } else {
392                         DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
393                                 unix_ea_name, fname));
394                         ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
395                 }
396         }
397
398         if (ret == -1) {
399 #ifdef ENOTSUP
400                 if (errno == ENOTSUP) {
401                         return NT_STATUS_EAS_NOT_SUPPORTED;
402                 }
403 #endif
404                 return map_nt_error_from_unix(errno);
405         }
406
407         return NT_STATUS_OK;
408 }
409
410 /****************************************************************************
411  Read a list of EA's from an incoming data buffer. Create an ea_list with them.
412 ****************************************************************************/
413
414 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
415 {
416         struct ea_list *ea_list_head = NULL;
417         size_t offset = 4;
418
419         while (offset + 2 < data_size) {
420                 struct ea_list *tmp;
421                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
422                 unsigned int namelen = CVAL(pdata,offset);
423
424                 offset++; /* Go past the namelen byte. */
425                 if (offset + namelen >= data_size) {
426                         break;
427                 }
428                 eal->ea.name = TALLOC_ARRAY(ctx, char, namelen + 1);
429                 if (!eal->ea.name) {
430                         break;
431                 }
432                 memcpy(eal->ea.name, pdata + offset, namelen);
433                 eal->ea.name[namelen] = '\0';
434
435                 offset += (namelen + 1); /* Go past the name + terminating zero. */
436                 DLIST_ADD_END(ea_list_head, eal, tmp);
437         }
438
439         return ea_list_head;
440 }
441
442 /****************************************************************************
443   Send the required number of replies back.
444   We assume all fields other than the data fields are
445   set correctly for the type of call.
446   HACK ! Always assumes smb_setup field is zero.
447 ****************************************************************************/
448
449 static int send_trans2_replies(char *outbuf,
450                         int bufsize,
451                         char *params, 
452                         int paramsize,
453                         char *pdata,
454                         int datasize)
455 {
456         /* As we are using a protocol > LANMAN1 then the max_send
457          variable must have been set in the sessetupX call.
458          This takes precedence over the max_xmit field in the
459          global struct. These different max_xmit variables should
460          be merged as this is now too confusing */
461
462         extern int max_send;
463         int data_to_send = datasize;
464         int params_to_send = paramsize;
465         int useable_space;
466         char *pp = params;
467         char *pd = pdata;
468         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
469         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
470         int data_alignment_offset = 0;
471
472         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
473         
474         set_message(outbuf,10,0,True);
475
476         /* If there genuinely are no parameters or data to send just send the empty packet */
477
478         if(params_to_send == 0 && data_to_send == 0) {
479                 if (!send_smb(smbd_server_fd(),outbuf))
480                         exit_server("send_trans2_replies: send_smb failed.");
481                 return 0;
482         }
483
484         /* When sending params and data ensure that both are nicely aligned */
485         /* Only do this alignment when there is also data to send - else
486                 can cause NT redirector problems. */
487
488         if (((params_to_send % 4) != 0) && (data_to_send != 0))
489                 data_alignment_offset = 4 - (params_to_send % 4);
490
491         /* Space is bufsize minus Netbios over TCP header minus SMB header */
492         /* The alignment_offset is to align the param bytes on an even byte
493                 boundary. NT 4.0 Beta needs this to work correctly. */
494
495         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
496
497         /* useable_space can never be more than max_send minus the alignment offset. */
498
499         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
500
501         while (params_to_send || data_to_send) {
502                 /* Calculate whether we will totally or partially fill this packet */
503
504                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
505
506                 /* We can never send more than useable_space */
507                 /*
508                  * Note that 'useable_space' does not include the alignment offsets,
509                  * but we must include the alignment offsets in the calculation of
510                  * the length of the data we send over the wire, as the alignment offsets
511                  * are sent here. Fix from Marc_Jacobsen@hp.com.
512                  */
513
514                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
515
516                 set_message(outbuf, 10, total_sent_thistime, True);
517
518                 /* Set total params and data to be sent */
519                 SSVAL(outbuf,smb_tprcnt,paramsize);
520                 SSVAL(outbuf,smb_tdrcnt,datasize);
521
522                 /* Calculate how many parameters and data we can fit into
523                  * this packet. Parameters get precedence
524                  */
525
526                 params_sent_thistime = MIN(params_to_send,useable_space);
527                 data_sent_thistime = useable_space - params_sent_thistime;
528                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
529
530                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
531
532                 /* smb_proff is the offset from the start of the SMB header to the
533                         parameter bytes, however the first 4 bytes of outbuf are
534                         the Netbios over TCP header. Thus use smb_base() to subtract
535                         them from the calculation */
536
537                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
538
539                 if(params_sent_thistime == 0)
540                         SSVAL(outbuf,smb_prdisp,0);
541                 else
542                         /* Absolute displacement of param bytes sent in this packet */
543                         SSVAL(outbuf,smb_prdisp,pp - params);
544
545                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
546                 if(data_sent_thistime == 0) {
547                         SSVAL(outbuf,smb_droff,0);
548                         SSVAL(outbuf,smb_drdisp, 0);
549                 } else {
550                         /* The offset of the data bytes is the offset of the
551                                 parameter bytes plus the number of parameters being sent this time */
552                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
553                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
554                         SSVAL(outbuf,smb_drdisp, pd - pdata);
555                 }
556
557                 /* Copy the param bytes into the packet */
558
559                 if(params_sent_thistime)
560                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
561
562                 /* Copy in the data bytes */
563                 if(data_sent_thistime)
564                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
565                                 data_alignment_offset,pd,data_sent_thistime);
566
567                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
568                         params_sent_thistime, data_sent_thistime, useable_space));
569                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
570                         params_to_send, data_to_send, paramsize, datasize));
571
572                 /* Send the packet */
573                 if (!send_smb(smbd_server_fd(),outbuf))
574                         exit_server("send_trans2_replies: send_smb failed.");
575
576                 pp += params_sent_thistime;
577                 pd += data_sent_thistime;
578
579                 params_to_send -= params_sent_thistime;
580                 data_to_send -= data_sent_thistime;
581
582                 /* Sanity check */
583                 if(params_to_send < 0 || data_to_send < 0) {
584                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
585                                 params_to_send, data_to_send));
586                         return -1;
587                 }
588         }
589
590         return 0;
591 }
592
593 /****************************************************************************
594  Reply to a TRANSACT2_OPEN.
595 ****************************************************************************/
596
597 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
598                                 char **pparams, int total_params, char **ppdata, int total_data,
599                                 unsigned int max_data_bytes)
600 {
601         char *params = *pparams;
602         int16 open_mode;
603         int16 open_attr;
604         BOOL oplock_request;
605 #if 0
606         BOOL return_additional_info;
607         int16 open_sattr;
608         time_t open_time;
609 #endif
610         int16 open_ofun;
611         int32 open_size;
612         char *pname;
613         pstring fname;
614         SMB_OFF_T size=0;
615         int fmode=0,mtime=0,rmode;
616         SMB_INO_T inode = 0;
617         SMB_STRUCT_STAT sbuf;
618         int smb_action = 0;
619         BOOL bad_path = False;
620         files_struct *fsp;
621         NTSTATUS status;
622
623         /*
624          * Ensure we have enough parameters to perform the operation.
625          */
626
627         if (total_params < 29)
628                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
629
630         open_mode = SVAL(params, 2);
631         open_attr = SVAL(params,6);
632         oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
633 #if 0
634         return_additional_info = BITSETW(params,0);
635         open_sattr = SVAL(params, 4);
636         open_time = make_unix_date3(params+8);
637 #endif
638         open_ofun = SVAL(params,12);
639         open_size = IVAL(params,14);
640         pname = &params[28];
641
642         if (IS_IPC(conn))
643                 return(ERROR_DOS(ERRSRV,ERRaccess));
644
645         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
646         if (!NT_STATUS_IS_OK(status)) {
647                 return ERROR_NT(status);
648         }
649
650         DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
651                 fname,open_mode, open_attr, open_ofun, open_size));
652
653         /* XXXX we need to handle passed times, sattr and flags */
654
655         unix_convert(fname,conn,0,&bad_path,&sbuf);
656         if (bad_path) {
657                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
658         }
659     
660         if (!check_name(fname,conn)) {
661                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
662         }
663
664         fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
665                 oplock_request, &rmode,&smb_action);
666       
667         if (!fsp) {
668                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
669                         /* We have re-scheduled this call. */
670                         clear_cached_errors();
671                         return -1;
672                 }
673                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
674         }
675
676         size = get_file_size(sbuf);
677         fmode = dos_mode(conn,fname,&sbuf);
678         mtime = sbuf.st_mtime;
679         inode = sbuf.st_ino;
680         if (fmode & aDIR) {
681                 close_file(fsp,False);
682                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
683         }
684
685         /* Realloc the size of parameters and data we will return */
686         params = SMB_REALLOC(*pparams, 28);
687         if( params == NULL )
688                 return(ERROR_DOS(ERRDOS,ERRnomem));
689         *pparams = params;
690
691         memset((char *)params,'\0',28);
692         SSVAL(params,0,fsp->fnum);
693         SSVAL(params,2,fmode);
694         put_dos_date2(params,4, mtime);
695         SIVAL(params,8, (uint32)size);
696         SSVAL(params,12,rmode);
697
698         if (oplock_request && lp_fake_oplocks(SNUM(conn)))
699                 smb_action |= EXTENDED_OPLOCK_GRANTED;
700
701         SSVAL(params,18,smb_action);
702
703         /*
704          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
705          */
706         SIVAL(params,20,inode);
707  
708         /* Send the required number of replies */
709         send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
710
711         return -1;
712 }
713
714 /*********************************************************
715  Routine to check if a given string matches exactly.
716  as a special case a mask of "." does NOT match. That
717  is required for correct wildcard semantics
718  Case can be significant or not.
719 **********************************************************/
720
721 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
722 {
723         if (mask[0] == '.' && mask[1] == 0)
724                 return False;
725         if (case_sig)   
726                 return strcmp(str,mask)==0;
727         if (StrCaseCmp(str,mask) != 0) {
728                 return False;
729         }
730         if (ms_has_wild(str)) {
731                 return False;
732         }
733         return True;
734 }
735
736 /****************************************************************************
737  Return the filetype for UNIX extensions.
738 ****************************************************************************/
739
740 static uint32 unix_filetype(mode_t mode)
741 {
742         if(S_ISREG(mode))
743                 return UNIX_TYPE_FILE;
744         else if(S_ISDIR(mode))
745                 return UNIX_TYPE_DIR;
746 #ifdef S_ISLNK
747         else if(S_ISLNK(mode))
748                 return UNIX_TYPE_SYMLINK;
749 #endif
750 #ifdef S_ISCHR
751         else if(S_ISCHR(mode))
752                 return UNIX_TYPE_CHARDEV;
753 #endif
754 #ifdef S_ISBLK
755         else if(S_ISBLK(mode))
756                 return UNIX_TYPE_BLKDEV;
757 #endif
758 #ifdef S_ISFIFO
759         else if(S_ISFIFO(mode))
760                 return UNIX_TYPE_FIFO;
761 #endif
762 #ifdef S_ISSOCK
763         else if(S_ISSOCK(mode))
764                 return UNIX_TYPE_SOCKET;
765 #endif
766
767         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
768         return UNIX_TYPE_UNKNOWN;
769 }
770
771 /****************************************************************************
772  Map wire perms onto standard UNIX permissions. Obey share restrictions.
773 ****************************************************************************/
774
775 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
776 {
777         mode_t ret = 0;
778
779         if (perms == SMB_MODE_NO_CHANGE)
780                 return pst->st_mode;
781
782         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
783         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
784         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
785         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
786         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
787         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
788         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
789         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
790         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
791 #ifdef S_ISVTX
792         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
793 #endif
794 #ifdef S_ISGID
795         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
796 #endif
797 #ifdef S_ISUID
798         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
799 #endif
800
801         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
802                 ret &= lp_dir_mask(SNUM(conn));
803                 /* Add in force bits */
804                 ret |= lp_force_dir_mode(SNUM(conn));
805         } else {
806                 /* Apply mode mask */
807                 ret &= lp_create_mask(SNUM(conn));
808                 /* Add in force bits */
809                 ret |= lp_force_create_mode(SNUM(conn));
810         }
811
812         return ret;
813 }
814
815 /****************************************************************************
816  Get a level dependent lanman2 dir entry.
817 ****************************************************************************/
818
819 static BOOL get_lanman2_dir_entry(connection_struct *conn,
820                                   void *inbuf, void *outbuf,
821                                  char *path_mask,int dirtype,int info_level,
822                                  int requires_resume_key,
823                                  BOOL dont_descend,char **ppdata, 
824                                  char *base_data, int space_remaining, 
825                                  BOOL *out_of_space, BOOL *got_exact_match,
826                                  int *last_entry_off)
827 {
828         const char *dname;
829         BOOL found = False;
830         SMB_STRUCT_STAT sbuf;
831         pstring mask;
832         pstring pathreal;
833         pstring fname;
834         char *p, *q, *pdata = *ppdata;
835         uint32 reskey=0;
836         long prev_dirpos=0;
837         int mode=0;
838         SMB_OFF_T file_size = 0;
839         SMB_BIG_UINT allocation_size = 0;
840         uint32 len;
841         time_t mdate=0, adate=0, cdate=0;
842         char *nameptr;
843         char *last_entry_ptr;
844         BOOL was_8_3;
845         int nt_extmode; /* Used for NT connections instead of mode */
846         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
847
848         *fname = 0;
849         *out_of_space = False;
850         *got_exact_match = False;
851
852         if (!conn->dirptr)
853                 return(False);
854
855         p = strrchr_m(path_mask,'/');
856         if(p != NULL) {
857                 if(p[1] == '\0')
858                         pstrcpy(mask,"*.*");
859                 else
860                         pstrcpy(mask, p+1);
861         } else
862                 pstrcpy(mask, path_mask);
863
864
865         while (!found) {
866                 BOOL got_match;
867                 /* Needed if we run out of space */
868                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
869                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
870
871                 /*
872                  * Due to bugs in NT client redirectors we are not using
873                  * resume keys any more - set them to zero.
874                  * Check out the related comments in findfirst/findnext.
875                  * JRA.
876                  */
877
878                 reskey = 0;
879
880                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
881                         (long)conn->dirptr,curr_dirpos));
882       
883                 if (!dname) 
884                         return(False);
885
886                 pstrcpy(fname,dname);      
887
888                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
889                         got_match = mask_match(fname, mask, conn->case_sensitive);
890
891                 if(!got_match && !mangle_is_8_3(fname, False)) {
892
893                         /*
894                          * It turns out that NT matches wildcards against
895                          * both long *and* short names. This may explain some
896                          * of the wildcard wierdness from old DOS clients
897                          * that some people have been seeing.... JRA.
898                          */
899
900                         pstring newname;
901                         pstrcpy( newname, fname);
902                         mangle_map( newname, True, False, SNUM(conn));
903                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
904                                 got_match = mask_match(newname, mask, conn->case_sensitive);
905                 }
906
907                 if(got_match) {
908                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
909                         if (dont_descend && !isdots)
910                                 continue;
911           
912                         pstrcpy(pathreal,conn->dirpath);
913                         if(needslash)
914                                 pstrcat(pathreal,"/");
915                         pstrcat(pathreal,dname);
916
917                         if (INFO_LEVEL_IS_UNIX(info_level)) {
918                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
919                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
920                                                 pathreal,strerror(errno)));
921                                         continue;
922                                 }
923                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
924
925                                 /* Needed to show the msdfs symlinks as 
926                                  * directories */
927
928                                 if(lp_host_msdfs() && 
929                                    lp_msdfs_root(SNUM(conn)) &&
930                                    is_msdfs_link(conn, pathreal, NULL, NULL,
931                                                  &sbuf)) {
932
933                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
934                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
935
936                                 } else {
937
938                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
939                                                 pathreal,strerror(errno)));
940                                         continue;
941                                 }
942                         }
943
944                         mode = dos_mode(conn,pathreal,&sbuf);
945
946                         if (!dir_check_ftype(conn,mode,dirtype)) {
947                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
948                                 continue;
949                         }
950
951                         file_size = get_file_size(sbuf);
952                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
953                         mdate = sbuf.st_mtime;
954                         adate = sbuf.st_atime;
955                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
956
957                         if (lp_dos_filetime_resolution(SNUM(conn))) {
958                                 cdate &= ~1;
959                                 mdate &= ~1;
960                                 adate &= ~1;
961                         }
962
963                         if(mode & aDIR) {
964                                 /* This is necessary, as otherwise the
965                                  * desktop.ini file in this folder is
966                                  * ignored */
967                                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
968                                 file_size = 0;
969                         }
970
971                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
972           
973                         found = True;
974                 }
975         }
976
977         mangle_map(fname,False,True,SNUM(conn));
978
979         p = pdata;
980         last_entry_ptr = p;
981
982         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
983
984         switch (info_level) {
985                 case SMB_FIND_INFO_STANDARD:
986                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
987                         if(requires_resume_key) {
988                                 SIVAL(p,0,reskey);
989                                 p += 4;
990                         }
991                         put_dos_date2(p,l1_fdateCreation,cdate);
992                         put_dos_date2(p,l1_fdateLastAccess,adate);
993                         put_dos_date2(p,l1_fdateLastWrite,mdate);
994                         SIVAL(p,l1_cbFile,(uint32)file_size);
995                         SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
996                         SSVAL(p,l1_attrFile,mode);
997                         p += l1_achName;
998                         nameptr = p;
999                         p += align_string(outbuf, p, 0);
1000                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1001                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1002                                 if (len > 2) {
1003                                         SCVAL(nameptr, -1, len - 2);
1004                                 } else {
1005                                         SCVAL(nameptr, -1, 0);
1006                                 }
1007                         } else {
1008                                 if (len > 1) {
1009                                         SCVAL(nameptr, -1, len - 1);
1010                                 } else {
1011                                         SCVAL(nameptr, -1, 0);
1012                                 }
1013                         }
1014                         p += len;
1015                         break;
1016
1017                 case SMB_FIND_EA_SIZE:
1018                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1019                         if(requires_resume_key) {
1020                                 SIVAL(p,0,reskey);
1021                                 p += 4;
1022                         }
1023                         put_dos_date2(p,l2_fdateCreation,cdate);
1024                         put_dos_date2(p,l2_fdateLastAccess,adate);
1025                         put_dos_date2(p,l2_fdateLastWrite,mdate);
1026                         SIVAL(p,l2_cbFile,(uint32)file_size);
1027                         SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1028                         SSVAL(p,l2_attrFile,mode);
1029                         {
1030                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1031                                 SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1032                         }
1033                         p += l2_achName;
1034                         nameptr = p - 1;
1035                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1036                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1037                                 if (len > 2) {
1038                                         len -= 2;
1039                                 } else {
1040                                         len = 0;
1041                                 }
1042                         } else {
1043                                 if (len > 1) {
1044                                         len -= 1;
1045                                 } else {
1046                                         len = 0;
1047                                 }
1048                         }
1049                         SCVAL(nameptr,0,len);
1050                         p += len;
1051                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1052                         break;
1053
1054 #if 0
1055                 case SMB_FIND_EA_LIST:
1056                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1057                         if(requires_resume_key) {
1058                                 SIVAL(p,0,reskey);
1059                                 p += 4;
1060                         }
1061 #endif
1062
1063                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1064                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1065                         was_8_3 = mangle_is_8_3(fname, True);
1066                         p += 4;
1067                         SIVAL(p,0,reskey); p += 4;
1068                         put_long_date(p,cdate); p += 8;
1069                         put_long_date(p,adate); p += 8;
1070                         put_long_date(p,mdate); p += 8;
1071                         put_long_date(p,mdate); p += 8;
1072                         SOFF_T(p,0,file_size); p += 8;
1073                         SOFF_T(p,0,allocation_size); p += 8;
1074                         SIVAL(p,0,nt_extmode); p += 4;
1075                         q = p; p += 4; /* q is placeholder for name length. */
1076                         {
1077                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1078                                 SIVAL(p,0,ea_size); /* Extended attributes */
1079                                 p += 4;
1080                         }
1081                         /* Clear the short name buffer. This is
1082                          * IMPORTANT as not doing so will trigger
1083                          * a Win2k client bug. JRA.
1084                          */
1085                         memset(p,'\0',26);
1086                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1087                                 pstring mangled_name;
1088                                 pstrcpy(mangled_name, fname);
1089                                 mangle_map(mangled_name,True,True,SNUM(conn));
1090                                 mangled_name[12] = 0;
1091                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1092                                 SSVAL(p, 0, len);
1093                         } else {
1094                                 SSVAL(p,0,0);
1095                                 *(p+2) = 0;
1096                         }
1097                         p += 2 + 24;
1098                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1099                         SIVAL(q,0,len);
1100                         p += len;
1101                         len = PTR_DIFF(p, pdata);
1102                         len = (len + 3) & ~3;
1103                         SIVAL(pdata,0,len);
1104                         p = pdata + len;
1105                         break;
1106
1107                 case SMB_FIND_FILE_DIRECTORY_INFO:
1108                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1109                         p += 4;
1110                         SIVAL(p,0,reskey); p += 4;
1111                         put_long_date(p,cdate); p += 8;
1112                         put_long_date(p,adate); p += 8;
1113                         put_long_date(p,mdate); p += 8;
1114                         put_long_date(p,mdate); p += 8;
1115                         SOFF_T(p,0,file_size); p += 8;
1116                         SOFF_T(p,0,allocation_size); p += 8;
1117                         SIVAL(p,0,nt_extmode); p += 4;
1118                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1119                         SIVAL(p,0,len);
1120                         p += 4 + len;
1121                         len = PTR_DIFF(p, pdata);
1122                         len = (len + 3) & ~3;
1123                         SIVAL(pdata,0,len);
1124                         p = pdata + len;
1125                         break;
1126       
1127                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1128                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1129                         p += 4;
1130                         SIVAL(p,0,reskey); p += 4;
1131                         put_long_date(p,cdate); p += 8;
1132                         put_long_date(p,adate); p += 8;
1133                         put_long_date(p,mdate); p += 8;
1134                         put_long_date(p,mdate); p += 8;
1135                         SOFF_T(p,0,file_size); p += 8;
1136                         SOFF_T(p,0,allocation_size); p += 8;
1137                         SIVAL(p,0,nt_extmode); p += 4;
1138                         q = p; p += 4; /* q is placeholder for name length. */
1139                         {
1140                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1141                                 SIVAL(p,0,ea_size); /* Extended attributes */
1142                                 p +=4;
1143                         }
1144                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1145                         SIVAL(q, 0, len);
1146                         p += len;
1147
1148                         len = PTR_DIFF(p, pdata);
1149                         len = (len + 3) & ~3;
1150                         SIVAL(pdata,0,len);
1151                         p = pdata + len;
1152                         break;
1153
1154                 case SMB_FIND_FILE_NAMES_INFO:
1155                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1156                         p += 4;
1157                         SIVAL(p,0,reskey); p += 4;
1158                         p += 4;
1159                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1160                            acl on a dir (tridge) */
1161                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1162                         SIVAL(p, -4, len);
1163                         p += len;
1164                         len = PTR_DIFF(p, pdata);
1165                         len = (len + 3) & ~3;
1166                         SIVAL(pdata,0,len);
1167                         p = pdata + len;
1168                         break;
1169
1170                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1171                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1172                         p += 4;
1173                         SIVAL(p,0,reskey); p += 4;
1174                         put_long_date(p,cdate); p += 8;
1175                         put_long_date(p,adate); p += 8;
1176                         put_long_date(p,mdate); p += 8;
1177                         put_long_date(p,mdate); p += 8;
1178                         SOFF_T(p,0,file_size); p += 8;
1179                         SOFF_T(p,0,allocation_size); p += 8;
1180                         SIVAL(p,0,nt_extmode); p += 4;
1181                         q = p; p += 4; /* q is placeholder for name length. */
1182                         {
1183                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1184                                 SIVAL(p,0,ea_size); /* Extended attributes */
1185                                 p +=4;
1186                         }
1187                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1188                         SIVAL(p,0,sbuf.st_dev); p += 4;
1189                         SIVAL(p,0,sbuf.st_ino); p += 4;
1190                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1191                         SIVAL(q, 0, len);
1192                         p += len; 
1193                         len = PTR_DIFF(p, pdata);
1194                         len = (len + 3) & ~3;
1195                         SIVAL(pdata,0,len);
1196                         p = pdata + len;
1197                         break;
1198
1199                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1200                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1201                         was_8_3 = mangle_is_8_3(fname, True);
1202                         p += 4;
1203                         SIVAL(p,0,reskey); p += 4;
1204                         put_long_date(p,cdate); p += 8;
1205                         put_long_date(p,adate); p += 8;
1206                         put_long_date(p,mdate); p += 8;
1207                         put_long_date(p,mdate); p += 8;
1208                         SOFF_T(p,0,file_size); p += 8;
1209                         SOFF_T(p,0,allocation_size); p += 8;
1210                         SIVAL(p,0,nt_extmode); p += 4;
1211                         q = p; p += 4; /* q is placeholder for name length */
1212                         {
1213                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1214                                 SIVAL(p,0,ea_size); /* Extended attributes */
1215                                 p +=4;
1216                         }
1217                         /* Clear the short name buffer. This is
1218                          * IMPORTANT as not doing so will trigger
1219                          * a Win2k client bug. JRA.
1220                          */
1221                         memset(p,'\0',26);
1222                         if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1223                                 pstring mangled_name;
1224                                 pstrcpy(mangled_name, fname);
1225                                 mangle_map(mangled_name,True,True,SNUM(conn));
1226                                 mangled_name[12] = 0;
1227                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1228                                 SSVAL(p, 0, len);
1229                         } else {
1230                                 SSVAL(p,0,0);
1231                                 *(p+2) = 0;
1232                         }
1233                         p += 26;
1234                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1235                         SIVAL(p,0,sbuf.st_dev); p += 4;
1236                         SIVAL(p,0,sbuf.st_ino); p += 4;
1237                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1238                         SIVAL(q,0,len);
1239                         p += len;
1240                         len = PTR_DIFF(p, pdata);
1241                         len = (len + 3) & ~3;
1242                         SIVAL(pdata,0,len);
1243                         p = pdata + len;
1244                         break;
1245
1246                 /* CIFS UNIX Extension. */
1247
1248                 case SMB_FIND_FILE_UNIX:
1249                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1250                         p+= 4;
1251                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1252
1253                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1254                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1255                         p+= 8;
1256
1257                         SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1258                         p+= 8;
1259
1260                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1261                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1262                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1263                         p+= 24;
1264
1265                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1266                         SIVAL(p,4,0);
1267                         p+= 8;
1268
1269                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1270                         SIVAL(p,4,0);
1271                         p+= 8;
1272
1273                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1274                         p+= 4;
1275
1276                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1277                         SIVAL(p,4,0);
1278                         p+= 8;
1279
1280                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1281                         SIVAL(p,4,0);
1282                         p+= 8;
1283
1284                         SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1285                         p+= 8;
1286
1287                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1288                         SIVAL(p,4,0);
1289                         p+= 8;
1290
1291                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1292                         SIVAL(p,4,0);
1293                         p+= 8;
1294
1295                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1296                         p += len;
1297
1298                         len = PTR_DIFF(p, pdata);
1299                         len = (len + 3) & ~3;
1300                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1301                         p = pdata + len;
1302                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1303
1304                         break;
1305
1306                 default:      
1307                         return(False);
1308         }
1309
1310
1311         if (PTR_DIFF(p,pdata) > space_remaining) {
1312                 /* Move the dirptr back to prev_dirpos */
1313                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1314                 *out_of_space = True;
1315                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1316                 return False; /* Not finished - just out of space */
1317         }
1318
1319         /* Setup the last entry pointer, as an offset from base_data */
1320         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1321         /* Advance the data pointer to the next slot */
1322         *ppdata = p;
1323
1324         return(found);
1325 }
1326
1327 /****************************************************************************
1328  Reply to a TRANS2_FINDFIRST.
1329 ****************************************************************************/
1330
1331 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1332                                 char **pparams, int total_params, char **ppdata, int total_data,
1333                                 unsigned int max_data_bytes)
1334 {
1335         /* We must be careful here that we don't return more than the
1336                 allowed number of data bytes. If this means returning fewer than
1337                 maxentries then so be it. We assume that the redirector has
1338                 enough room for the fixed number of parameter bytes it has
1339                 requested. */
1340         char *params = *pparams;
1341         char *pdata = *ppdata;
1342         int dirtype = SVAL(params,0);
1343         int maxentries = SVAL(params,2);
1344         uint16 findfirst_flags = SVAL(params,4);
1345         BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1346         BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1347         BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1348         int info_level = SVAL(params,6);
1349         pstring directory;
1350         pstring mask;
1351         char *p;
1352         int last_entry_off=0;
1353         int dptr_num = -1;
1354         int numentries = 0;
1355         int i;
1356         BOOL finished = False;
1357         BOOL dont_descend = False;
1358         BOOL out_of_space = False;
1359         int space_remaining;
1360         BOOL bad_path = False;
1361         SMB_STRUCT_STAT sbuf;
1362         NTSTATUS ntstatus = NT_STATUS_OK;
1363
1364         if (total_params < 12)
1365                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1366
1367         *directory = *mask = 0;
1368
1369         DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1370 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1371                 dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1372                 info_level, max_data_bytes));
1373
1374         if (!maxentries) {
1375                 /* W2K3 seems to treat zero as 1. */
1376                 maxentries = 1;
1377         }
1378  
1379         switch (info_level) {
1380                 case SMB_FIND_INFO_STANDARD:
1381                 case SMB_FIND_EA_SIZE:
1382                 case SMB_FIND_FILE_DIRECTORY_INFO:
1383                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1384                 case SMB_FIND_FILE_NAMES_INFO:
1385                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1386                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1387                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1388                         break;
1389                 case SMB_FIND_FILE_UNIX:
1390                         if (!lp_unix_extensions())
1391                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1392                         break;
1393                 default:
1394                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1395         }
1396
1397         srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1398         if (!NT_STATUS_IS_OK(ntstatus)) {
1399                 return ERROR_NT(ntstatus);
1400         }
1401
1402         RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1403
1404         unix_convert(directory,conn,0,&bad_path,&sbuf);
1405         if (bad_path) {
1406                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1407         }
1408         if(!check_name(directory,conn)) {
1409                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1410         }
1411
1412         p = strrchr_m(directory,'/');
1413         if(p == NULL) {
1414                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1415                 if((directory[0] == '.') && (directory[1] == '\0'))
1416                         pstrcpy(mask,"*");
1417                 else
1418                         pstrcpy(mask,directory);
1419                 pstrcpy(directory,"./");
1420         } else {
1421                 pstrcpy(mask,p+1);
1422                 *p = 0;
1423         }
1424
1425         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1426
1427         pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1428         if( pdata == NULL )
1429                 return(ERROR_DOS(ERRDOS,ERRnomem));
1430
1431         *ppdata = pdata;
1432         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1433
1434         /* Realloc the params space */
1435         params = SMB_REALLOC(*pparams, 10);
1436         if (params == NULL)
1437                 return ERROR_DOS(ERRDOS,ERRnomem);
1438         *pparams = params;
1439
1440         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1441         if (dptr_num < 0)
1442                 return(UNIXERROR(ERRDOS,ERRbadfile));
1443
1444         /* Save the wildcard match and attribs we are using on this directory - 
1445                 needed as lanman2 assumes these are being saved between calls */
1446
1447         if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1448                 dptr_close(&dptr_num);
1449                 return ERROR_DOS(ERRDOS,ERRnomem);
1450         }
1451
1452         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1453
1454         /* We don't need to check for VOL here as this is returned by 
1455                 a different TRANS2 call. */
1456   
1457         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1458         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1459                 dont_descend = True;
1460     
1461         p = pdata;
1462         space_remaining = max_data_bytes;
1463         out_of_space = False;
1464
1465         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1466                 BOOL got_exact_match = False;
1467
1468                 /* this is a heuristic to avoid seeking the dirptr except when 
1469                         absolutely necessary. It allows for a filename of about 40 chars */
1470                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1471                         out_of_space = True;
1472                         finished = False;
1473                 } else {
1474                         finished = !get_lanman2_dir_entry(conn,
1475                                         inbuf, outbuf,
1476                                         mask,dirtype,info_level,
1477                                         requires_resume_key,dont_descend,
1478                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1479                                         &last_entry_off);
1480                 }
1481
1482                 if (finished && out_of_space)
1483                         finished = False;
1484
1485                 if (!finished && !out_of_space)
1486                         numentries++;
1487
1488                 /*
1489                  * As an optimisation if we know we aren't looking
1490                  * for a wildcard name (ie. the name matches the wildcard exactly)
1491                  * then we can finish on any (first) match.
1492                  * This speeds up large directory searches. JRA.
1493                  */
1494
1495                 if(got_exact_match)
1496                         finished = True;
1497
1498                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1499         }
1500   
1501         /* Check if we can close the dirptr */
1502         if(close_after_first || (finished && close_if_end)) {
1503                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1504                 dptr_close(&dptr_num);
1505         }
1506
1507         /* 
1508          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1509          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1510          * the protocol level is less than NT1. Tested with smbclient. JRA.
1511          * This should fix the OS/2 client bug #2335.
1512          */
1513
1514         if(numentries == 0) {
1515                 dptr_close(&dptr_num);
1516                 if (Protocol < PROTOCOL_NT1) {
1517                         return ERROR_DOS(ERRDOS,ERRnofiles);
1518                 } else {
1519                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1520                 }
1521         }
1522
1523         /* At this point pdata points to numentries directory entries. */
1524
1525         /* Set up the return parameter block */
1526         SSVAL(params,0,dptr_num);
1527         SSVAL(params,2,numentries);
1528         SSVAL(params,4,finished);
1529         SSVAL(params,6,0); /* Never an EA error */
1530         SSVAL(params,8,last_entry_off);
1531
1532         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1533
1534         if ((! *directory) && dptr_path(dptr_num))
1535                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1536
1537         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1538                 smb_fn_name(CVAL(inbuf,smb_com)), 
1539                 mask, directory, dirtype, numentries ) );
1540
1541         /* 
1542          * Force a name mangle here to ensure that the
1543          * mask as an 8.3 name is top of the mangled cache.
1544          * The reasons for this are subtle. Don't remove
1545          * this code unless you know what you are doing
1546          * (see PR#13758). JRA.
1547          */
1548
1549         if(!mangle_is_8_3_wildcards( mask, False))
1550                 mangle_map(mask, True, True, SNUM(conn));
1551
1552         return(-1);
1553 }
1554
1555 /****************************************************************************
1556  Reply to a TRANS2_FINDNEXT.
1557 ****************************************************************************/
1558
1559 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1560                                         char **pparams, int total_params, char **ppdata, int total_data,
1561                                         unsigned int max_data_bytes)
1562 {
1563         /* We must be careful here that we don't return more than the
1564                 allowed number of data bytes. If this means returning fewer than
1565                 maxentries then so be it. We assume that the redirector has
1566                 enough room for the fixed number of parameter bytes it has
1567                 requested. */
1568         char *params = *pparams;
1569         char *pdata = *ppdata;
1570         int dptr_num = SVAL(params,0);
1571         int maxentries = SVAL(params,2);
1572         uint16 info_level = SVAL(params,4);
1573         uint32 resume_key = IVAL(params,6);
1574         uint16 findnext_flags = SVAL(params,10);
1575         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1576         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1577         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1578         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1579         pstring resume_name;
1580         pstring mask;
1581         pstring directory;
1582         char *p;
1583         uint16 dirtype;
1584         int numentries = 0;
1585         int i, last_entry_off=0;
1586         BOOL finished = False;
1587         BOOL dont_descend = False;
1588         BOOL out_of_space = False;
1589         int space_remaining;
1590         NTSTATUS ntstatus = NT_STATUS_OK;
1591
1592         if (total_params < 12)
1593                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1594
1595         *mask = *directory = *resume_name = 0;
1596
1597         srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1598         if (!NT_STATUS_IS_OK(ntstatus)) {
1599                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1600                    complain (it thinks we're asking for the directory above the shared
1601                    path or an invalid name). Catch this as the resume name is only compared, never used in
1602                    a file access. JRA. */
1603                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1604                         pstrcpy(resume_name, "..");
1605                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1606                         pstrcpy(resume_name, ".");
1607                 } else {
1608                         return ERROR_NT(ntstatus);
1609                 }
1610         }
1611
1612         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1613 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1614 resume_key = %d resume name = %s continue=%d level = %d\n",
1615                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1616                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1617
1618         if (!maxentries) {
1619                 /* W2K3 seems to treat zero as 1. */
1620                 maxentries = 1;
1621         }
1622
1623         switch (info_level) {
1624                 case SMB_FIND_INFO_STANDARD:
1625                 case SMB_FIND_EA_SIZE:
1626                 case SMB_FIND_FILE_DIRECTORY_INFO:
1627                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1628                 case SMB_FIND_FILE_NAMES_INFO:
1629                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1630                         break;
1631                 case SMB_FIND_FILE_UNIX:
1632                         if (!lp_unix_extensions())
1633                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1634                         break;
1635                 default:
1636                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1637         }
1638
1639         pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1640         if(pdata == NULL)
1641                 return ERROR_DOS(ERRDOS,ERRnomem);
1642
1643         *ppdata = pdata;
1644         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1645
1646         /* Realloc the params space */
1647         params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1648         if( params == NULL )
1649                 return ERROR_DOS(ERRDOS,ERRnomem);
1650
1651         *pparams = params;
1652
1653         /* Check that the dptr is valid */
1654         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1655                 return ERROR_DOS(ERRDOS,ERRnofiles);
1656
1657         string_set(&conn->dirpath,dptr_path(dptr_num));
1658
1659         /* Get the wildcard mask from the dptr */
1660         if((p = dptr_wcard(dptr_num))== NULL) {
1661                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1662                 return ERROR_DOS(ERRDOS,ERRnofiles);
1663         }
1664
1665         pstrcpy(mask, p);
1666         pstrcpy(directory,conn->dirpath);
1667
1668         /* Get the attr mask from the dptr */
1669         dirtype = dptr_attr(dptr_num);
1670
1671         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1672                 dptr_num, mask, dirtype, 
1673                 (long)conn->dirptr,
1674                 dptr_TellDir(conn->dirptr)));
1675
1676         /* We don't need to check for VOL here as this is returned by 
1677                 a different TRANS2 call. */
1678
1679         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1680         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1681                 dont_descend = True;
1682     
1683         p = pdata;
1684         space_remaining = max_data_bytes;
1685         out_of_space = False;
1686
1687         /* 
1688          * Seek to the correct position. We no longer use the resume key but
1689          * depend on the last file name instead.
1690          */
1691
1692         if(*resume_name && !continue_bit) {
1693                 SMB_STRUCT_STAT st;
1694
1695                 long current_pos = 0;
1696                 /*
1697                  * Remember, mangle_map is called by
1698                  * get_lanman2_dir_entry(), so the resume name
1699                  * could be mangled. Ensure we check the unmangled name.
1700                  */
1701
1702                 if (mangle_is_mangled(resume_name)) {
1703                         mangle_check_cache(resume_name, sizeof(resume_name)-1);
1704                 }
1705
1706                 /*
1707                  * Fix for NT redirector problem triggered by resume key indexes
1708                  * changing between directory scans. We now return a resume key of 0
1709                  * and instead look for the filename to continue from (also given
1710                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1711                  * findfirst/findnext (as is usual) then the directory pointer
1712                  * should already be at the correct place.
1713                  */
1714
1715                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1716         } /* end if resume_name && !continue_bit */
1717
1718         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1719                 BOOL got_exact_match = False;
1720
1721                 /* this is a heuristic to avoid seeking the dirptr except when 
1722                         absolutely necessary. It allows for a filename of about 40 chars */
1723                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1724                         out_of_space = True;
1725                         finished = False;
1726                 } else {
1727                         finished = !get_lanman2_dir_entry(conn,
1728                                                 inbuf, outbuf,
1729                                                 mask,dirtype,info_level,
1730                                                 requires_resume_key,dont_descend,
1731                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1732                                                 &last_entry_off);
1733                 }
1734
1735                 if (finished && out_of_space)
1736                         finished = False;
1737
1738                 if (!finished && !out_of_space)
1739                         numentries++;
1740
1741                 /*
1742                  * As an optimisation if we know we aren't looking
1743                  * for a wildcard name (ie. the name matches the wildcard exactly)
1744                  * then we can finish on any (first) match.
1745                  * This speeds up large directory searches. JRA.
1746                  */
1747
1748                 if(got_exact_match)
1749                         finished = True;
1750
1751                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1752         }
1753   
1754         /* Check if we can close the dirptr */
1755         if(close_after_request || (finished && close_if_end)) {
1756                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1757                 dptr_close(&dptr_num); /* This frees up the saved mask */
1758         }
1759
1760         /* Set up the return parameter block */
1761         SSVAL(params,0,numentries);
1762         SSVAL(params,2,finished);
1763         SSVAL(params,4,0); /* Never an EA error */
1764         SSVAL(params,6,last_entry_off);
1765
1766         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1767
1768         if ((! *directory) && dptr_path(dptr_num))
1769                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1770
1771         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1772                 smb_fn_name(CVAL(inbuf,smb_com)), 
1773                 mask, directory, dirtype, numentries ) );
1774
1775         return(-1);
1776 }
1777
1778 /****************************************************************************
1779  Reply to a TRANS2_QFSINFO (query filesystem info).
1780 ****************************************************************************/
1781
1782 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1783                                         char **pparams, int total_params, char **ppdata, int total_data,
1784                                         unsigned int max_data_bytes)
1785 {
1786         char *pdata = *ppdata;
1787         char *params = *pparams;
1788         uint16 info_level = SVAL(params,0);
1789         int data_len, len;
1790         SMB_STRUCT_STAT st;
1791         char *vname = volume_label(SNUM(conn));
1792         int snum = SNUM(conn);
1793         char *fstype = lp_fstype(SNUM(conn));
1794         int quota_flag = 0;
1795
1796         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1797
1798         if(SMB_VFS_STAT(conn,".",&st)!=0) {
1799                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1800                 return ERROR_DOS(ERRSRV,ERRinvdevice);
1801         }
1802
1803         pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1804         if ( pdata == NULL )
1805                 return ERROR_DOS(ERRDOS,ERRnomem);
1806
1807         *ppdata = pdata;
1808         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1809
1810         switch (info_level) {
1811                 case SMB_INFO_ALLOCATION:
1812                 {
1813                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1814                         data_len = 18;
1815                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1816                                 return(UNIXERROR(ERRHRD,ERRgeneral));
1817                         }
1818
1819                         block_size = lp_block_size(snum);
1820                         if (bsize < block_size) {
1821                                 SMB_BIG_UINT factor = block_size/bsize;
1822                                 bsize = block_size;
1823                                 dsize /= factor;
1824                                 dfree /= factor;
1825                         }
1826                         if (bsize > block_size) {
1827                                 SMB_BIG_UINT factor = bsize/block_size;
1828                                 bsize = block_size;
1829                                 dsize *= factor;
1830                                 dfree *= factor;
1831                         }
1832                         bytes_per_sector = 512;
1833                         sectors_per_unit = bsize/bytes_per_sector;
1834
1835                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1836 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1837                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1838
1839                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
1840                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1841                         SIVAL(pdata,l1_cUnit,dsize);
1842                         SIVAL(pdata,l1_cUnitAvail,dfree);
1843                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
1844                         break;
1845                 }
1846
1847                 case SMB_INFO_VOLUME:
1848                         /* Return volume name */
1849                         /* 
1850                          * Add volume serial number - hash of a combination of
1851                          * the called hostname and the service name.
1852                          */
1853                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1854                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1855                         SCVAL(pdata,l2_vol_cch,len);
1856                         data_len = l2_vol_szVolLabel + len;
1857                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1858                                 (unsigned)st.st_ctime, len, vname));
1859                         break;
1860
1861                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
1862                 case SMB_FS_ATTRIBUTE_INFORMATION:
1863
1864
1865 #if defined(HAVE_SYS_QUOTAS)
1866                         quota_flag = FILE_VOLUME_QUOTAS;
1867 #endif
1868
1869                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1870                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1871                                 quota_flag); /* FS ATTRIBUTES */
1872
1873                         SIVAL(pdata,4,255); /* Max filename component length */
1874                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1875                                 and will think we can't do long filenames */
1876                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1877                         SIVAL(pdata,8,len);
1878                         data_len = 12 + len;
1879                         break;
1880
1881                 case SMB_QUERY_FS_LABEL_INFO:
1882                 case SMB_FS_LABEL_INFORMATION:
1883                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1884                         data_len = 4 + len;
1885                         SIVAL(pdata,0,len);
1886                         break;
1887
1888                 case SMB_QUERY_FS_VOLUME_INFO:      
1889                 case SMB_FS_VOLUME_INFORMATION:
1890
1891                         /* 
1892                          * Add volume serial number - hash of a combination of
1893                          * the called hostname and the service name.
1894                          */
1895                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
1896                                 (str_checksum(get_local_machine_name())<<16));
1897
1898                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1899                         SIVAL(pdata,12,len);
1900                         data_len = 18+len;
1901                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
1902                                 (int)strlen(vname),vname, lp_servicename(snum)));
1903                         break;
1904
1905                 case SMB_QUERY_FS_SIZE_INFO:
1906                 case SMB_FS_SIZE_INFORMATION:
1907                 {
1908                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1909                         data_len = 24;
1910                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1911                                 return(UNIXERROR(ERRHRD,ERRgeneral));
1912                         }
1913                         block_size = lp_block_size(snum);
1914                         if (bsize < block_size) {
1915                                 SMB_BIG_UINT factor = block_size/bsize;
1916                                 bsize = block_size;
1917                                 dsize /= factor;
1918                                 dfree /= factor;
1919                         }
1920                         if (bsize > block_size) {
1921                                 SMB_BIG_UINT factor = bsize/block_size;
1922                                 bsize = block_size;
1923                                 dsize *= factor;
1924                                 dfree *= factor;
1925                         }
1926                         bytes_per_sector = 512;
1927                         sectors_per_unit = bsize/bytes_per_sector;
1928                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1929 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1930                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1931                         SBIG_UINT(pdata,0,dsize);
1932                         SBIG_UINT(pdata,8,dfree);
1933                         SIVAL(pdata,16,sectors_per_unit);
1934                         SIVAL(pdata,20,bytes_per_sector);
1935                         break;
1936                 }
1937
1938                 case SMB_FS_FULL_SIZE_INFORMATION:
1939                 {
1940                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1941                         data_len = 32;
1942                         if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1943                                 return(UNIXERROR(ERRHRD,ERRgeneral));
1944                         }
1945                         block_size = lp_block_size(snum);
1946                         if (bsize < block_size) {
1947                                 SMB_BIG_UINT factor = block_size/bsize;
1948                                 bsize = block_size;
1949                                 dsize /= factor;
1950                                 dfree /= factor;
1951                         }
1952                         if (bsize > block_size) {
1953                                 SMB_BIG_UINT factor = bsize/block_size;
1954                                 bsize = block_size;
1955                                 dsize *= factor;
1956                                 dfree *= factor;
1957                         }
1958                         bytes_per_sector = 512;
1959                         sectors_per_unit = bsize/bytes_per_sector;
1960                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1962                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1963                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
1964                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
1965                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
1966                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
1967                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
1968                         break;
1969                 }
1970
1971                 case SMB_QUERY_FS_DEVICE_INFO:
1972                 case SMB_FS_DEVICE_INFORMATION:
1973                         data_len = 8;
1974                         SIVAL(pdata,0,0); /* dev type */
1975                         SIVAL(pdata,4,0); /* characteristics */
1976                         break;
1977
1978 #ifdef HAVE_SYS_QUOTAS
1979                 case SMB_FS_QUOTA_INFORMATION:
1980                 /* 
1981                  * what we have to send --metze:
1982                  *
1983                  * Unknown1:            24 NULL bytes
1984                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
1985                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
1986                  * Quota Flags:         2 byte :
1987                  * Unknown3:            6 NULL bytes
1988                  *
1989                  * 48 bytes total
1990                  * 
1991                  * details for Quota Flags:
1992                  * 
1993                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
1994                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
1995                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
1996                  * 0x0001 Enable Quotas: enable quota for this fs
1997                  *
1998                  */
1999                 {
2000                         /* we need to fake up a fsp here,
2001                          * because its not send in this call
2002                          */
2003                         files_struct fsp;
2004                         SMB_NTQUOTA_STRUCT quotas;
2005                         
2006                         ZERO_STRUCT(fsp);
2007                         ZERO_STRUCT(quotas);
2008                         
2009                         fsp.conn = conn;
2010                         fsp.fnum = -1;
2011                         fsp.fd = -1;
2012                         
2013                         /* access check */
2014                         if (current_user.uid != 0) {
2015                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2016                                         lp_servicename(SNUM(conn)),conn->user));
2017                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2018                         }
2019                         
2020                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2021                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2022                                 return ERROR_DOS(ERRSRV,ERRerror);
2023                         }
2024
2025                         data_len = 48;
2026
2027                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2028                 
2029                         /* Unknown1 24 NULL bytes*/
2030                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2031                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2032                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2033                 
2034                         /* Default Soft Quota 8 bytes */
2035                         SBIG_UINT(pdata,24,quotas.softlim);
2036
2037                         /* Default Hard Quota 8 bytes */
2038                         SBIG_UINT(pdata,32,quotas.hardlim);
2039         
2040                         /* Quota flag 2 bytes */
2041                         SSVAL(pdata,40,quotas.qflags);
2042                 
2043                         /* Unknown3 6 NULL bytes */
2044                         SSVAL(pdata,42,0);
2045                         SIVAL(pdata,44,0);
2046                         
2047                         break;
2048                 }
2049 #endif /* HAVE_SYS_QUOTAS */
2050                 case SMB_FS_OBJECTID_INFORMATION:
2051                         data_len = 64;
2052                         break;
2053
2054                 /*
2055                  * Query the version and capabilities of the CIFS UNIX extensions
2056                  * in use.
2057                  */
2058
2059                 case SMB_QUERY_CIFS_UNIX_INFO:
2060                         if (!lp_unix_extensions())
2061                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2062                         data_len = 12;
2063                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2064                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2065                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2066                         break;
2067
2068                 case SMB_MAC_QUERY_FS_INFO:
2069                         /*
2070                          * Thursby MAC extension... ONLY on NTFS filesystems
2071                          * once we do streams then we don't need this
2072                          */
2073                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2074                                 data_len = 88;
2075                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2076                                 break;
2077                         }
2078                         /* drop through */
2079                 default:
2080                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2081         }
2082
2083
2084         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2085
2086         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2087
2088         return -1;
2089 }
2090
2091 #ifdef HAVE_SYS_QUOTAS
2092 /****************************************************************************
2093  Reply to a TRANS2_SETFSINFO (set filesystem info).
2094 ****************************************************************************/
2095
2096 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2097                                         char **pparams, int total_params, char **ppdata, int total_data,
2098                                         unsigned int max_data_bytes)
2099 {
2100         char *pdata = *ppdata;
2101         char *params = *pparams;
2102         files_struct *fsp = NULL;
2103         uint16 info_level;
2104         int outsize;
2105         SMB_NTQUOTA_STRUCT quotas;
2106         
2107         ZERO_STRUCT(quotas);
2108
2109         DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2110
2111         /* access check */
2112         if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2113                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2114                         lp_servicename(SNUM(conn)),conn->user));
2115                 return ERROR_DOS(ERRSRV,ERRaccess);
2116         }
2117
2118         /*  */
2119         if (total_params < 4) {
2120                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2121                         total_params));
2122                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
2123         }
2124
2125         fsp = file_fsp(params,0);
2126
2127         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2128                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2129                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2130         }
2131
2132         info_level = SVAL(params,2);
2133
2134         switch(info_level) {
2135                 case SMB_FS_QUOTA_INFORMATION:
2136                         /* note: normaly there're 48 bytes,
2137                          * but we didn't use the last 6 bytes for now 
2138                          * --metze 
2139                          */
2140                         if (total_data < 42) {
2141                                 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2142                                         total_data));
2143                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2144                         }
2145                         
2146                         /* unknown_1 24 NULL bytes in pdata*/
2147                 
2148                         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2149                         quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2150 #ifdef LARGE_SMB_OFF_T
2151                         quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2152 #else /* LARGE_SMB_OFF_T */
2153                         if ((IVAL(pdata,28) != 0)&&
2154                                 ((quotas.softlim != 0xFFFFFFFF)||
2155                                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
2156                                 /* more than 32 bits? */
2157                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2158                         }
2159 #endif /* LARGE_SMB_OFF_T */
2160                 
2161                         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2162                         quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2163 #ifdef LARGE_SMB_OFF_T
2164                         quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2165 #else /* LARGE_SMB_OFF_T */
2166                         if ((IVAL(pdata,36) != 0)&&
2167                                 ((quotas.hardlim != 0xFFFFFFFF)||
2168                                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
2169                                 /* more than 32 bits? */
2170                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2171                         }
2172 #endif /* LARGE_SMB_OFF_T */
2173                 
2174                         /* quota_flags 2 bytes **/
2175                         quotas.qflags = SVAL(pdata,40);
2176                 
2177                         /* unknown_2 6 NULL bytes follow*/
2178                 
2179                         /* now set the quotas */
2180                         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2181                                 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2182                                 return ERROR_DOS(ERRSRV,ERRerror);
2183                         }
2184                         
2185                         break;
2186                 default:
2187                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2188                                 info_level));
2189                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2190                         break;
2191         }
2192
2193         /* 
2194          * sending this reply works fine, 
2195          * but I'm not sure it's the same 
2196          * like windows do...
2197          * --metze
2198          */ 
2199         outsize = set_message(outbuf,10,0,True);
2200
2201         return outsize;
2202 }
2203 #endif /* HAVE_SYS_QUOTAS */
2204
2205 /****************************************************************************
2206  Utility function to set bad path error.
2207 ****************************************************************************/
2208
2209 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2210 {
2211         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2212                         err, (int)bad_path ));
2213
2214         if(err == ENOENT) {
2215                 if (bad_path) {
2216                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2217                 } else {
2218                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2219                 }
2220         }
2221         return UNIXERROR(def_class,def_code);
2222 }
2223
2224 #if defined(HAVE_POSIX_ACLS)
2225 /****************************************************************************
2226  Utility function to count the number of entries in a POSIX acl.
2227 ****************************************************************************/
2228
2229 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2230 {
2231         unsigned int ace_count = 0;
2232         int entry_id = SMB_ACL_FIRST_ENTRY;
2233         SMB_ACL_ENTRY_T entry;
2234
2235         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2236                 /* get_next... */
2237                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2238                         entry_id = SMB_ACL_NEXT_ENTRY;
2239                 }
2240                 ace_count++;
2241         }
2242         return ace_count;
2243 }
2244
2245 /****************************************************************************
2246  Utility function to marshall a POSIX acl into wire format.
2247 ****************************************************************************/
2248
2249 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2250 {
2251         int entry_id = SMB_ACL_FIRST_ENTRY;
2252         SMB_ACL_ENTRY_T entry;
2253
2254         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2255                 SMB_ACL_TAG_T tagtype;
2256                 SMB_ACL_PERMSET_T permset;
2257                 unsigned char perms = 0;
2258                 unsigned int own_grp;
2259
2260                 /* get_next... */
2261                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2262                         entry_id = SMB_ACL_NEXT_ENTRY;
2263                 }
2264
2265                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2266                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2267                         return False;
2268                 }
2269
2270                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2271                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2272                         return False;
2273                 }
2274
2275                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2276                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2277                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2278
2279                 SCVAL(pdata,1,perms);
2280
2281                 switch (tagtype) {
2282                         case SMB_ACL_USER_OBJ:
2283                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2284                                 own_grp = (unsigned int)pst->st_uid;
2285                                 SIVAL(pdata,2,own_grp);
2286                                 SIVAL(pdata,6,0);
2287                                 break;
2288                         case SMB_ACL_USER:
2289                                 {
2290                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2291                                         if (!puid) {
2292                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2293                                         }
2294                                         own_grp = (unsigned int)*puid;
2295                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2296                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2297                                         SIVAL(pdata,2,own_grp);
2298                                         SIVAL(pdata,6,0);
2299                                         break;
2300                                 }
2301                         case SMB_ACL_GROUP_OBJ:
2302                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2303                                 own_grp = (unsigned int)pst->st_gid;
2304                                 SIVAL(pdata,2,own_grp);
2305                                 SIVAL(pdata,6,0);
2306                                 break;
2307                         case SMB_ACL_GROUP:
2308                                 {
2309                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2310                                         if (!pgid) {
2311                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2312                                         }
2313                                         own_grp = (unsigned int)*pgid;
2314                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2315                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2316                                         SIVAL(pdata,2,own_grp);
2317                                         SIVAL(pdata,6,0);
2318                                         break;
2319                                 }
2320                         case SMB_ACL_MASK:
2321                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2322                                 SIVAL(pdata,2,0xFFFFFFFF);
2323                                 SIVAL(pdata,6,0xFFFFFFFF);
2324                                 break;
2325                         case SMB_ACL_OTHER:
2326                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2327                                 SIVAL(pdata,2,0xFFFFFFFF);
2328                                 SIVAL(pdata,6,0xFFFFFFFF);
2329                                 break;
2330                         default:
2331                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2332                                 return False;
2333                 }
2334                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2335         }
2336
2337         return True;
2338 }
2339 #endif
2340
2341 /****************************************************************************
2342  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2343  file name or file id).
2344 ****************************************************************************/
2345
2346 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2347                                         char **pparams, int total_params, char **ppdata, int total_data,
2348                                         unsigned int max_data_bytes)
2349 {
2350         char *params = *pparams;
2351         char *pdata = *ppdata;
2352         uint16 tran_call = SVAL(inbuf, smb_setup0);
2353         uint16 info_level;
2354         int mode=0;
2355         SMB_OFF_T file_size=0;
2356         SMB_BIG_UINT allocation_size=0;
2357         unsigned int data_size = 0;
2358         unsigned int param_size = 2;
2359         SMB_STRUCT_STAT sbuf;
2360         pstring fname, dos_fname;
2361         char *fullpathname;
2362         char *base_name;
2363         char *p;
2364         SMB_OFF_T pos = 0;
2365         BOOL bad_path = False;
2366         BOOL delete_pending = False;
2367         int len;
2368         time_t c_time;
2369         files_struct *fsp = NULL;
2370         TALLOC_CTX *ea_ctx = NULL;
2371         struct ea_list *ea_list = NULL;
2372         uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2373
2374         if (!params)
2375                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2376
2377         ZERO_STRUCT(sbuf);
2378
2379         if (tran_call == TRANSACT2_QFILEINFO) {
2380                 if (total_params < 4)
2381                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2382
2383                 fsp = file_fsp(params,0);
2384                 info_level = SVAL(params,2);
2385
2386                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2387
2388                 if(fsp && (fsp->fake_file_handle)) {
2389                         /*
2390                          * This is actually for the QUOTA_FAKE_FILE --metze
2391                          */
2392                                                 
2393                         pstrcpy(fname, fsp->fsp_name);
2394                         /* We know this name is ok, it's already passed the checks. */
2395                         
2396                 } else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2397                         /*
2398                          * This is actually a QFILEINFO on a directory
2399                          * handle (returned from an NT SMB). NT5.0 seems
2400                          * to do this call. JRA.
2401                          */
2402                         /* We know this name is ok, it's already passed the checks. */
2403                         pstrcpy(fname, fsp->fsp_name);
2404                   
2405                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2406                                 /* Always do lstat for UNIX calls. */
2407                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2408                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2409                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2410                                 }
2411                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2412                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2413                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2414                         }
2415
2416                         delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2417                 } else {
2418                         /*
2419                          * Original code - this is an open file.
2420                          */
2421                         CHECK_FSP(fsp,conn);
2422
2423                         pstrcpy(fname, fsp->fsp_name);
2424                         if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2425                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2426                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2427                         }
2428                         pos = fsp->position_information;
2429                         delete_pending = fsp->delete_on_close;
2430                         desired_access = fsp->desired_access;
2431                 }
2432         } else {
2433                 NTSTATUS status = NT_STATUS_OK;
2434
2435                 /* qpathinfo */
2436                 if (total_params < 6)
2437                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2438
2439                 info_level = SVAL(params,0);
2440
2441                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2442
2443                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2444                 if (!NT_STATUS_IS_OK(status)) {
2445                         return ERROR_NT(status);
2446                 }
2447
2448                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2449
2450                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2451                 if (bad_path) {
2452                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2453                 }
2454                 if (!check_name(fname,conn)) {
2455                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2456                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2457                 }
2458
2459                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2460                         /* Always do lstat for UNIX calls. */
2461                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2462                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2463                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2464                         }
2465                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2466                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2467                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2468                 }
2469         }
2470
2471         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2472                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2473
2474         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2475                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2476
2477         p = strrchr_m(fname,'/'); 
2478         if (!p)
2479                 base_name = fname;
2480         else
2481                 base_name = p+1;
2482
2483         mode = dos_mode(conn,fname,&sbuf);
2484         if (!mode)
2485                 mode = FILE_ATTRIBUTE_NORMAL;
2486
2487         fullpathname = fname;
2488         file_size = get_file_size(sbuf);
2489         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2490         if (mode & aDIR) {
2491                 /* This is necessary, as otherwise the desktop.ini file in
2492                  * this folder is ignored */
2493                 mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2494                 file_size = 0;
2495         }
2496
2497         /* Pull any EA list from the data portion. */
2498         if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2499                 uint32 ea_size = IVAL(pdata,0);
2500
2501                 if (total_data > 0 && ea_size != total_data) {
2502                         DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2503 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2504                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2505                 }
2506
2507                 if (!lp_ea_support(SNUM(conn))) {
2508                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2509                 }
2510
2511                 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2512                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2513                 }
2514
2515                 /* Pull out the list of names. */
2516                 ea_list = read_ea_list(ea_ctx, pdata, ea_size);
2517                 if (!ea_list) {
2518                         talloc_destroy(ea_ctx);
2519                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2520                 }
2521         }
2522
2523         params = SMB_REALLOC(*pparams,2);
2524         if (params == NULL) {
2525                 talloc_destroy(ea_ctx);
2526                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2527         }
2528         *pparams = params;
2529         memset((char *)params,'\0',2);
2530         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2531         pdata = SMB_REALLOC(*ppdata, data_size); 
2532         if ( pdata == NULL ) {
2533                 talloc_destroy(ea_ctx);
2534                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2535         }
2536         *ppdata = pdata;
2537
2538         memset((char *)pdata,'\0',data_size);
2539
2540         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2541
2542         if (fsp) {
2543                 if (fsp->pending_modtime) {
2544                         /* the pending modtime overrides the current modtime */
2545                         sbuf.st_mtime = fsp->pending_modtime;
2546                 }
2547         } else {
2548                 /* Do we have this path open ? */
2549                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2550                 if (fsp1 && fsp1->pending_modtime) {
2551                         /* the pending modtime overrides the current modtime */
2552                         sbuf.st_mtime = fsp1->pending_modtime;
2553                 }
2554         }
2555
2556         if (lp_dos_filetime_resolution(SNUM(conn))) {
2557                 c_time &= ~1;
2558                 sbuf.st_atime &= ~1;
2559                 sbuf.st_ctime &= ~1;
2560                 sbuf.st_mtime &= ~1;
2561         }
2562
2563         /* NT expects the name to be in an exact form of the *full*
2564            filename. See the trans2 torture test */
2565         if (strequal(base_name,".")) {
2566                 pstrcpy(dos_fname, "\\");
2567         } else {
2568                 pstr_sprintf(dos_fname, "\\%s", fname);
2569                 string_replace(dos_fname, '/', '\\');
2570         }
2571
2572         switch (info_level) {
2573                 case SMB_INFO_STANDARD:
2574                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2575                         data_size = 22;
2576                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2577                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2578                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2579                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2580                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2581                         SSVAL(pdata,l1_attrFile,mode);
2582                         break;
2583
2584                 case SMB_INFO_QUERY_EA_SIZE:
2585                 {
2586                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2587                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2588                         data_size = 26;
2589                         put_dos_date2(pdata,l1_fdateCreation,c_time);
2590                         put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2591                         put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2592                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
2593                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2594                         SSVAL(pdata,l1_attrFile,mode);
2595                         SIVAL(pdata,l1_attrFile+2,ea_size);
2596                         break;
2597                 }
2598
2599                 case SMB_INFO_IS_NAME_VALID:
2600                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2601                         if (tran_call == TRANSACT2_QFILEINFO) {
2602                                 /* os/2 needs this ? really ?*/      
2603                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
2604                         }
2605                         data_size = 0;
2606                         param_size = 0;
2607                         break;
2608                         
2609                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2610                 {
2611                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2612                         data_size = 24;
2613                         put_dos_date2(pdata,0,c_time);
2614                         put_dos_date2(pdata,4,sbuf.st_atime);
2615                         put_dos_date2(pdata,8,sbuf.st_mtime);
2616                         SIVAL(pdata,12,(uint32)file_size);
2617                         SIVAL(pdata,16,(uint32)allocation_size);
2618                         SIVAL(pdata,20,mode);
2619                         talloc_destroy(ea_ctx);
2620                         break;
2621                 }
2622
2623                 case SMB_INFO_QUERY_ALL_EAS:
2624                 {
2625                         /* We have data_size bytes to put EA's into. */
2626                         size_t total_ea_len = 0;
2627
2628                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2629
2630                         ea_ctx = talloc_init("ea_ctx");
2631                         if (!ea_ctx) {
2632                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2633                         }
2634
2635                         ea_list = get_ea_list(ea_ctx, conn, fsp, fname, &total_ea_len);
2636                         if (!ea_list || (total_ea_len > data_size)) {
2637                                 talloc_destroy(ea_ctx);
2638                                 data_size = 4;
2639                                 break;
2640                         }
2641
2642                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
2643                         talloc_destroy(ea_ctx);
2644                         break;
2645                 }
2646
2647                 case SMB_FILE_BASIC_INFORMATION:
2648                 case SMB_QUERY_FILE_BASIC_INFO:
2649
2650                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2651                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2652                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2653                         } else {
2654                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2655                                 data_size = 40;
2656                                 SIVAL(pdata,36,0);
2657                         }
2658                         put_long_date(pdata,c_time);
2659                         put_long_date(pdata+8,sbuf.st_atime);
2660                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2661                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2662                         SIVAL(pdata,32,mode);
2663
2664                         DEBUG(5,("SMB_QFBI - "));
2665                         {
2666                                 time_t create_time = c_time;
2667                                 DEBUG(5,("create: %s ", ctime(&create_time)));
2668                         }
2669                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2670                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2671                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2672                         DEBUG(5,("mode: %x\n", mode));
2673
2674                         break;
2675
2676                 case SMB_FILE_STANDARD_INFORMATION:
2677                 case SMB_QUERY_FILE_STANDARD_INFO:
2678
2679                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2680                         data_size = 24;
2681                         SOFF_T(pdata,0,allocation_size);
2682                         SOFF_T(pdata,8,file_size);
2683                         if (delete_pending & sbuf.st_nlink)
2684                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2685                         else
2686                                 SIVAL(pdata,16,sbuf.st_nlink);
2687                         SCVAL(pdata,20,0);
2688                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2689                         break;
2690
2691                 case SMB_FILE_EA_INFORMATION:
2692                 case SMB_QUERY_FILE_EA_INFO:
2693                 {
2694                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2695                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2696                         data_size = 4;
2697                         SIVAL(pdata,0,ea_size);
2698                         break;
2699                 }
2700
2701                 /* Get the 8.3 name - used if NT SMB was negotiated. */
2702                 case SMB_QUERY_FILE_ALT_NAME_INFO:
2703                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2704                 {
2705                         pstring short_name;
2706
2707                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2708                         pstrcpy(short_name,base_name);
2709                         /* Mangle if not already 8.3 */
2710                         if(!mangle_is_8_3(short_name, True)) {
2711                                 mangle_map(short_name,True,True,SNUM(conn));
2712                         }
2713                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2714                         data_size = 4 + len;
2715                         SIVAL(pdata,0,len);
2716                         break;
2717                 }
2718
2719                 case SMB_QUERY_FILE_NAME_INFO:
2720                         /*
2721                           this must be *exactly* right for ACLs on mapped drives to work
2722                          */
2723                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2724                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2725                         data_size = 4 + len;
2726                         SIVAL(pdata,0,len);
2727                         break;
2728
2729                 case SMB_FILE_ALLOCATION_INFORMATION:
2730                 case SMB_QUERY_FILE_ALLOCATION_INFO:
2731                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2732                         data_size = 8;
2733                         SOFF_T(pdata,0,allocation_size);
2734                         break;
2735
2736                 case SMB_FILE_END_OF_FILE_INFORMATION:
2737                 case SMB_QUERY_FILE_END_OF_FILEINFO:
2738                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2739                         data_size = 8;
2740                         SOFF_T(pdata,0,file_size);
2741                         break;
2742
2743                 case SMB_QUERY_FILE_ALL_INFO:
2744                 case SMB_FILE_ALL_INFORMATION:
2745                 {
2746                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2747                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2748                         put_long_date(pdata,c_time);
2749                         put_long_date(pdata+8,sbuf.st_atime);
2750                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2751                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2752                         SIVAL(pdata,32,mode);
2753                         pdata += 40;
2754                         SOFF_T(pdata,0,allocation_size);
2755                         SOFF_T(pdata,8,file_size);
2756                         if (delete_pending && sbuf.st_nlink)
2757                                 SIVAL(pdata,16,sbuf.st_nlink - 1);
2758                         else
2759                                 SIVAL(pdata,16,sbuf.st_nlink);
2760                         SCVAL(pdata,20,delete_pending);
2761                         SCVAL(pdata,21,(mode&aDIR)?1:0);
2762                         pdata += 24;
2763                         SIVAL(pdata,0,ea_size);
2764                         pdata += 4; /* EA info */
2765                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2766                         SIVAL(pdata,0,len);
2767                         pdata += 4 + len;
2768                         data_size = PTR_DIFF(pdata,(*ppdata));
2769                         break;
2770                 }
2771                 case SMB_FILE_INTERNAL_INFORMATION:
2772                         /* This should be an index number - looks like
2773                            dev/ino to me :-) 
2774
2775                            I think this causes us to fail the IFSKIT
2776                            BasicFileInformationTest. -tpot */
2777
2778                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2779                         SIVAL(pdata,0,sbuf.st_dev);
2780                         SIVAL(pdata,4,sbuf.st_ino);
2781                         data_size = 8;
2782                         break;
2783
2784                 case SMB_FILE_ACCESS_INFORMATION:
2785                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2786                         SIVAL(pdata,0,desired_access);
2787                         data_size = 4;
2788                         break;
2789
2790                 case SMB_FILE_NAME_INFORMATION:
2791                         /* Pathname with leading '\'. */
2792                         {
2793                                 size_t byte_len;
2794                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2795                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2796                                 SIVAL(pdata,0,byte_len);
2797                                 data_size = 4 + byte_len;
2798                                 break;
2799                         }
2800
2801                 case SMB_FILE_DISPOSITION_INFORMATION:
2802                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2803                         data_size = 1;
2804                         SCVAL(pdata,0,delete_pending);
2805                         break;
2806
2807                 case SMB_FILE_POSITION_INFORMATION:
2808                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2809                         data_size = 8;
2810                         SOFF_T(pdata,0,pos);
2811                         break;
2812
2813                 case SMB_FILE_MODE_INFORMATION:
2814                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2815                         SIVAL(pdata,0,mode);
2816                         data_size = 4;
2817                         break;
2818
2819                 case SMB_FILE_ALIGNMENT_INFORMATION:
2820                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2821                         SIVAL(pdata,0,0); /* No alignment needed. */
2822                         data_size = 4;
2823                         break;
2824
2825 #if 0
2826                 /*
2827                  * NT4 server just returns "invalid query" to this - if we try to answer
2828                  * it then NTws gets a BSOD! (tridge).
2829                  * W2K seems to want this. JRA.
2830                  */
2831                 case SMB_QUERY_FILE_STREAM_INFO:
2832 #endif
2833                 case SMB_FILE_STREAM_INFORMATION:
2834                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2835                         if (mode & aDIR) {
2836                                 data_size = 0;
2837                         } else {
2838                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2839                                 SIVAL(pdata,0,0); /* ??? */
2840                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2841                                 SOFF_T(pdata,8,file_size);
2842                                 SIVAL(pdata,16,allocation_size);
2843                                 SIVAL(pdata,20,0); /* ??? */
2844                                 data_size = 24 + byte_len;
2845                         }
2846                         break;
2847
2848                 case SMB_QUERY_COMPRESSION_INFO:
2849                 case SMB_FILE_COMPRESSION_INFORMATION:
2850                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2851                         SOFF_T(pdata,0,file_size);
2852                         SIVAL(pdata,8,0); /* ??? */
2853                         SIVAL(pdata,12,0); /* ??? */
2854                         data_size = 16;
2855                         break;
2856
2857                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
2858                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2859                         put_long_date(pdata,c_time);
2860                         put_long_date(pdata+8,sbuf.st_atime);
2861                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2862                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2863                         SIVAL(pdata,32,allocation_size);
2864                         SOFF_T(pdata,40,file_size);
2865                         SIVAL(pdata,48,mode);
2866                         SIVAL(pdata,52,0); /* ??? */
2867                         data_size = 56;
2868                         break;
2869
2870                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2871                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2872                         SIVAL(pdata,0,mode);
2873                         SIVAL(pdata,4,0);
2874                         data_size = 8;
2875                         break;
2876
2877                 /*
2878                  * CIFS UNIX Extensions.
2879                  */
2880
2881                 case SMB_QUERY_FILE_UNIX_BASIC:
2882
2883                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2884                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2885
2886                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
2887                         pdata += 8;
2888
2889                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2890                         pdata += 8;
2891
2892                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2893                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2894                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2895                         pdata += 24;
2896
2897                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2898                         SIVAL(pdata,4,0);
2899                         pdata += 8;
2900
2901                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2902                         SIVAL(pdata,4,0);
2903                         pdata += 8;
2904
2905                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2906                         pdata += 4;
2907
2908                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2909                         SIVAL(pdata,4,0);
2910                         pdata += 8;
2911
2912                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2913                         SIVAL(pdata,4,0);
2914                         pdata += 8;
2915
2916                         SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2917                         pdata += 8;
2918                                 
2919                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2920                         SIVAL(pdata,4,0);
2921                         pdata += 8;
2922
2923                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2924                         SIVAL(pdata,4,0);
2925                         pdata += 8+1;
2926                         data_size = PTR_DIFF(pdata,(*ppdata));
2927
2928                         {
2929                                 int i;
2930                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2931
2932                                 for (i=0; i<100; i++)
2933                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2934                                 DEBUG(4,("\n"));
2935                         }
2936
2937                         break;
2938
2939                 case SMB_QUERY_FILE_UNIX_LINK:
2940                         {
2941                                 pstring buffer;
2942
2943                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2944 #ifdef S_ISLNK
2945                                 if(!S_ISLNK(sbuf.st_mode))
2946                                         return(UNIXERROR(ERRSRV,ERRbadlink));
2947 #else
2948                                 return(UNIXERROR(ERRDOS,ERRbadlink));
2949 #endif
2950                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
2951                                 if (len == -1)
2952                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
2953                                 buffer[len] = 0;
2954                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
2955                                 pdata += len;
2956                                 data_size = PTR_DIFF(pdata,(*ppdata));
2957
2958                                 break;
2959                         }
2960
2961 #if defined(HAVE_POSIX_ACLS)
2962                 case SMB_QUERY_POSIX_ACL:
2963                         {
2964                                 SMB_ACL_T file_acl = NULL;
2965                                 SMB_ACL_T def_acl = NULL;
2966                                 uint16 num_file_acls = 0;
2967                                 uint16 num_def_acls = 0;
2968
2969                                 if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
2970                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
2971                                 } else {
2972                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
2973                                 }
2974
2975                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
2976                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
2977                                                 fname ));
2978                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
2979                                 }
2980
2981                                 if (S_ISDIR(sbuf.st_mode)) {
2982                                         if (fsp && fsp->is_directory) {
2983                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2984                                         } else {
2985                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
2986                                         }
2987                                         def_acl = free_empty_sys_acl(conn, def_acl);
2988                                 }
2989
2990                                 num_file_acls = count_acl_entries(conn, file_acl);
2991                                 num_def_acls = count_acl_entries(conn, def_acl);
2992
2993                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
2994                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
2995                                                 data_size,
2996                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
2997                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
2998                                         if (file_acl) {
2999                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3000                                         }
3001                                         if (def_acl) {
3002                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3003                                         }
3004                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3005                                 }
3006
3007                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3008                                 SSVAL(pdata,2,num_file_acls);
3009                                 SSVAL(pdata,4,num_def_acls);
3010                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3011                                         if (file_acl) {
3012                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3013                                         }
3014                                         if (def_acl) {
3015                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3016                                         }
3017                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3018                                 }
3019                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3020                                         if (file_acl) {
3021                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3022                                         }
3023                                         if (def_acl) {
3024                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3025                                         }
3026                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3027                                 }
3028
3029                                 if (file_acl) {
3030                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3031                                 }
3032                                 if (def_acl) {
3033                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3034                                 }
3035                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3036                                 break;
3037                         }
3038 #endif
3039
3040                 default:
3041                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3042         }
3043
3044         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3045
3046         return(-1);
3047 }
3048
3049 /****************************************************************************
3050  Deal with the internal needs of setting the delete on close flag. Note that
3051  as the tdb locking is recursive, it is safe to call this from within 
3052  open_file_shared. JRA.
3053 ****************************************************************************/
3054
3055 NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3056 {
3057         if (delete_on_close) {
3058                 /*
3059                  * Only allow delete on close for writable files.
3060                  */
3061
3062                 if (!lp_delete_readonly(SNUM(fsp->conn))) {
3063                         if (dosmode & aRONLY) {
3064                                 DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3065                                         fsp->fsp_name ));
3066                                 return NT_STATUS_CANNOT_DELETE;
3067                         }
3068                 }
3069
3070                 /*
3071                  * Only allow delete on close for writable shares.
3072                  */
3073
3074                 if (!CAN_WRITE(fsp->conn)) {
3075                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3076                                 fsp->fsp_name ));
3077                         return NT_STATUS_ACCESS_DENIED;
3078                 }
3079
3080                 /*
3081                  * Only allow delete on close for files/directories opened with delete intent.
3082                  */
3083
3084                 if (!(fsp->desired_access & DELETE_ACCESS)) {
3085                         DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3086                                 fsp->fsp_name ));
3087                         return NT_STATUS_ACCESS_DENIED;
3088                 }
3089         }
3090
3091         if(fsp->is_directory) {
3092                 fsp->directory_delete_on_close = delete_on_close;
3093                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3094                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3095         } else {
3096                 fsp->delete_on_close = delete_on_close;
3097                 DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3098                         delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3099         }
3100
3101         return NT_STATUS_OK;
3102 }
3103
3104 /****************************************************************************
3105  Sets the delete on close flag over all share modes on this file.
3106  Modify the share mode entry for all files open
3107  on this device and inode to tell other smbds we have
3108  changed the delete on close flag. This will be noticed
3109  in the close code, the last closer will delete the file
3110  if flag is set.
3111 ****************************************************************************/
3112
3113 NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3114 {
3115         DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3116                 delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3117
3118         if (fsp->is_directory || fsp->is_stat)
3119                 return NT_STATUS_OK;
3120
3121         if (lock_share_entry_fsp(fsp) == False)
3122                 return NT_STATUS_ACCESS_DENIED;
3123
3124         if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3125                 DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3126                         fsp->fsp_name ));
3127                 unlock_share_entry_fsp(fsp);
3128                 return NT_STATUS_ACCESS_DENIED;
3129         }
3130
3131         unlock_share_entry_fsp(fsp);
3132         return NT_STATUS_OK;
3133 }
3134
3135 /****************************************************************************
3136  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3137  code.
3138 ****************************************************************************/
3139
3140 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3141 {
3142         BOOL bad_path_oldname = False;
3143         BOOL bad_path_newname = False;
3144         SMB_STRUCT_STAT sbuf1, sbuf2;
3145         pstring last_component_oldname;
3146         pstring last_component_newname;
3147         NTSTATUS status = NT_STATUS_OK;
3148
3149         ZERO_STRUCT(sbuf1);
3150         ZERO_STRUCT(sbuf2);
3151
3152         /* No wildcards. */
3153         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3154                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3155         }
3156
3157         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3158         if (bad_path_oldname) {
3159                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3160         }
3161
3162         /* Quick check for "." and ".." */
3163         if (last_component_oldname[0] == '.') {
3164                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3165                         return NT_STATUS_OBJECT_NAME_INVALID;
3166                 }
3167         }
3168
3169         /* source must already exist. */
3170         if (!VALID_STAT(sbuf1)) {
3171                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3172         }
3173
3174         if (!check_name(oldname,conn)) {
3175                 return NT_STATUS_ACCESS_DENIED;
3176         }
3177
3178         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3179         if (bad_path_newname) {
3180                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3181         }
3182
3183         /* Quick check for "." and ".." */
3184         if (last_component_newname[0] == '.') {
3185                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3186                         return NT_STATUS_OBJECT_NAME_INVALID;
3187                 }
3188         }
3189
3190         /* Disallow if newname already exists. */
3191         if (VALID_STAT(sbuf2)) {
3192                 return NT_STATUS_OBJECT_NAME_COLLISION;
3193         }
3194
3195         if (!check_name(newname,conn)) {
3196                 return NT_STATUS_ACCESS_DENIED;
3197         }
3198
3199         /* No links from a directory. */
3200         if (S_ISDIR(sbuf1.st_mode)) {
3201                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3202         }
3203
3204         /* Ensure this is within the share. */
3205         if (!reduce_name(conn, oldname) != 0)
3206                 return NT_STATUS_ACCESS_DENIED;
3207
3208         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3209
3210         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3211                 status = map_nt_error_from_unix(errno);
3212                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3213                                 nt_errstr(status), newname, oldname));
3214         }
3215
3216         return status;
3217 }
3218
3219 /****************************************************************************
3220  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3221 ****************************************************************************/
3222
3223 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3224                                         char **pparams, int total_params, char **ppdata, int total_data,
3225                                         unsigned int max_data_bytes)
3226 {
3227         char *params = *pparams;
3228         char *pdata = *ppdata;
3229         uint16 tran_call = SVAL(inbuf, smb_setup0);
3230         uint16 info_level;
3231         int dosmode=0;
3232         SMB_OFF_T size=0;
3233         struct utimbuf tvs;
3234         SMB_STRUCT_STAT sbuf;
3235         pstring fname;
3236         int fd = -1;
3237         BOOL bad_path = False;
3238         files_struct *fsp = NULL;
3239         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3240         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3241         mode_t unixmode = 0;
3242         NTSTATUS status = NT_STATUS_OK;
3243
3244         if (!params)
3245                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3246
3247         ZERO_STRUCT(sbuf);
3248
3249         if (tran_call == TRANSACT2_SETFILEINFO) {
3250                 if (total_params < 4)
3251                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3252
3253                 fsp = file_fsp(params,0);
3254                 info_level = SVAL(params,2);    
3255
3256                 if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3257                         /*
3258                          * This is actually a SETFILEINFO on a directory
3259                          * handle (returned from an NT SMB). NT5.0 seems
3260                          * to do this call. JRA.
3261                          */
3262                         pstrcpy(fname, fsp->fsp_name);
3263                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3264                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3265                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3266                         }
3267                 } else if (fsp && fsp->print_file) {
3268                         /*
3269                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3270                          */
3271                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3272                                 fsp->share_mode = FILE_DELETE_ON_CLOSE;
3273
3274                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3275         
3276                                 SSVAL(params,0,0);
3277                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3278                                 return(-1);
3279                         } else
3280                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3281             } else {
3282                         /*
3283                          * Original code - this is an open file.
3284                          */
3285                         CHECK_FSP(fsp,conn);
3286
3287                         pstrcpy(fname, fsp->fsp_name);
3288                         fd = fsp->fd;
3289
3290                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3291                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3292                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3293                         }
3294                 }
3295         } else {
3296                 /* set path info */
3297                 if (total_params < 6)
3298                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3299
3300                 info_level = SVAL(params,0);    
3301                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3302                 if (!NT_STATUS_IS_OK(status)) {
3303                         return ERROR_NT(status);
3304                 }
3305                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3306                 if (bad_path) {
3307                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3308                 }
3309
3310                 /*
3311                  * For CIFS UNIX extensions the target name may not exist.
3312                  */
3313
3314                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3315                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3316                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3317                 }    
3318
3319                 if(!check_name(fname, conn)) {
3320                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3321                 }
3322
3323         }
3324
3325         if (!CAN_WRITE(conn))
3326                 return ERROR_DOS(ERRSRV,ERRaccess);
3327
3328         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3329                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3330
3331         if (VALID_STAT(sbuf))
3332                 unixmode = sbuf.st_mode;
3333
3334         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3335                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3336
3337         /* Realloc the parameter and data sizes */
3338         params = SMB_REALLOC(*pparams,2);
3339         if(params == NULL)
3340                 return ERROR_DOS(ERRDOS,ERRnomem);
3341         *pparams = params;
3342
3343         SSVAL(params,0,0);
3344
3345         if (fsp && fsp->pending_modtime) {
3346                 /* the pending modtime overrides the current modtime */
3347                 sbuf.st_mtime = fsp->pending_modtime;
3348         }
3349
3350         size = get_file_size(sbuf);
3351         tvs.modtime = sbuf.st_mtime;
3352         tvs.actime = sbuf.st_atime;
3353         dosmode = dos_mode(conn,fname,&sbuf);
3354         unixmode = sbuf.st_mode;
3355
3356         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3357         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3358
3359         switch (info_level) {
3360                 case SMB_INFO_STANDARD:
3361                 {
3362                         if (total_data < 12)
3363                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3364
3365                         /* access time */
3366                         tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3367                         /* write time */
3368                         tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3369                         break;
3370                 }
3371
3372                 case SMB_INFO_SET_EA:
3373                         status = set_ea(conn, fsp, fname, pdata, total_data);
3374                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3375                                 return ERROR_NT(status);
3376                         break;
3377
3378                 /* XXXX um, i don't think this is right.
3379                         it's also not in the cifs6.txt spec.
3380                 */
3381                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3382                         if (total_data < 28)
3383                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3384
3385                         tvs.actime = make_unix_date2(pdata+8);
3386                         tvs.modtime = make_unix_date2(pdata+12);
3387                         size = IVAL(pdata,16);
3388                         dosmode = IVAL(pdata,24);
3389                         break;
3390
3391                 /* XXXX nor this.  not in cifs6.txt, either. */
3392                 case SMB_INFO_QUERY_ALL_EAS:
3393                         if (total_data < 28)
3394                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3395
3396                         tvs.actime = make_unix_date2(pdata+8);
3397                         tvs.modtime = make_unix_date2(pdata+12);
3398                         size = IVAL(pdata,16);
3399                         dosmode = IVAL(pdata,24);
3400                         break;
3401
3402                 case SMB_SET_FILE_BASIC_INFO:
3403                 case SMB_FILE_BASIC_INFORMATION:
3404                 {
3405                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3406                         time_t write_time;
3407                         time_t changed_time;
3408
3409                         if (total_data < 36)
3410                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3411
3412                         /* Ignore create time at offset pdata. */
3413
3414                         /* access time */
3415                         tvs.actime = interpret_long_date(pdata+8);
3416
3417                         write_time = interpret_long_date(pdata+16);
3418                         changed_time = interpret_long_date(pdata+24);
3419
3420                         tvs.modtime = MIN(write_time, changed_time);
3421
3422                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3423                                 tvs.modtime = write_time;
3424                         }
3425                         /* Prefer a defined time to an undefined one. */
3426                         if (null_mtime(tvs.modtime)) {
3427                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3428                         }
3429
3430                         /* attributes */
3431                         dosmode = IVAL(pdata,32);
3432                         break;
3433                 }
3434
3435                 case SMB_FILE_ALLOCATION_INFORMATION:
3436                 case SMB_SET_FILE_ALLOCATION_INFO:
3437                 {
3438                         int ret = -1;
3439                         SMB_BIG_UINT allocation_size;
3440
3441                         if (total_data < 8)
3442                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3443
3444                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3445 #ifdef LARGE_SMB_OFF_T
3446                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3447 #else /* LARGE_SMB_OFF_T */
3448                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3449                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3450 #endif /* LARGE_SMB_OFF_T */
3451                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3452                                         fname, (double)allocation_size ));
3453
3454                         if (allocation_size) {
3455                                 allocation_size = smb_roundup(conn, allocation_size);
3456                         }
3457
3458                         if(allocation_size != get_file_size(sbuf)) {
3459                                 SMB_STRUCT_STAT new_sbuf;
3460  
3461                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3462                                         fname, (double)allocation_size ));
3463  
3464                                 if (fd == -1) {
3465                                         files_struct *new_fsp = NULL;
3466                                         int access_mode = 0;
3467                                         int action = 0;
3468  
3469                                         if(global_oplock_break) {
3470                                                 /* Queue this file modify as we are the process of an oplock break.  */
3471  
3472                                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3473                                                 DEBUGADD(2,( "in oplock break state.\n"));
3474  
3475                                                 push_oplock_pending_smb_message(inbuf, length);
3476                                                 return -1;
3477                                         }
3478  
3479                                         new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3480                                                                         SET_OPEN_MODE(DOS_OPEN_RDWR),
3481                                                                         (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3482                                                                         FILE_ATTRIBUTE_NORMAL,
3483                                                                         INTERNAL_OPEN_ONLY, &access_mode, &action);
3484  
3485                                         if (new_fsp == NULL)
3486                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3487                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3488                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3489                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3490                                                                         new_fsp->fnum, strerror(errno)));
3491                                                 ret = -1;
3492                                         }
3493                                         close_file(new_fsp,True);
3494                                 } else {
3495                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3496                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3497                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3498                                                                         fsp->fnum, strerror(errno)));
3499                                                 ret = -1;
3500                                         }
3501                                 }
3502                                 if (ret == -1)
3503                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3504
3505                                 /* Allocate can truncate size... */
3506                                 size = get_file_size(new_sbuf);
3507                         }
3508
3509                         break;
3510                 }
3511
3512                 case SMB_FILE_END_OF_FILE_INFORMATION:
3513                 case SMB_SET_FILE_END_OF_FILE_INFO:
3514                 {
3515                         if (total_data < 8)
3516                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3517
3518                         size = IVAL(pdata,0);
3519 #ifdef LARGE_SMB_OFF_T
3520                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3521 #else /* LARGE_SMB_OFF_T */
3522                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3523                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3524 #endif /* LARGE_SMB_OFF_T */
3525                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3526                         break;
3527                 }
3528
3529                 case SMB_FILE_DISPOSITION_INFORMATION:
3530                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3531                 {
3532                         BOOL delete_on_close;
3533
3534                         if (total_data < 1)
3535                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3536
3537                         delete_on_close = (CVAL(pdata,0) ? True : False);
3538
3539                         /* Just ignore this set on a path. */
3540                         if (tran_call != TRANSACT2_SETFILEINFO)
3541                                 break;
3542
3543                         if (fsp == NULL)
3544                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3545
3546                         status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3547  
3548                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3549                                 return ERROR_NT(status);
3550
3551                         /* The set is across all open files on this dev/inode pair. */
3552                         status =set_delete_on_close_over_all(fsp, delete_on_close);
3553                         if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3554                                 return ERROR_NT(status);
3555
3556                         break;
3557                 }
3558
3559                 case SMB_FILE_POSITION_INFORMATION:
3560                 {
3561                         SMB_BIG_UINT position_information;
3562
3563                         if (total_data < 8)
3564                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3565
3566                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3567 #ifdef LARGE_SMB_OFF_T
3568                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3569 #else /* LARGE_SMB_OFF_T */
3570                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3571                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3572 #endif /* LARGE_SMB_OFF_T */
3573                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3574                                         fname, (double)position_information ));
3575                         if (fsp)
3576                                 fsp->position_information = position_information;
3577                         break;
3578                 }
3579
3580                 /*
3581                  * CIFS UNIX extensions.
3582                  */
3583
3584                 case SMB_SET_FILE_UNIX_BASIC:
3585                 {
3586                         uint32 raw_unixmode;
3587
3588                         if (total_data < 100)
3589                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3590
3591                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3592                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3593                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
3594 #ifdef LARGE_SMB_OFF_T
3595                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3596 #else /* LARGE_SMB_OFF_T */
3597                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3598                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3599 #endif /* LARGE_SMB_OFF_T */
3600                         }
3601                         pdata+=24;          /* ctime & st_blocks are not changed */
3602                         tvs.actime = interpret_long_date(pdata); /* access_time */
3603                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3604                         pdata+=16;
3605                         set_owner = (uid_t)IVAL(pdata,0);
3606                         pdata += 8;
3607                         set_grp = (gid_t)IVAL(pdata,0);
3608                         pdata += 8;
3609                         raw_unixmode = IVAL(pdata,28);
3610                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3611                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
3612
3613                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3614 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3615                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3616
3617                         if (!VALID_STAT(sbuf)) {
3618
3619                                 /*
3620                                  * The only valid use of this is to create character and block
3621                                  * devices, and named pipes. This is deprecated (IMHO) and 
3622                                  * a new info level should be used for mknod. JRA.
3623                                  */
3624
3625                                 uint32 file_type = IVAL(pdata,0);
3626 #if defined(HAVE_MAKEDEV)
3627                                 uint32 dev_major = IVAL(pdata,4);
3628                                 uint32 dev_minor = IVAL(pdata,12);
3629 #endif
3630
3631                                 uid_t myuid = geteuid();
3632                                 gid_t mygid = getegid();
3633                                 SMB_DEV_T dev = (SMB_DEV_T)0;
3634
3635                                 if (tran_call == TRANSACT2_SETFILEINFO)
3636                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3637
3638                                 if (raw_unixmode == SMB_MODE_NO_CHANGE)
3639                                         return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3640
3641 #if defined(HAVE_MAKEDEV)
3642                                 dev = makedev(dev_major, dev_minor);
3643 #endif
3644
3645                                 /* We can only create as the owner/group we are. */
3646
3647                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3648                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3649                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3650                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
3651
3652                                 switch (file_type) {
3653 #if defined(S_IFIFO)
3654                                         case UNIX_TYPE_FIFO:
3655                                                 unixmode |= S_IFIFO;
3656                                                 break;
3657 #endif
3658 #if defined(S_IFSOCK)
3659                                         case UNIX_TYPE_SOCKET:
3660                                                 unixmode |= S_IFSOCK;
3661                                                 break;
3662 #endif
3663 #if defined(S_IFCHR)
3664                                         case UNIX_TYPE_CHARDEV:
3665                                                 unixmode |= S_IFCHR;
3666                                                 break;
3667 #endif
3668 #if defined(S_IFBLK)
3669                                         case UNIX_TYPE_BLKDEV:
3670                                                 unixmode |= S_IFBLK;
3671                                                 break;
3672 #endif
3673                                         default:
3674                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3675                                 }
3676
3677                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
3678 0%o for file %s\n", (double)dev, unixmode, fname ));
3679
3680                                 /* Ok - do the mknod. */
3681                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3682                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3683
3684                                 inherit_access_acl(conn, fname, unixmode);
3685
3686                                 SSVAL(params,0,0);
3687                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3688                                 return(-1);
3689                         }
3690
3691                         /*
3692                          * Deal with the UNIX specific mode set.
3693                          */
3694
3695                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3696                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3697                                         (unsigned int)unixmode, fname ));
3698                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3699                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3700                         }
3701
3702                         /*
3703                          * Deal with the UNIX specific uid set.
3704                          */
3705
3706                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3707                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3708                                         (unsigned int)set_owner, fname ));
3709                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3710                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3711                         }
3712
3713                         /*
3714                          * Deal with the UNIX specific gid set.
3715                          */
3716
3717                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3718                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3719                                         (unsigned int)set_owner, fname ));
3720                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3721                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3722                         }
3723                         break;
3724                 }
3725
3726                 case SMB_SET_FILE_UNIX_LINK:
3727                 {
3728                         pstring link_target;
3729                         char *newname = fname;
3730
3731                         /* Set a symbolic link. */
3732                         /* Don't allow this if follow links is false. */
3733
3734                         if (!lp_symlinks(SNUM(conn)))
3735                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
3736
3737                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3738
3739                         /* !widelinks forces the target path to be within the share. */
3740                         /* This means we can interpret the target as a pathname. */
3741                         if (!lp_widelinks(SNUM(conn))) {
3742                                 pstring rel_name;
3743                                 char *last_dirp = NULL;
3744
3745                                 unix_format(link_target);
3746                                 if (*link_target == '/') {
3747                                         /* No absolute paths allowed. */
3748                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3749                                 }
3750                                 pstrcpy(rel_name, newname);
3751                                 last_dirp = strrchr_m(rel_name, '/');
3752                                 if (last_dirp) {
3753                                         last_dirp[1] = '\0';
3754                                 } else {
3755                                         pstrcpy(rel_name, "./");
3756                                 }
3757                                 pstrcat(rel_name, link_target);
3758
3759                                 if (!check_name(rel_name, conn)) {
3760                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3761                                 }
3762                         }
3763
3764                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3765                                 fname, link_target ));
3766
3767                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3768                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3769                         SSVAL(params,0,0);
3770                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3771                         return(-1);
3772                 }
3773
3774                 case SMB_SET_FILE_UNIX_HLINK:
3775                 {
3776                         pstring oldname;
3777                         char *newname = fname;
3778
3779                         /* Set a hard link. */
3780                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3781                         if (!NT_STATUS_IS_OK(status)) {
3782                                 return ERROR_NT(status);
3783                         }
3784
3785                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3786                                 fname, oldname));
3787
3788                         status = hardlink_internals(conn, oldname, newname);
3789                         if (!NT_STATUS_IS_OK(status)) {
3790                                 return ERROR_NT(status);
3791                         }
3792
3793                         SSVAL(params,0,0);
3794                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3795                         return(-1);
3796                 }
3797
3798                 case SMB_FILE_RENAME_INFORMATION:
3799                 {
3800                         BOOL overwrite;
3801                         uint32 root_fid;
3802                         uint32 len;
3803                         pstring newname;
3804                         pstring base_name;
3805                         char *p;
3806
3807                         if (total_data < 12)
3808                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3809
3810                         overwrite = (CVAL(pdata,0) ? True : False);
3811                         root_fid = IVAL(pdata,4);
3812                         len = IVAL(pdata,8);
3813                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3814                         if (!NT_STATUS_IS_OK(status)) {
3815                                 return ERROR_NT(status);
3816                         }
3817
3818                         /* Check the new name has no '/' characters. */
3819                         if (strchr_m(newname, '/'))
3820                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3821
3822                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3823
3824                         /* Create the base directory. */
3825                         pstrcpy(base_name, fname);
3826                         p = strrchr_m(base_name, '/');
3827                         if (p)
3828                                 *p = '\0';
3829                         /* Append the new name. */
3830                         pstrcat(base_name, "/");
3831                         pstrcat(base_name, newname);
3832
3833                         if (fsp) {
3834                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3835                                         fsp->fnum, fsp->fsp_name, base_name ));
3836                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3837                         } else {
3838                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3839                                         fname, newname ));
3840                                 status = rename_internals(conn, fname, base_name, 0, overwrite);
3841                         }
3842                         if (!NT_STATUS_IS_OK(status)) {
3843                                 return ERROR_NT(status);
3844                         }
3845                         process_pending_change_notify_queue((time_t)0);
3846                         SSVAL(params,0,0);
3847                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3848                         return(-1);
3849                 }
3850
3851 #if defined(HAVE_POSIX_ACLS)
3852                 case SMB_SET_POSIX_ACL:
3853                 {
3854                         uint16 posix_acl_version;
3855                         uint16 num_file_acls;
3856                         uint16 num_def_acls;
3857                         BOOL valid_file_acls = True;
3858                         BOOL valid_def_acls = True;
3859
3860                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3861                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3862                         }
3863                         posix_acl_version = SVAL(pdata,0);
3864                         num_file_acls = SVAL(pdata,2);
3865                         num_def_acls = SVAL(pdata,4);
3866
3867                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3868                                 valid_file_acls = False;
3869                                 num_file_acls = 0;
3870                         }
3871
3872                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3873                                 valid_def_acls = False;
3874                                 num_def_acls = 0;
3875                         }
3876
3877                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3878                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3879                         }
3880
3881                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3882                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3883                                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3884                         }
3885
3886                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3887                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3888                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3889                         }
3890
3891                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3892                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
3893                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3894                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
3895                         }
3896
3897                         SSVAL(params,0,0);
3898                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3899                         return(-1);
3900                 }
3901 #endif
3902
3903                 default:
3904                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3905         }
3906
3907         /* get some defaults (no modifications) if any info is zero or -1. */
3908         if (null_mtime(tvs.actime)) {
3909                 tvs.actime = sbuf.st_atime;
3910         }
3911
3912         if (null_mtime(tvs.modtime)) {
3913                 tvs.modtime = sbuf.st_mtime;
3914         }
3915
3916         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
3917         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
3918         DEBUG(6,("size: %.0f ", (double)size));
3919
3920         if (dosmode) {
3921                 if (S_ISDIR(sbuf.st_mode))
3922                         dosmode |= aDIR;
3923                 else
3924                         dosmode &= ~aDIR;
3925         }
3926
3927         DEBUG(6,("dosmode: %x\n"  , dosmode));
3928
3929         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
3930                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
3931                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
3932                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
3933
3934                 /*
3935                  * Only do this test if we are not explicitly
3936                  * changing the size of a file.
3937                  */
3938                 if (!size)
3939                         size = get_file_size(sbuf);
3940         }
3941
3942         /*
3943          * Try and set the times, size and mode of this file -
3944          * if they are different from the current values
3945          */
3946
3947         /* check the mode isn't different, before changing it */
3948         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
3949
3950                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
3951
3952                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
3953                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
3954                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3955                 }
3956         }
3957
3958         /* Now the size. */
3959         if (size != get_file_size(sbuf)) {
3960
3961                 int ret;
3962
3963                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3964                         fname, (double)size ));
3965
3966                 if (fd == -1) {
3967                         files_struct *new_fsp = NULL;
3968                         int access_mode = 0;
3969                         int action = 0;
3970
3971                         if(global_oplock_break) {
3972                                 /* Queue this file modify as we are the process of an oplock break.  */
3973
3974                                 DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3975                                 DEBUGADD(2,( "in oplock break state.\n"));
3976
3977                                 push_oplock_pending_smb_message(inbuf, length);
3978                                 return -1;
3979                         }
3980
3981                         new_fsp = open_file_shared(conn, fname, &sbuf,
3982                                                 SET_OPEN_MODE(DOS_OPEN_RDWR),
3983                                                 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3984                                                 FILE_ATTRIBUTE_NORMAL,
3985                                                 INTERNAL_OPEN_ONLY, &access_mode, &action);
3986         
3987                         if (new_fsp == NULL)
3988                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3989                         ret = vfs_set_filelen(new_fsp, size);
3990                         close_file(new_fsp,True);
3991                 } else {
3992                         ret = vfs_set_filelen(fsp, size);
3993                 }
3994
3995                 if (ret == -1)
3996                         return (UNIXERROR(ERRHRD,ERRdiskfull));
3997         }
3998
3999         /*
4000          * Finally the times.
4001          */
4002         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4003                 if(fsp != NULL) {
4004                         /*
4005                          * This was a setfileinfo on an open file.
4006                          * NT does this a lot. We also need to 
4007                          * set the time here, as it can be read by 
4008                          * FindFirst/FindNext and with the patch for bug #2045
4009                          * in smbd/fileio.c it ensures that this timestamp is
4010                          * kept sticky even after a write. We save the request
4011                          * away and will set it on file close and after a write. JRA.
4012                          */
4013
4014                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4015                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4016                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4017                         }
4018
4019                 }
4020                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4021
4022                 if(file_utime(conn, fname, &tvs)!=0) {
4023                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4024                 }
4025         }
4026
4027         SSVAL(params,0,0);
4028         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4029   
4030         return(-1);
4031 }
4032
4033 /****************************************************************************
4034  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4035 ****************************************************************************/
4036
4037 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4038                                         char **pparams, int total_params, char **ppdata, int total_data,
4039                                         unsigned int max_data_bytes)
4040 {
4041         char *params = *pparams;
4042         pstring directory;
4043         int ret = -1;
4044         SMB_STRUCT_STAT sbuf;
4045         BOOL bad_path = False;
4046         NTSTATUS status = NT_STATUS_OK;
4047
4048         if (!CAN_WRITE(conn))
4049                 return ERROR_DOS(ERRSRV,ERRaccess);
4050
4051         if (total_params < 4)
4052                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4053
4054         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4055         if (!NT_STATUS_IS_OK(status)) {
4056                 return ERROR_NT(status);
4057         }
4058
4059         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4060
4061         unix_convert(directory,conn,0,&bad_path,&sbuf);
4062         if (bad_path) {
4063                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4064         }
4065         if (check_name(directory,conn))
4066                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4067   
4068         if(ret < 0) {
4069                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4070                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4071         }
4072
4073         /* Realloc the parameter and data sizes */
4074         params = SMB_REALLOC(*pparams,2);
4075         if(params == NULL)
4076                 return ERROR_DOS(ERRDOS,ERRnomem);
4077         *pparams = params;
4078
4079         SSVAL(params,0,0);
4080
4081         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4082   
4083         return(-1);
4084 }
4085
4086 /****************************************************************************
4087  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4088  We don't actually do this - we just send a null response.
4089 ****************************************************************************/
4090
4091 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4092                                         char **pparams, int total_params, char **ppdata, int total_data,
4093                                         unsigned int max_data_bytes)
4094 {
4095         static uint16 fnf_handle = 257;
4096         char *params = *pparams;
4097         uint16 info_level;
4098
4099         if (total_params < 6)
4100                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4101
4102         info_level = SVAL(params,4);
4103         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4104
4105         switch (info_level) {
4106                 case 1:
4107                 case 2:
4108                         break;
4109                 default:
4110                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4111         }
4112
4113         /* Realloc the parameter and data sizes */
4114         params = SMB_REALLOC(*pparams,6);
4115         if(params == NULL) 
4116                 return ERROR_DOS(ERRDOS,ERRnomem);
4117         *pparams = params;
4118
4119         SSVAL(params,0,fnf_handle);
4120         SSVAL(params,2,0); /* No changes */
4121         SSVAL(params,4,0); /* No EA errors */
4122
4123         fnf_handle++;
4124
4125         if(fnf_handle == 0)
4126                 fnf_handle = 257;
4127
4128         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4129   
4130         return(-1);
4131 }
4132
4133 /****************************************************************************
4134  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4135  changes). Currently this does nothing.
4136 ****************************************************************************/
4137
4138 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4139                                         char **pparams, int total_params, char **ppdata, int total_data,
4140                                         unsigned int max_data_bytes)
4141 {
4142         char *params = *pparams;
4143
4144         DEBUG(3,("call_trans2findnotifynext\n"));
4145
4146         /* Realloc the parameter and data sizes */
4147         params = SMB_REALLOC(*pparams,4);
4148         if(params == NULL)
4149                 return ERROR_DOS(ERRDOS,ERRnomem);
4150         *pparams = params;
4151
4152         SSVAL(params,0,0); /* No changes */
4153         SSVAL(params,2,0); /* No EA errors */
4154
4155         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4156   
4157         return(-1);
4158 }
4159
4160 /****************************************************************************
4161  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4162 ****************************************************************************/
4163
4164 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4165                                         char **pparams, int total_params, char **ppdata, int total_data,
4166                                         unsigned int max_data_bytes)
4167 {
4168         char *params = *pparams;
4169         pstring pathname;
4170         int reply_size = 0;
4171         int max_referral_level;
4172
4173         DEBUG(10,("call_trans2getdfsreferral\n"));
4174
4175         if (total_params < 2)
4176                 return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4177
4178         max_referral_level = SVAL(params,0);
4179
4180         if(!lp_host_msdfs())
4181                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4182
4183         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4184         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4185                 return UNIXERROR(ERRDOS,ERRbadfile);
4186     
4187         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4188         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4189
4190         return(-1);
4191 }
4192
4193 #define LMCAT_SPL       0x53
4194 #define LMFUNC_GETJOBID 0x60
4195
4196 /****************************************************************************
4197  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4198 ****************************************************************************/
4199
4200 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4201                                         char **pparams, int total_params, char **ppdata, int total_data,
4202                                         unsigned int max_data_bytes)
4203 {
4204         char *pdata = *ppdata;
4205         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4206
4207         /* check for an invalid fid before proceeding */
4208         
4209         if (!fsp)                                
4210                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4211
4212         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4213                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4214                 pdata = SMB_REALLOC(*ppdata, 32);
4215                 if(pdata == NULL)
4216                         return ERROR_DOS(ERRDOS,ERRnomem);
4217                 *ppdata = pdata;
4218
4219                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4220                         CAN ACCEPT THIS IN UNICODE. JRA. */
4221
4222                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4223                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4224                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4225                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4226                 return(-1);
4227         } else {
4228                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4229                 return ERROR_DOS(ERRSRV,ERRerror);
4230         }
4231 }
4232
4233 /****************************************************************************
4234  Reply to a SMBfindclose (stop trans2 directory search).
4235 ****************************************************************************/
4236
4237 int reply_findclose(connection_struct *conn,
4238                     char *inbuf,char *outbuf,int length,int bufsize)
4239 {
4240         int outsize = 0;
4241         int dptr_num=SVALS(inbuf,smb_vwv0);
4242         START_PROFILE(SMBfindclose);
4243
4244         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4245
4246         dptr_close(&dptr_num);
4247
4248         outsize = set_message(outbuf,0,0,True);
4249
4250         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4251
4252         END_PROFILE(SMBfindclose);
4253         return(outsize);
4254 }
4255
4256 /****************************************************************************
4257  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4258 ****************************************************************************/
4259
4260 int reply_findnclose(connection_struct *conn, 
4261                      char *inbuf,char *outbuf,int length,int bufsize)
4262 {
4263         int outsize = 0;
4264         int dptr_num= -1;
4265         START_PROFILE(SMBfindnclose);
4266         
4267         dptr_num = SVAL(inbuf,smb_vwv0);
4268
4269         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4270
4271         /* We never give out valid handles for a 
4272            findnotifyfirst - so any dptr_num is ok here. 
4273            Just ignore it. */
4274
4275         outsize = set_message(outbuf,0,0,True);
4276
4277         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4278
4279         END_PROFILE(SMBfindnclose);
4280         return(outsize);
4281 }
4282
4283 /****************************************************************************
4284  Reply to a SMBtranss2 - just ignore it!
4285 ****************************************************************************/
4286
4287 int reply_transs2(connection_struct *conn,
4288                   char *inbuf,char *outbuf,int length,int bufsize)
4289 {
4290         START_PROFILE(SMBtranss2);
4291         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4292         END_PROFILE(SMBtranss2);
4293         return(-1);
4294 }
4295
4296 /****************************************************************************
4297  Reply to a SMBtrans2.
4298 ****************************************************************************/
4299
4300 int reply_trans2(connection_struct *conn,
4301                  char *inbuf,char *outbuf,int length,int bufsize)
4302 {
4303         int outsize = 0;
4304         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4305         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4306         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4307 #if 0
4308         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4309         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4310         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4311         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4312         int32 timeout = IVALS(inbuf,smb_timeout);
4313 #endif
4314         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4315         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4316         char *params = NULL, *data = NULL;
4317         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4318         START_PROFILE(SMBtrans2);
4319
4320         if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4321                 /* Queue this open message as we are the process of an
4322                  * oplock break.  */
4323
4324                 DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4325                 DEBUGADD(2,( "in oplock break state.\n"));
4326
4327                 push_oplock_pending_smb_message(inbuf, length);
4328                 END_PROFILE(SMBtrans2);
4329                 return -1;
4330         }
4331         
4332         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4333             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4334                 END_PROFILE(SMBtrans2);
4335                 return ERROR_DOS(ERRSRV,ERRaccess);
4336         }
4337
4338         outsize = set_message(outbuf,0,0,True);
4339
4340         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4341            is so as a sanity check */
4342         if (suwcnt != 1) {
4343                 /*
4344                  * Need to have rc=0 for ioctl to get job id for OS/2.
4345                  *  Network printing will fail if function is not successful.
4346                  *  Similar function in reply.c will be used if protocol
4347                  *  is LANMAN1.0 instead of LM1.2X002.
4348                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4349                  *  outbuf doesn't have to be set(only job id is used).
4350                  */
4351                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4352                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4353                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4354                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4355                 } else {
4356                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4357                         DEBUG(2,("Transaction is %d\n",tran_call));
4358                         END_PROFILE(SMBtrans2);
4359                         ERROR_DOS(ERRDOS,ERRinvalidparam);
4360                 }
4361         }
4362     
4363         /* Allocate the space for the maximum needed parameters and data */
4364         if (total_params > 0)
4365                 params = (char *)SMB_MALLOC(total_params);
4366         if (total_data > 0)
4367                 data = (char *)SMB_MALLOC(total_data);
4368   
4369         if ((total_params && !params)  || (total_data && !data)) {
4370                 DEBUG(2,("Out of memory in reply_trans2\n"));
4371                 SAFE_FREE(params);
4372                 SAFE_FREE(data); 
4373                 END_PROFILE(SMBtrans2);
4374                 return ERROR_DOS(ERRDOS,ERRnomem);
4375         }
4376
4377         /* Copy the param and data bytes sent with this request into
4378            the params buffer */
4379         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4380         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4381
4382         if (num_params > total_params || num_data > total_data)
4383                 exit_server("invalid params in reply_trans2");
4384
4385         if(params) {
4386                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4387                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4388                         goto bad_param;
4389                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4390                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4391                         goto bad_param;
4392                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4393         }
4394         if(data) {
4395                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4396                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4397                         goto bad_param;
4398                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4399                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4400                         goto bad_param;
4401                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4402         }
4403
4404         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4405
4406         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4407                 /* We need to send an interim response then receive the rest
4408                    of the parameter/data bytes */
4409                 outsize = set_message(outbuf,0,0,True);
4410                 srv_signing_trans_stop();
4411                 if (!send_smb(smbd_server_fd(),outbuf))
4412                         exit_server("reply_trans2: send_smb failed.");
4413
4414                 while (num_data_sofar < total_data || 
4415                        num_params_sofar < total_params) {
4416                         BOOL ret;
4417                         unsigned int param_disp;
4418                         unsigned int param_off;
4419                         unsigned int data_disp;
4420                         unsigned int data_off;
4421
4422                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4423                         
4424                         /*
4425                          * The sequence number for the trans reply is always
4426                          * based on the last secondary received.
4427                          */
4428
4429                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4430
4431                         if ((ret && 
4432                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4433                                 outsize = set_message(outbuf,0,0,True);
4434                                 if(ret)
4435                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4436                                 else
4437                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4438                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4439                                 goto bad_param;
4440                         }
4441       
4442                         /* Revise total_params and total_data in case
4443                            they have changed downwards */
4444                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4445                                 total_params = SVAL(inbuf, smb_tpscnt);
4446                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4447                                 total_data = SVAL(inbuf, smb_tdscnt);
4448
4449                         num_params = SVAL(inbuf,smb_spscnt);
4450                         param_off = SVAL(inbuf, smb_spsoff);
4451                         param_disp = SVAL(inbuf, smb_spsdisp);
4452                         num_params_sofar += num_params;
4453
4454                         num_data = SVAL(inbuf, smb_sdscnt);
4455                         data_off = SVAL(inbuf, smb_sdsoff);
4456                         data_disp = SVAL(inbuf, smb_sdsdisp);
4457                         num_data_sofar += num_data;
4458
4459                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4460                                 goto bad_param;
4461                         
4462                         if (num_params) {
4463                                 if (param_disp + num_params > total_params)
4464                                         goto bad_param;
4465                                 if ((param_disp + num_params < param_disp) ||
4466                                                 (param_disp + num_params < num_params))
4467                                         goto bad_param;
4468                                 if (param_disp > total_params)
4469                                         goto bad_param;
4470                                 if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4471                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4472                                         goto bad_param;
4473                                 if (params + param_disp < params)
4474                                         goto bad_param;
4475
4476                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4477                         }
4478                         if (num_data) {
4479                                 if (data_disp + num_data > total_data)
4480                                         goto bad_param;
4481                                 if ((data_disp + num_data < data_disp) ||
4482                                                 (data_disp + num_data < num_data))
4483                                         goto bad_param;
4484                                 if (data_disp > total_data)
4485                                         goto bad_param;
4486                                 if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4487                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4488                                         goto bad_param;
4489                                 if (data + data_disp < data)
4490                                         goto bad_param;
4491
4492                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4493                         }
4494                 }
4495         }
4496         
4497         if (Protocol >= PROTOCOL_NT1) {
4498                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4499         }
4500
4501         /* Now we must call the relevant TRANS2 function */
4502         switch(tran_call)  {
4503         case TRANSACT2_OPEN:
4504                 START_PROFILE_NESTED(Trans2_open);
4505                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4506                                           &params, total_params, &data, total_data, max_data_bytes);
4507                 END_PROFILE_NESTED(Trans2_open);
4508                 break;
4509
4510         case TRANSACT2_FINDFIRST:
4511                 START_PROFILE_NESTED(Trans2_findfirst);
4512                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4513                                           &params, total_params, &data, total_data, max_data_bytes);
4514                 END_PROFILE_NESTED(Trans2_findfirst);
4515                 break;
4516
4517         case TRANSACT2_FINDNEXT:
4518                 START_PROFILE_NESTED(Trans2_findnext);
4519                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4520                                           &params, total_params, &data, total_data, max_data_bytes);
4521                 END_PROFILE_NESTED(Trans2_findnext);
4522                 break;
4523
4524         case TRANSACT2_QFSINFO:
4525                 START_PROFILE_NESTED(Trans2_qfsinfo);
4526                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4527                                           &params, total_params, &data, total_data, max_data_bytes);
4528                 END_PROFILE_NESTED(Trans2_qfsinfo);
4529             break;
4530
4531 #ifdef HAVE_SYS_QUOTAS
4532         case TRANSACT2_SETFSINFO:
4533                 START_PROFILE_NESTED(Trans2_setfsinfo);
4534                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
4535                                           &params, total_params, &data, total_data, max_data_bytes);
4536                 END_PROFILE_NESTED(Trans2_setfsinfo);
4537                 break;
4538 #endif
4539         case TRANSACT2_QPATHINFO:
4540         case TRANSACT2_QFILEINFO:
4541                 START_PROFILE_NESTED(Trans2_qpathinfo);
4542                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4543                                           &params, total_params, &data, total_data, max_data_bytes);
4544                 END_PROFILE_NESTED(Trans2_qpathinfo);
4545                 break;
4546         case TRANSACT2_SETPATHINFO:
4547         case TRANSACT2_SETFILEINFO:
4548                 START_PROFILE_NESTED(Trans2_setpathinfo);
4549                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, 
4550                                           &params, total_params, &data, total_data, max_data_bytes);
4551                 END_PROFILE_NESTED(Trans2_setpathinfo);
4552                 break;
4553
4554         case TRANSACT2_FINDNOTIFYFIRST:
4555                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
4556                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
4557                                           &params, total_params, &data, total_data, max_data_bytes);
4558                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
4559                 break;
4560
4561         case TRANSACT2_FINDNOTIFYNEXT:
4562                 START_PROFILE_NESTED(Trans2_findnotifynext);
4563                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
4564                                           &params, total_params, &data, total_data, max_data_bytes);
4565                 END_PROFILE_NESTED(Trans2_findnotifynext);
4566                 break;
4567         case TRANSACT2_MKDIR:
4568                 START_PROFILE_NESTED(Trans2_mkdir);
4569                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4570                                           &params, total_params, &data, total_data, max_data_bytes);
4571                 END_PROFILE_NESTED(Trans2_mkdir);
4572                 break;
4573
4574         case TRANSACT2_GET_DFS_REFERRAL:
4575                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
4576                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4577                                           &params, total_params, &data, total_data, max_data_bytes);
4578                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
4579                 break;
4580         case TRANSACT2_IOCTL:
4581                 START_PROFILE_NESTED(Trans2_ioctl);
4582                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4583                                           &params, total_params, &data, total_data, max_data_bytes);
4584                 END_PROFILE_NESTED(Trans2_ioctl);
4585                 break;
4586         default:
4587                 /* Error in request */
4588                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4589                 SAFE_FREE(params);
4590                 SAFE_FREE(data);
4591                 END_PROFILE(SMBtrans2);
4592                 srv_signing_trans_stop();
4593                 return ERROR_DOS(ERRSRV,ERRerror);
4594         }
4595         
4596         /* As we do not know how many data packets will need to be
4597            returned here the various call_trans2xxxx calls
4598            must send their own. Thus a call_trans2xxx routine only
4599            returns a value other than -1 when it wants to send
4600            an error packet. 
4601         */
4602         
4603         srv_signing_trans_stop();
4604
4605         SAFE_FREE(params);
4606         SAFE_FREE(data);
4607         END_PROFILE(SMBtrans2);
4608         return outsize; /* If a correct response was needed the
4609                            call_trans2xxx calls have already sent
4610                            it. If outsize != -1 then it is returning */
4611
4612   bad_param:
4613
4614         srv_signing_trans_stop();
4615         SAFE_FREE(params);
4616         SAFE_FREE(data);
4617         END_PROFILE(SMBtrans2);
4618         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4619 }