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