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