Add bcast_msg_flags to connection struct. Allows sender to filter when
[Samba.git] / source / smbd / reply.c
blob263626dcc1622f169d27ce77f2602d95d31773d8
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
29 /* look in server.c for some explanation of these variables */
30 extern int Protocol;
31 extern int max_send;
32 extern int max_recv;
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern pstring global_myname;
38 extern int global_oplock_break;
39 unsigned int smb_echo_count = 0;
41 extern BOOL global_encrypted_passwords_negotiated;
44 /****************************************************************************
45 reply to an special message
46 ****************************************************************************/
48 int reply_special(char *inbuf,char *outbuf)
50 int outsize = 4;
51 int msg_type = CVAL(inbuf,0);
52 int msg_flags = CVAL(inbuf,1);
53 pstring name1,name2;
55 int len;
56 char name_type = 0;
58 static BOOL already_got_session = False;
60 *name1 = *name2 = 0;
62 memset(outbuf,'\0',smb_size);
64 smb_setlen(outbuf,0);
66 switch (msg_type) {
67 case 0x81: /* session request */
69 if (already_got_session) {
70 exit_server("multiple session request not permitted");
73 SCVAL(outbuf,0,0x82);
74 SCVAL(outbuf,3,0);
75 if (name_len(inbuf+4) > 50 ||
76 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
77 DEBUG(0,("Invalid name length in session request\n"));
78 return(0);
80 name_extract(inbuf,4,name1);
81 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
82 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
83 name1,name2));
85 name1[15] = 0;
87 len = strlen(name2);
88 if (len == 16) {
89 name_type = name2[15];
90 name2[15] = 0;
93 set_local_machine_name(name1);
94 set_remote_machine_name(name2);
96 DEBUG(2,("netbios connect: local=%s remote=%s\n",
97 get_local_machine_name(), get_remote_machine_name() ));
99 if (name_type == 'R') {
100 /* We are being asked for a pathworks session ---
101 no thanks! */
102 SCVAL(outbuf, 0,0x83);
103 break;
106 /* only add the client's machine name to the list
107 of possibly valid usernames if we are operating
108 in share mode security */
109 if (lp_security() == SEC_SHARE) {
110 add_session_user(get_remote_machine_name());
113 reload_services(True);
114 reopen_logs();
116 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINTING);
118 already_got_session = True;
119 break;
121 case 0x89: /* session keepalive request
122 (some old clients produce this?) */
123 SCVAL(outbuf,0,SMBkeepalive);
124 SCVAL(outbuf,3,0);
125 break;
127 case 0x82: /* positive session response */
128 case 0x83: /* negative session response */
129 case 0x84: /* retarget session response */
130 DEBUG(0,("Unexpected session response\n"));
131 break;
133 case SMBkeepalive: /* session keepalive */
134 default:
135 return(0);
138 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
139 msg_type, msg_flags));
141 return(outsize);
145 /****************************************************************************
146 Reply to a tcon.
147 ****************************************************************************/
149 int reply_tcon(connection_struct *conn,
150 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
152 const char *service;
153 pstring service_buf;
154 pstring password;
155 pstring dev;
156 int outsize = 0;
157 uint16 vuid = SVAL(inbuf,smb_uid);
158 int pwlen=0;
159 NTSTATUS nt_status;
160 char *p;
161 DATA_BLOB password_blob;
163 START_PROFILE(SMBtcon);
165 *service_buf = *password = *dev = 0;
167 p = smb_buf(inbuf)+1;
168 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
169 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
170 p += pwlen;
171 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
173 p = strrchr_m(service_buf,'\\');
174 if (p) {
175 service = p+1;
176 } else {
177 service = service_buf;
180 password_blob = data_blob(password, pwlen+1);
182 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
184 data_blob_clear_free(&password_blob);
186 if (!conn) {
187 END_PROFILE(SMBtcon);
188 return ERROR_NT(nt_status);
191 outsize = set_message(outbuf,2,0,True);
192 SSVAL(outbuf,smb_vwv0,max_recv);
193 SSVAL(outbuf,smb_vwv1,conn->cnum);
194 SSVAL(outbuf,smb_tid,conn->cnum);
196 DEBUG(3,("tcon service=%s cnum=%d\n",
197 service, conn->cnum));
199 END_PROFILE(SMBtcon);
200 return(outsize);
203 /****************************************************************************
204 Reply to a tcon and X.
205 ****************************************************************************/
207 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
209 fstring service;
210 DATA_BLOB password;
211 pstring devicename;
212 NTSTATUS nt_status;
213 uint16 vuid = SVAL(inbuf,smb_uid);
214 int passlen = SVAL(inbuf,smb_vwv3);
215 pstring path;
216 char *p, *q;
217 extern BOOL global_encrypted_passwords_negotiated;
218 START_PROFILE(SMBtconX);
220 *service = *devicename = 0;
222 /* we might have to close an old one */
223 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
224 close_cnum(conn,vuid);
227 if (passlen > MAX_PASS_LEN) {
228 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
231 if (global_encrypted_passwords_negotiated) {
232 password = data_blob(smb_buf(inbuf),passlen);
233 } else {
234 password = data_blob(smb_buf(inbuf),passlen+1);
235 /* Ensure correct termination */
236 password.data[passlen]=0;
239 p = smb_buf(inbuf) + passlen;
240 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
243 * the service name can be either: \\server\share
244 * or share directly like on the DELL PowerVault 705
246 if (*path=='\\') {
247 q = strchr_m(path+2,'\\');
248 if (!q) {
249 END_PROFILE(SMBtconX);
250 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
252 fstrcpy(service,q+1);
254 else
255 fstrcpy(service,path);
257 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
259 DEBUG(4,("Got device type %s\n",devicename));
261 conn = make_connection(service,password,devicename,vuid,&nt_status);
263 data_blob_clear_free(&password);
265 if (!conn) {
266 END_PROFILE(SMBtconX);
267 return ERROR_NT(nt_status);
270 if (Protocol < PROTOCOL_NT1) {
271 set_message(outbuf,2,0,True);
272 p = smb_buf(outbuf);
273 p += srvstr_push(outbuf, p, devicename, -1,
274 STR_TERMINATE|STR_ASCII);
275 set_message_end(outbuf,p);
276 } else {
277 /* NT sets the fstype of IPC$ to the null string */
278 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
280 set_message(outbuf,3,0,True);
282 p = smb_buf(outbuf);
283 p += srvstr_push(outbuf, p, devicename, -1,
284 STR_TERMINATE|STR_ASCII);
285 p += srvstr_push(outbuf, p, fsname, -1,
286 STR_TERMINATE);
288 set_message_end(outbuf,p);
290 /* what does setting this bit do? It is set by NT4 and
291 may affect the ability to autorun mounted cdroms */
292 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
293 (lp_csc_policy(SNUM(conn)) << 2));
295 init_dfsroot(conn, inbuf, outbuf);
299 DEBUG(3,("tconX service=%s \n",
300 service));
302 /* set the incoming and outgoing tid to the just created one */
303 SSVAL(inbuf,smb_tid,conn->cnum);
304 SSVAL(outbuf,smb_tid,conn->cnum);
306 END_PROFILE(SMBtconX);
307 return chain_reply(inbuf,outbuf,length,bufsize);
311 /****************************************************************************
312 reply to an unknown type
313 ****************************************************************************/
314 int reply_unknown(char *inbuf,char *outbuf)
316 int type;
317 type = CVAL(inbuf,smb_com);
319 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
320 smb_fn_name(type), type, type));
322 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
326 /****************************************************************************
327 reply to an ioctl
328 ****************************************************************************/
329 int reply_ioctl(connection_struct *conn,
330 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
332 uint16 device = SVAL(inbuf,smb_vwv1);
333 uint16 function = SVAL(inbuf,smb_vwv2);
334 uint32 ioctl_code = (device << 16) + function;
335 int replysize, outsize;
336 char *p;
337 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
338 START_PROFILE(SMBioctl);
340 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
342 switch (ioctl_code)
344 case IOCTL_QUERY_JOB_INFO:
345 replysize = 32;
346 break;
347 default:
348 END_PROFILE(SMBioctl);
349 return(ERROR_DOS(ERRSRV,ERRnosupport));
352 outsize = set_message(outbuf,8,replysize+1,True);
353 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
354 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
355 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
356 p = smb_buf(outbuf) + 1; /* Allow for alignment */
358 switch (ioctl_code)
360 case IOCTL_QUERY_JOB_INFO:
362 uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
363 SSVAL(p,0,rap_jobid); /* Job number */
364 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
365 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
366 break;
370 END_PROFILE(SMBioctl);
371 return outsize;
374 /****************************************************************************
375 reply to a chkpth
376 ****************************************************************************/
377 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
379 int outsize = 0;
380 int mode;
381 pstring name;
382 BOOL ok = False;
383 BOOL bad_path = False;
384 SMB_STRUCT_STAT sbuf;
385 START_PROFILE(SMBchkpth);
387 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
389 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
391 unix_convert(name,conn,0,&bad_path,&sbuf);
393 mode = SVAL(inbuf,smb_vwv0);
395 if (check_name(name,conn)) {
396 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
397 ok = S_ISDIR(sbuf.st_mode);
400 if (!ok) {
401 /* We special case this - as when a Windows machine
402 is parsing a path is steps through the components
403 one at a time - if a component fails it expects
404 ERRbadpath, not ERRbadfile.
406 if(errno == ENOENT) {
407 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
410 return(UNIXERROR(ERRDOS,ERRbadpath));
413 outsize = set_message(outbuf,0,0,True);
415 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
417 END_PROFILE(SMBchkpth);
418 return(outsize);
422 /****************************************************************************
423 reply to a getatr
424 ****************************************************************************/
425 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
427 pstring fname;
428 int outsize = 0;
429 SMB_STRUCT_STAT sbuf;
430 BOOL ok = False;
431 int mode=0;
432 SMB_OFF_T size=0;
433 time_t mtime=0;
434 BOOL bad_path = False;
435 char *p;
436 START_PROFILE(SMBgetatr);
438 p = smb_buf(inbuf) + 1;
439 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
441 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
443 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
444 under WfWg - weird! */
445 if (! (*fname))
447 mode = aHIDDEN | aDIR;
448 if (!CAN_WRITE(conn)) mode |= aRONLY;
449 size = 0;
450 mtime = 0;
451 ok = True;
453 else
455 unix_convert(fname,conn,0,&bad_path,&sbuf);
456 if (check_name(fname,conn))
458 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
460 mode = dos_mode(conn,fname,&sbuf);
461 size = sbuf.st_size;
462 mtime = sbuf.st_mtime;
463 if (mode & aDIR)
464 size = 0;
465 ok = True;
467 else
468 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
472 if (!ok)
474 set_bad_path_error(errno, bad_path);
475 END_PROFILE(SMBgetatr);
476 return(UNIXERROR(ERRDOS,ERRbadfile));
479 outsize = set_message(outbuf,10,0,True);
481 SSVAL(outbuf,smb_vwv0,mode);
482 if(lp_dos_filetime_resolution(SNUM(conn)) )
483 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
484 else
485 put_dos_date3(outbuf,smb_vwv1,mtime);
486 SIVAL(outbuf,smb_vwv3,(uint32)size);
488 if (Protocol >= PROTOCOL_NT1)
489 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
491 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
493 END_PROFILE(SMBgetatr);
494 return(outsize);
498 /****************************************************************************
499 reply to a setatr
500 ****************************************************************************/
501 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
503 pstring fname;
504 int outsize = 0;
505 BOOL ok=False;
506 int mode;
507 time_t mtime;
508 SMB_STRUCT_STAT sbuf;
509 BOOL bad_path = False;
510 char *p;
512 START_PROFILE(SMBsetatr);
514 p = smb_buf(inbuf) + 1;
515 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
516 unix_convert(fname,conn,0,&bad_path,&sbuf);
518 mode = SVAL(inbuf,smb_vwv0);
519 mtime = make_unix_date3(inbuf+smb_vwv1);
521 if (VALID_STAT_OF_DIR(sbuf))
522 mode |= aDIR;
523 else
524 mode &= ~aDIR;
526 if (check_name(fname,conn))
527 ok = (file_chmod(conn,fname,mode,NULL) == 0);
528 if (ok)
529 ok = set_filetime(conn,fname,mtime);
531 if (!ok)
533 set_bad_path_error(errno, bad_path);
534 END_PROFILE(SMBsetatr);
535 return(UNIXERROR(ERRDOS,ERRnoaccess));
538 outsize = set_message(outbuf,0,0,True);
540 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
542 END_PROFILE(SMBsetatr);
543 return(outsize);
547 /****************************************************************************
548 reply to a dskattr
549 ****************************************************************************/
550 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
552 int outsize = 0;
553 SMB_BIG_UINT dfree,dsize,bsize;
554 START_PROFILE(SMBdskattr);
556 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
558 outsize = set_message(outbuf,5,0,True);
560 if (Protocol <= PROTOCOL_LANMAN2) {
561 double total_space, free_space;
562 /* we need to scale this to a number that DOS6 can handle. We
563 use floating point so we can handle large drives on systems
564 that don't have 64 bit integers
566 we end up displaying a maximum of 2G to DOS systems
568 total_space = dsize * (double)bsize;
569 free_space = dfree * (double)bsize;
571 dsize = (total_space+63*512) / (64*512);
572 dfree = (free_space+63*512) / (64*512);
574 if (dsize > 0xFFFF) dsize = 0xFFFF;
575 if (dfree > 0xFFFF) dfree = 0xFFFF;
577 SSVAL(outbuf,smb_vwv0,dsize);
578 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
579 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
580 SSVAL(outbuf,smb_vwv3,dfree);
581 } else {
582 SSVAL(outbuf,smb_vwv0,dsize);
583 SSVAL(outbuf,smb_vwv1,bsize/512);
584 SSVAL(outbuf,smb_vwv2,512);
585 SSVAL(outbuf,smb_vwv3,dfree);
588 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
590 END_PROFILE(SMBdskattr);
591 return(outsize);
595 /****************************************************************************
596 reply to a search
597 Can be called from SMBsearch, SMBffirst or SMBfunique.
598 ****************************************************************************/
599 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
601 pstring mask;
602 pstring directory;
603 pstring fname;
604 SMB_OFF_T size;
605 int mode;
606 time_t date;
607 int dirtype;
608 int outsize = 0;
609 int numentries = 0;
610 BOOL finished = False;
611 int maxentries;
612 int i;
613 char *p;
614 BOOL ok = False;
615 int status_len;
616 pstring path;
617 char status[21];
618 int dptr_num= -1;
619 BOOL check_descend = False;
620 BOOL expect_close = False;
621 BOOL can_open = True;
622 BOOL bad_path = False;
623 START_PROFILE(SMBsearch);
625 *mask = *directory = *fname = 0;
627 /* If we were called as SMBffirst then we must expect close. */
628 if(CVAL(inbuf,smb_com) == SMBffirst)
629 expect_close = True;
631 outsize = set_message(outbuf,1,3,True);
632 maxentries = SVAL(inbuf,smb_vwv0);
633 dirtype = SVAL(inbuf,smb_vwv1);
634 p = smb_buf(inbuf) + 1;
635 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
636 p++;
637 status_len = SVAL(p, 0);
638 p += 2;
640 /* dirtype &= ~aDIR; */
642 if (status_len == 0)
644 SMB_STRUCT_STAT sbuf;
645 pstring dir2;
647 pstrcpy(directory,path);
648 pstrcpy(dir2,path);
649 unix_convert(directory,conn,0,&bad_path,&sbuf);
650 unix_format(dir2);
652 if (!check_name(directory,conn))
653 can_open = False;
655 p = strrchr_m(dir2,'/');
656 if (p == NULL)
658 pstrcpy(mask,dir2);
659 *dir2 = 0;
661 else
663 *p = 0;
664 pstrcpy(mask,p+1);
667 p = strrchr_m(directory,'/');
668 if (!p)
669 *directory = 0;
670 else
671 *p = 0;
673 if (strlen(directory) == 0)
674 pstrcpy(directory,"./");
675 memset((char *)status,'\0',21);
676 SCVAL(status,0,dirtype);
678 else
680 memcpy(status,p,21);
681 dirtype = CVAL(status,0) & 0x1F;
682 conn->dirptr = dptr_fetch(status+12,&dptr_num);
683 if (!conn->dirptr)
684 goto SearchEmpty;
685 string_set(&conn->dirpath,dptr_path(dptr_num));
686 fstrcpy(mask, dptr_wcard(dptr_num));
689 if (can_open)
691 p = smb_buf(outbuf) + 3;
693 ok = True;
695 if (status_len == 0)
697 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
698 if (dptr_num < 0)
700 if(dptr_num == -2)
702 set_bad_path_error(errno, bad_path);
703 END_PROFILE(SMBsearch);
704 return (UNIXERROR(ERRDOS,ERRnofids));
706 END_PROFILE(SMBsearch);
707 return ERROR_DOS(ERRDOS,ERRnofids);
709 dptr_set_wcard(dptr_num, strdup(mask));
712 DEBUG(4,("dptr_num is %d\n",dptr_num));
714 if (ok)
716 if ((dirtype&0x1F) == aVOLID)
718 memcpy(p,status,21);
719 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
720 dptr_fill(p+12,dptr_num);
721 if (dptr_zero(p+12) && (status_len==0))
722 numentries = 1;
723 else
724 numentries = 0;
725 p += DIR_STRUCT_SIZE;
727 else
729 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
730 conn->dirpath,lp_dontdescend(SNUM(conn))));
731 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
732 check_descend = True;
734 for (i=numentries;(i<maxentries) && !finished;i++)
736 finished =
737 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
738 if (!finished)
740 memcpy(p,status,21);
741 make_dir_struct(p,mask,fname,size,mode,date);
742 dptr_fill(p+12,dptr_num);
743 numentries++;
745 p += DIR_STRUCT_SIZE;
748 } /* if (ok ) */
752 SearchEmpty:
754 if (numentries == 0 || !ok)
756 SCVAL(outbuf,smb_rcls,ERRDOS);
757 SSVAL(outbuf,smb_err,ERRnofiles);
758 dptr_close(&dptr_num);
761 /* If we were called as SMBffirst with smb_search_id == NULL
762 and no entries were found then return error and close dirptr
763 (X/Open spec) */
765 if(ok && expect_close && numentries == 0 && status_len == 0)
767 SCVAL(outbuf,smb_rcls,ERRDOS);
768 SSVAL(outbuf,smb_err,ERRnofiles);
769 /* Also close the dptr - we know it's gone */
770 dptr_close(&dptr_num);
773 /* If we were called as SMBfunique, then we can close the dirptr now ! */
774 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
775 dptr_close(&dptr_num);
777 SSVAL(outbuf,smb_vwv0,numentries);
778 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
779 SCVAL(smb_buf(outbuf),0,5);
780 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
782 if (Protocol >= PROTOCOL_NT1)
783 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
785 outsize += DIR_STRUCT_SIZE*numentries;
786 smb_setlen(outbuf,outsize - 4);
788 if ((! *directory) && dptr_path(dptr_num))
789 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
791 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
792 smb_fn_name(CVAL(inbuf,smb_com)),
793 mask, directory, dirtype, numentries, maxentries ) );
795 END_PROFILE(SMBsearch);
796 return(outsize);
800 /****************************************************************************
801 reply to a fclose (stop directory search)
802 ****************************************************************************/
803 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 int outsize = 0;
806 int status_len;
807 pstring path;
808 char status[21];
809 int dptr_num= -2;
810 char *p;
812 START_PROFILE(SMBfclose);
814 outsize = set_message(outbuf,1,0,True);
815 p = smb_buf(inbuf) + 1;
816 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
817 p++;
818 status_len = SVAL(p,0);
819 p += 2;
821 if (status_len == 0) {
822 END_PROFILE(SMBfclose);
823 return ERROR_DOS(ERRSRV,ERRsrverror);
826 memcpy(status,p,21);
828 if(dptr_fetch(status+12,&dptr_num)) {
829 /* Close the dptr - we know it's gone */
830 dptr_close(&dptr_num);
833 SSVAL(outbuf,smb_vwv0,0);
835 DEBUG(3,("search close\n"));
837 END_PROFILE(SMBfclose);
838 return(outsize);
842 /****************************************************************************
843 reply to an open
844 ****************************************************************************/
846 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
848 pstring fname;
849 int outsize = 0;
850 int fmode=0;
851 int share_mode;
852 SMB_OFF_T size = 0;
853 time_t mtime=0;
854 mode_t unixmode;
855 int rmode=0;
856 SMB_STRUCT_STAT sbuf;
857 BOOL bad_path = False;
858 files_struct *fsp;
859 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
860 START_PROFILE(SMBopen);
862 share_mode = SVAL(inbuf,smb_vwv0);
864 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
866 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
868 unix_convert(fname,conn,0,&bad_path,&sbuf);
870 unixmode = unix_mode(conn,aARCH,fname);
872 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
873 unixmode, oplock_request,&rmode,NULL);
875 if (!fsp)
877 set_bad_path_error(errno, bad_path);
878 END_PROFILE(SMBopen);
879 return(UNIXERROR(ERRDOS,ERRnoaccess));
882 size = sbuf.st_size;
883 fmode = dos_mode(conn,fname,&sbuf);
884 mtime = sbuf.st_mtime;
886 if (fmode & aDIR) {
887 DEBUG(3,("attempt to open a directory %s\n",fname));
888 close_file(fsp,False);
889 END_PROFILE(SMBopen);
890 return ERROR_DOS(ERRDOS,ERRnoaccess);
893 outsize = set_message(outbuf,7,0,True);
894 SSVAL(outbuf,smb_vwv0,fsp->fnum);
895 SSVAL(outbuf,smb_vwv1,fmode);
896 if(lp_dos_filetime_resolution(SNUM(conn)) )
897 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
898 else
899 put_dos_date3(outbuf,smb_vwv2,mtime);
900 SIVAL(outbuf,smb_vwv4,(uint32)size);
901 SSVAL(outbuf,smb_vwv6,rmode);
903 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
904 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
907 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
908 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
909 END_PROFILE(SMBopen);
910 return(outsize);
914 /****************************************************************************
915 reply to an open and X
916 ****************************************************************************/
917 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
919 pstring fname;
920 int smb_mode = SVAL(inbuf,smb_vwv3);
921 int smb_attr = SVAL(inbuf,smb_vwv5);
922 /* Breakout the oplock request bits so we can set the
923 reply bits separately. */
924 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
925 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
926 BOOL oplock_request = ex_oplock_request | core_oplock_request;
927 #if 0
928 int open_flags = SVAL(inbuf,smb_vwv2);
929 int smb_sattr = SVAL(inbuf,smb_vwv4);
930 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
931 #endif
932 int smb_ofun = SVAL(inbuf,smb_vwv8);
933 mode_t unixmode;
934 SMB_OFF_T size=0;
935 int fmode=0,mtime=0,rmode=0;
936 SMB_STRUCT_STAT sbuf;
937 int smb_action = 0;
938 BOOL bad_path = False;
939 files_struct *fsp;
940 START_PROFILE(SMBopenX);
942 /* If it's an IPC, pass off the pipe handler. */
943 if (IS_IPC(conn)) {
944 if (lp_nt_pipe_support()) {
945 END_PROFILE(SMBopenX);
946 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
947 } else {
948 END_PROFILE(SMBopenX);
949 return ERROR_DOS(ERRSRV,ERRaccess);
953 /* XXXX we need to handle passed times, sattr and flags */
954 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
956 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
958 unix_convert(fname,conn,0,&bad_path,&sbuf);
960 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
962 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
963 oplock_request, &rmode,&smb_action);
965 if (!fsp)
967 set_bad_path_error(errno, bad_path);
968 END_PROFILE(SMBopenX);
969 return(UNIXERROR(ERRDOS,ERRnoaccess));
972 size = sbuf.st_size;
973 fmode = dos_mode(conn,fname,&sbuf);
974 mtime = sbuf.st_mtime;
975 if (fmode & aDIR) {
976 close_file(fsp,False);
977 END_PROFILE(SMBopenX);
978 return ERROR_DOS(ERRDOS,ERRnoaccess);
981 /* If the caller set the extended oplock request bit
982 and we granted one (by whatever means) - set the
983 correct bit for extended oplock reply.
986 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
987 smb_action |= EXTENDED_OPLOCK_GRANTED;
990 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
991 smb_action |= EXTENDED_OPLOCK_GRANTED;
994 /* If the caller set the core oplock request bit
995 and we granted one (by whatever means) - set the
996 correct bit for core oplock reply.
999 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1000 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1003 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1004 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1007 set_message(outbuf,15,0,True);
1008 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1009 SSVAL(outbuf,smb_vwv3,fmode);
1010 if(lp_dos_filetime_resolution(SNUM(conn)) )
1011 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1012 else
1013 put_dos_date3(outbuf,smb_vwv4,mtime);
1014 SIVAL(outbuf,smb_vwv6,(uint32)size);
1015 SSVAL(outbuf,smb_vwv8,rmode);
1016 SSVAL(outbuf,smb_vwv11,smb_action);
1018 END_PROFILE(SMBopenX);
1019 return chain_reply(inbuf,outbuf,length,bufsize);
1023 /****************************************************************************
1024 reply to a SMBulogoffX
1025 ****************************************************************************/
1026 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1028 uint16 vuid = SVAL(inbuf,smb_uid);
1029 user_struct *vuser = get_valid_user_struct(vuid);
1030 START_PROFILE(SMBulogoffX);
1032 if(vuser == 0) {
1033 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1036 /* in user level security we are supposed to close any files
1037 open by this user */
1038 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1039 file_close_user(vuid);
1042 invalidate_vuid(vuid);
1044 set_message(outbuf,2,0,True);
1046 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1048 END_PROFILE(SMBulogoffX);
1049 return chain_reply(inbuf,outbuf,length,bufsize);
1053 /****************************************************************************
1054 reply to a mknew or a create
1055 ****************************************************************************/
1056 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1058 pstring fname;
1059 int com;
1060 int outsize = 0;
1061 int createmode;
1062 mode_t unixmode;
1063 int ofun = 0;
1064 BOOL bad_path = False;
1065 files_struct *fsp;
1066 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1067 SMB_STRUCT_STAT sbuf;
1068 START_PROFILE(SMBcreate);
1070 com = SVAL(inbuf,smb_com);
1072 createmode = SVAL(inbuf,smb_vwv0);
1073 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1075 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1077 unix_convert(fname,conn,0,&bad_path,&sbuf);
1079 if (createmode & aVOLID) {
1080 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1083 unixmode = unix_mode(conn,createmode,fname);
1085 if(com == SMBmknew)
1087 /* We should fail if file exists. */
1088 ofun = FILE_CREATE_IF_NOT_EXIST;
1090 else
1092 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1093 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1096 /* Open file in dos compatibility share mode. */
1097 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1098 ofun, unixmode, oplock_request, NULL, NULL);
1100 if (!fsp)
1102 set_bad_path_error(errno, bad_path);
1103 END_PROFILE(SMBcreate);
1104 return(UNIXERROR(ERRDOS,ERRnoaccess));
1107 outsize = set_message(outbuf,1,0,True);
1108 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1110 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1111 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1114 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1115 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1117 DEBUG( 2, ( "new file %s\n", fname ) );
1118 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1119 fname, fsp->fd, createmode, (int)unixmode ) );
1121 END_PROFILE(SMBcreate);
1122 return(outsize);
1126 /****************************************************************************
1127 reply to a create temporary file
1128 ****************************************************************************/
1129 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1131 pstring fname;
1132 int outsize = 0;
1133 int createmode;
1134 mode_t unixmode;
1135 BOOL bad_path = False;
1136 files_struct *fsp;
1137 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1138 int tmpfd;
1139 SMB_STRUCT_STAT sbuf;
1140 char *p, *s;
1142 START_PROFILE(SMBctemp);
1144 createmode = SVAL(inbuf,smb_vwv0);
1145 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1146 pstrcat(fname,"\\TMXXXXXX");
1148 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1150 unix_convert(fname,conn,0,&bad_path,&sbuf);
1152 unixmode = unix_mode(conn,createmode,fname);
1154 tmpfd = smb_mkstemp(fname);
1155 if (tmpfd == -1) {
1156 END_PROFILE(SMBctemp);
1157 return(UNIXERROR(ERRDOS,ERRnoaccess));
1160 vfs_stat(conn,fname,&sbuf);
1162 /* Open file in dos compatibility share mode. */
1163 /* We should fail if file does not exist. */
1164 fsp = open_file_shared(conn,fname,&sbuf,
1165 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1166 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1167 unixmode, oplock_request, NULL, NULL);
1169 /* close fd from smb_mkstemp() */
1170 close(tmpfd);
1172 if (!fsp) {
1173 set_bad_path_error(errno, bad_path);
1174 END_PROFILE(SMBctemp);
1175 return(UNIXERROR(ERRDOS,ERRnoaccess));
1178 outsize = set_message(outbuf,1,0,True);
1179 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1181 /* the returned filename is relative to the directory */
1182 s = strrchr_m(fname, '/');
1183 if (!s) {
1184 s = fname;
1185 } else {
1186 s++;
1189 p = smb_buf(outbuf);
1190 SSVALS(p, 0, -1); /* what is this? not in spec */
1191 SSVAL(p, 2, strlen(s));
1192 p += 4;
1193 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1194 outsize = set_message_end(outbuf, p);
1196 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1197 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1200 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1201 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1203 DEBUG( 2, ( "created temp file %s\n", fname ) );
1204 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1205 fname, fsp->fd, createmode, (int)unixmode ) );
1207 END_PROFILE(SMBctemp);
1208 return(outsize);
1211 /*******************************************************************
1212 Check if a user is allowed to rename a file.
1213 ********************************************************************/
1215 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1217 int smb_action;
1218 int access_mode;
1219 files_struct *fsp;
1221 if (!CAN_WRITE(conn))
1222 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1224 if (S_ISDIR(pst->st_mode))
1225 return NT_STATUS_OK;
1227 /* We need a better way to return NT status codes from open... */
1228 unix_ERR_class = 0;
1229 unix_ERR_code = 0;
1231 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1232 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1234 if (!fsp) {
1235 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1236 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1237 ret = NT_STATUS_SHARING_VIOLATION;
1238 unix_ERR_class = 0;
1239 unix_ERR_code = 0;
1240 return ret;
1242 close_file(fsp,False);
1243 return NT_STATUS_OK;
1246 /*******************************************************************
1247 Check if a user is allowed to delete a file.
1248 ********************************************************************/
1250 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1252 SMB_STRUCT_STAT sbuf;
1253 int fmode;
1254 int smb_action;
1255 int access_mode;
1256 files_struct *fsp;
1258 if (!CAN_WRITE(conn))
1259 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1261 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1262 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1264 fmode = dos_mode(conn,fname,&sbuf);
1265 if (fmode & aDIR)
1266 return NT_STATUS_FILE_IS_A_DIRECTORY;
1267 if (!lp_delete_readonly(SNUM(conn))) {
1268 if (fmode & aRONLY)
1269 return NT_STATUS_CANNOT_DELETE;
1271 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1272 return NT_STATUS_CANNOT_DELETE;
1274 /* We need a better way to return NT status codes from open... */
1275 unix_ERR_class = 0;
1276 unix_ERR_code = 0;
1278 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1279 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1281 if (!fsp) {
1282 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1283 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1284 ret = NT_STATUS_SHARING_VIOLATION;
1285 unix_ERR_class = 0;
1286 unix_ERR_code = 0;
1287 return ret;
1289 close_file(fsp,False);
1290 return NT_STATUS_OK;
1293 /****************************************************************************
1294 The guts of the unlink command, split out so it may be called by the NT SMB
1295 code.
1296 ****************************************************************************/
1298 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1300 pstring directory;
1301 pstring mask;
1302 char *p;
1303 int count=0;
1304 NTSTATUS error = NT_STATUS_OK;
1305 BOOL has_wild;
1306 BOOL bad_path = False;
1307 BOOL rc = True;
1308 SMB_STRUCT_STAT sbuf;
1310 *directory = *mask = 0;
1312 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1314 p = strrchr_m(name,'/');
1315 if (!p) {
1316 pstrcpy(directory,".");
1317 pstrcpy(mask,name);
1318 } else {
1319 *p = 0;
1320 pstrcpy(directory,name);
1321 pstrcpy(mask,p+1);
1325 * We should only check the mangled cache
1326 * here if unix_convert failed. This means
1327 * that the path in 'mask' doesn't exist
1328 * on the file system and so we need to look
1329 * for a possible mangle. This patch from
1330 * Tine Smukavec <valentin.smukavec@hermes.si>.
1333 if (!rc && mangle_is_mangled(mask))
1334 mangle_check_cache( mask );
1336 has_wild = ms_has_wild(mask);
1338 if (!has_wild) {
1339 pstrcat(directory,"/");
1340 pstrcat(directory,mask);
1341 error = can_delete(directory,conn,dirtype);
1342 if (!NT_STATUS_IS_OK(error)) return error;
1344 if (vfs_unlink(conn,directory) == 0) {
1345 count++;
1347 } else {
1348 void *dirptr = NULL;
1349 char *dname;
1351 if (check_name(directory,conn))
1352 dirptr = OpenDir(conn, directory, True);
1354 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1355 the pattern matches against the long name, otherwise the short name
1356 We don't implement this yet XXXX
1359 if (dirptr) {
1360 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1362 if (strequal(mask,"????????.???"))
1363 pstrcpy(mask,"*");
1365 while ((dname = ReadDirName(dirptr))) {
1366 pstring fname;
1367 pstrcpy(fname,dname);
1369 if(!mask_match(fname, mask, case_sensitive)) continue;
1371 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1372 error = can_delete(fname,conn,dirtype);
1373 if (!NT_STATUS_IS_OK(error)) continue;
1374 if (vfs_unlink(conn,fname) == 0) count++;
1375 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1377 CloseDir(dirptr);
1381 if (count == 0 && NT_STATUS_IS_OK(error)) {
1382 error = map_nt_error_from_unix(errno);
1385 return error;
1388 /****************************************************************************
1389 Reply to a unlink
1390 ****************************************************************************/
1392 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1393 int dum_buffsize)
1395 int outsize = 0;
1396 pstring name;
1397 int dirtype;
1398 NTSTATUS status;
1399 START_PROFILE(SMBunlink);
1401 dirtype = SVAL(inbuf,smb_vwv0);
1403 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1405 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1407 DEBUG(3,("reply_unlink : %s\n",name));
1409 status = unlink_internals(conn, dirtype, name);
1410 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1413 * Win2k needs a changenotify request response before it will
1414 * update after a rename..
1416 process_pending_change_notify_queue((time_t)0);
1418 outsize = set_message(outbuf,0,0,True);
1420 END_PROFILE(SMBunlink);
1421 return outsize;
1424 /****************************************************************************
1425 Fail for readbraw.
1426 ****************************************************************************/
1428 void fail_readraw(void)
1430 pstring errstr;
1431 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1432 strerror(errno) );
1433 exit_server(errstr);
1436 /****************************************************************************
1437 Reply to a readbraw (core+ protocol).
1438 ****************************************************************************/
1440 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1442 ssize_t maxcount,mincount;
1443 size_t nread = 0;
1444 SMB_OFF_T startpos;
1445 char *header = outbuf;
1446 ssize_t ret=0;
1447 files_struct *fsp;
1448 START_PROFILE(SMBreadbraw);
1451 * Special check if an oplock break has been issued
1452 * and the readraw request croses on the wire, we must
1453 * return a zero length response here.
1456 if(global_oplock_break) {
1457 _smb_setlen(header,0);
1458 if (write_data(smbd_server_fd(),header,4) != 4)
1459 fail_readraw();
1460 DEBUG(5,("readbraw - oplock break finished\n"));
1461 END_PROFILE(SMBreadbraw);
1462 return -1;
1465 fsp = file_fsp(inbuf,smb_vwv0);
1467 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1469 * fsp could be NULL here so use the value from the packet. JRA.
1471 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1472 _smb_setlen(header,0);
1473 if (write_data(smbd_server_fd(),header,4) != 4)
1474 fail_readraw();
1475 END_PROFILE(SMBreadbraw);
1476 return(-1);
1479 CHECK_FSP(fsp,conn);
1481 flush_write_cache(fsp, READRAW_FLUSH);
1483 startpos = IVAL(inbuf,smb_vwv1);
1484 if(CVAL(inbuf,smb_wct) == 10) {
1486 * This is a large offset (64 bit) read.
1488 #ifdef LARGE_SMB_OFF_T
1490 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1492 #else /* !LARGE_SMB_OFF_T */
1495 * Ensure we haven't been sent a >32 bit offset.
1498 if(IVAL(inbuf,smb_vwv8) != 0) {
1499 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1500 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1501 _smb_setlen(header,0);
1502 if (write_data(smbd_server_fd(),header,4) != 4)
1503 fail_readraw();
1504 END_PROFILE(SMBreadbraw);
1505 return(-1);
1508 #endif /* LARGE_SMB_OFF_T */
1510 if(startpos < 0) {
1511 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1512 _smb_setlen(header,0);
1513 if (write_data(smbd_server_fd(),header,4) != 4)
1514 fail_readraw();
1515 END_PROFILE(SMBreadbraw);
1516 return(-1);
1519 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1520 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1522 /* ensure we don't overrun the packet size */
1523 maxcount = MIN(65535,maxcount);
1524 maxcount = MAX(mincount,maxcount);
1526 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1527 SMB_OFF_T size = fsp->size;
1528 SMB_OFF_T sizeneeded = startpos + maxcount;
1530 if (size < sizeneeded) {
1531 SMB_STRUCT_STAT st;
1532 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1533 size = st.st_size;
1534 if (!fsp->can_write)
1535 fsp->size = size;
1538 if (startpos >= size)
1539 nread = 0;
1540 else
1541 nread = MIN(maxcount,(size - startpos));
1544 if (nread < mincount)
1545 nread = 0;
1547 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1548 (int)maxcount, (int)mincount, (int)nread ) );
1550 if (nread > 0) {
1551 ret = read_file(fsp,header+4,startpos,nread);
1552 if (ret < mincount)
1553 ret = 0;
1556 _smb_setlen(header,ret);
1557 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1558 fail_readraw();
1560 DEBUG(5,("readbraw finished\n"));
1561 END_PROFILE(SMBreadbraw);
1562 return -1;
1565 /****************************************************************************
1566 reply to a lockread (core+ protocol)
1567 ****************************************************************************/
1568 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1570 ssize_t nread = -1;
1571 char *data;
1572 int outsize = 0;
1573 SMB_OFF_T startpos;
1574 size_t numtoread;
1575 NTSTATUS status;
1576 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1577 START_PROFILE(SMBlockread);
1579 CHECK_FSP(fsp,conn);
1580 CHECK_READ(fsp);
1582 release_level_2_oplocks_on_change(fsp);
1584 numtoread = SVAL(inbuf,smb_vwv1);
1585 startpos = IVAL(inbuf,smb_vwv2);
1587 outsize = set_message(outbuf,5,3,True);
1588 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1589 data = smb_buf(outbuf) + 3;
1592 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1593 * protocol request that predates the read/write lock concept.
1594 * Thus instead of asking for a read lock here we need to ask
1595 * for a write lock. JRA.
1598 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1599 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1601 if (NT_STATUS_V(status)) {
1602 if (lp_blocking_locks(SNUM(conn))) {
1604 * A blocking lock was requested. Package up
1605 * this smb into a queued request and push it
1606 * onto the blocking lock queue.
1608 if(push_blocking_lock_request(inbuf, length, -1, 0))
1609 END_PROFILE(SMBlockread);
1610 return -1;
1612 END_PROFILE(SMBlockread);
1613 return ERROR_NT(status);
1616 nread = read_file(fsp,data,startpos,numtoread);
1618 if (nread < 0) {
1619 END_PROFILE(SMBlockread);
1620 return(UNIXERROR(ERRDOS,ERRnoaccess));
1623 outsize += nread;
1624 SSVAL(outbuf,smb_vwv0,nread);
1625 SSVAL(outbuf,smb_vwv5,nread+3);
1626 SSVAL(smb_buf(outbuf),1,nread);
1628 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1629 fsp->fnum, (int)numtoread, (int)nread));
1631 END_PROFILE(SMBlockread);
1632 return(outsize);
1636 /****************************************************************************
1637 reply to a read
1638 ****************************************************************************/
1640 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1642 size_t numtoread;
1643 ssize_t nread = 0;
1644 char *data;
1645 SMB_OFF_T startpos;
1646 int outsize = 0;
1647 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1648 START_PROFILE(SMBread);
1650 CHECK_FSP(fsp,conn);
1651 CHECK_READ(fsp);
1653 numtoread = SVAL(inbuf,smb_vwv1);
1654 startpos = IVAL(inbuf,smb_vwv2);
1657 outsize = set_message(outbuf,5,3,True);
1658 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1659 data = smb_buf(outbuf) + 3;
1661 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1662 END_PROFILE(SMBread);
1663 return ERROR_DOS(ERRDOS,ERRlock);
1666 if (numtoread > 0)
1667 nread = read_file(fsp,data,startpos,numtoread);
1669 if (nread < 0) {
1670 END_PROFILE(SMBread);
1671 return(UNIXERROR(ERRDOS,ERRnoaccess));
1674 outsize += nread;
1675 SSVAL(outbuf,smb_vwv0,nread);
1676 SSVAL(outbuf,smb_vwv5,nread+3);
1677 SCVAL(smb_buf(outbuf),0,1);
1678 SSVAL(smb_buf(outbuf),1,nread);
1680 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1681 fsp->fnum, (int)numtoread, (int)nread ) );
1683 END_PROFILE(SMBread);
1684 return(outsize);
1688 /****************************************************************************
1689 reply to a read and X
1690 ****************************************************************************/
1691 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1693 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1694 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1695 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1696 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1697 ssize_t nread = -1;
1698 char *data;
1699 START_PROFILE(SMBreadX);
1701 /* If it's an IPC, pass off the pipe handler. */
1702 if (IS_IPC(conn)) {
1703 END_PROFILE(SMBreadX);
1704 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1707 CHECK_FSP(fsp,conn);
1708 CHECK_READ(fsp);
1710 set_message(outbuf,12,0,True);
1711 data = smb_buf(outbuf);
1713 if(CVAL(inbuf,smb_wct) == 12) {
1714 #ifdef LARGE_SMB_OFF_T
1716 * This is a large offset (64 bit) read.
1718 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1720 #else /* !LARGE_SMB_OFF_T */
1723 * Ensure we haven't been sent a >32 bit offset.
1726 if(IVAL(inbuf,smb_vwv10) != 0) {
1727 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1728 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1729 END_PROFILE(SMBreadX);
1730 return ERROR_DOS(ERRDOS,ERRbadaccess);
1733 #endif /* LARGE_SMB_OFF_T */
1737 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1738 END_PROFILE(SMBreadX);
1739 return ERROR_DOS(ERRDOS,ERRlock);
1741 nread = read_file(fsp,data,startpos,smb_maxcnt);
1743 if (nread < 0) {
1744 END_PROFILE(SMBreadX);
1745 return(UNIXERROR(ERRDOS,ERRnoaccess));
1748 SSVAL(outbuf,smb_vwv5,nread);
1749 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1750 SSVAL(smb_buf(outbuf),-2,nread);
1752 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1753 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
1755 END_PROFILE(SMBreadX);
1756 return chain_reply(inbuf,outbuf,length,bufsize);
1759 /****************************************************************************
1760 reply to a writebraw (core+ or LANMAN1.0 protocol)
1761 ****************************************************************************/
1763 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1765 ssize_t nwritten=0;
1766 ssize_t total_written=0;
1767 size_t numtowrite=0;
1768 size_t tcount;
1769 SMB_OFF_T startpos;
1770 char *data=NULL;
1771 BOOL write_through;
1772 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1773 int outsize = 0;
1774 START_PROFILE(SMBwritebraw);
1776 CHECK_FSP(fsp,conn);
1777 CHECK_WRITE(fsp);
1779 tcount = IVAL(inbuf,smb_vwv1);
1780 startpos = IVAL(inbuf,smb_vwv3);
1781 write_through = BITSETW(inbuf+smb_vwv7,0);
1783 /* We have to deal with slightly different formats depending
1784 on whether we are using the core+ or lanman1.0 protocol */
1786 if(Protocol <= PROTOCOL_COREPLUS) {
1787 numtowrite = SVAL(smb_buf(inbuf),-2);
1788 data = smb_buf(inbuf);
1789 } else {
1790 numtowrite = SVAL(inbuf,smb_vwv10);
1791 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1794 /* force the error type */
1795 SCVAL(inbuf,smb_com,SMBwritec);
1796 SCVAL(outbuf,smb_com,SMBwritec);
1798 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1799 END_PROFILE(SMBwritebraw);
1800 return(ERROR_DOS(ERRDOS,ERRlock));
1803 if (numtowrite>0)
1804 nwritten = write_file(fsp,data,startpos,numtowrite);
1806 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1807 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1809 if (nwritten < numtowrite) {
1810 END_PROFILE(SMBwritebraw);
1811 return(UNIXERROR(ERRHRD,ERRdiskfull));
1814 total_written = nwritten;
1816 /* Return a message to the redirector to tell it to send more bytes */
1817 SCVAL(outbuf,smb_com,SMBwritebraw);
1818 SSVALS(outbuf,smb_vwv0,-1);
1819 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1820 if (!send_smb(smbd_server_fd(),outbuf))
1821 exit_server("reply_writebraw: send_smb failed.");
1823 /* Now read the raw data into the buffer and write it */
1824 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1825 exit_server("secondary writebraw failed");
1828 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1829 numtowrite = smb_len(inbuf);
1831 /* Set up outbuf to return the correct return */
1832 outsize = set_message(outbuf,1,0,True);
1833 SCVAL(outbuf,smb_com,SMBwritec);
1834 SSVAL(outbuf,smb_vwv0,total_written);
1836 if (numtowrite != 0) {
1838 if (numtowrite > BUFFER_SIZE) {
1839 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1840 (unsigned int)numtowrite ));
1841 exit_server("secondary writebraw failed");
1844 if (tcount > nwritten+numtowrite) {
1845 DEBUG(3,("Client overestimated the write %d %d %d\n",
1846 (int)tcount,(int)nwritten,(int)numtowrite));
1849 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1850 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1851 strerror(errno) ));
1852 exit_server("secondary writebraw failed");
1855 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1857 if (nwritten < (ssize_t)numtowrite) {
1858 SCVAL(outbuf,smb_rcls,ERRHRD);
1859 SSVAL(outbuf,smb_err,ERRdiskfull);
1862 if (nwritten > 0)
1863 total_written += nwritten;
1866 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1867 sync_file(conn,fsp);
1869 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1870 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1872 /* we won't return a status if write through is not selected - this follows what WfWg does */
1873 END_PROFILE(SMBwritebraw);
1874 if (!write_through && total_written==tcount) {
1876 #if RABBIT_PELLET_FIX
1878 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1879 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1881 if (!send_keepalive(smbd_server_fd()))
1882 exit_server("reply_writebraw: send of keepalive failed");
1883 #endif
1884 return(-1);
1887 return(outsize);
1890 /****************************************************************************
1891 reply to a writeunlock (core+)
1892 ****************************************************************************/
1894 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1895 int size, int dum_buffsize)
1897 ssize_t nwritten = -1;
1898 size_t numtowrite;
1899 SMB_OFF_T startpos;
1900 char *data;
1901 NTSTATUS status;
1902 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1903 int outsize = 0;
1904 START_PROFILE(SMBwriteunlock);
1906 CHECK_FSP(fsp,conn);
1907 CHECK_WRITE(fsp);
1909 numtowrite = SVAL(inbuf,smb_vwv1);
1910 startpos = IVAL(inbuf,smb_vwv2);
1911 data = smb_buf(inbuf) + 3;
1913 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1914 WRITE_LOCK,False)) {
1915 END_PROFILE(SMBwriteunlock);
1916 return ERROR_DOS(ERRDOS,ERRlock);
1919 /* The special X/Open SMB protocol handling of
1920 zero length writes is *NOT* done for
1921 this call */
1922 if(numtowrite == 0)
1923 nwritten = 0;
1924 else
1925 nwritten = write_file(fsp,data,startpos,numtowrite);
1927 if (lp_syncalways(SNUM(conn)))
1928 sync_file(conn,fsp);
1930 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1931 END_PROFILE(SMBwriteunlock);
1932 return(UNIXERROR(ERRDOS,ERRnoaccess));
1935 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
1936 (SMB_BIG_UINT)startpos);
1937 if (NT_STATUS_V(status)) {
1938 END_PROFILE(SMBwriteunlock);
1939 return ERROR_NT(status);
1942 outsize = set_message(outbuf,1,0,True);
1944 SSVAL(outbuf,smb_vwv0,nwritten);
1946 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
1947 fsp->fnum, (int)numtowrite, (int)nwritten));
1949 END_PROFILE(SMBwriteunlock);
1950 return outsize;
1954 /****************************************************************************
1955 Reply to a write.
1956 ****************************************************************************/
1958 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
1960 size_t numtowrite;
1961 ssize_t nwritten = -1;
1962 SMB_OFF_T startpos;
1963 char *data;
1964 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1965 int outsize = 0;
1966 START_PROFILE(SMBwrite);
1968 /* If it's an IPC, pass off the pipe handler. */
1969 if (IS_IPC(conn)) {
1970 END_PROFILE(SMBwrite);
1971 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
1974 CHECK_FSP(fsp,conn);
1975 CHECK_WRITE(fsp);
1977 numtowrite = SVAL(inbuf,smb_vwv1);
1978 startpos = IVAL(inbuf,smb_vwv2);
1979 data = smb_buf(inbuf) + 3;
1981 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1982 END_PROFILE(SMBwrite);
1983 return ERROR_DOS(ERRDOS,ERRlock);
1987 * X/Open SMB protocol says that if smb_vwv1 is
1988 * zero then the file size should be extended or
1989 * truncated to the size given in smb_vwv[2-3].
1992 if(numtowrite == 0) {
1994 * This is actually an allocate call, and set EOF. JRA.
1996 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
1997 if (nwritten < 0) {
1998 END_PROFILE(SMBwrite);
1999 return ERROR_NT(NT_STATUS_DISK_FULL);
2001 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2002 if (nwritten < 0) {
2003 END_PROFILE(SMBwrite);
2004 return ERROR_NT(NT_STATUS_DISK_FULL);
2006 } else
2007 nwritten = write_file(fsp,data,startpos,numtowrite);
2009 if (lp_syncalways(SNUM(conn)))
2010 sync_file(conn,fsp);
2012 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2013 END_PROFILE(SMBwrite);
2014 return(UNIXERROR(ERRDOS,ERRnoaccess));
2017 outsize = set_message(outbuf,1,0,True);
2019 SSVAL(outbuf,smb_vwv0,nwritten);
2021 if (nwritten < (ssize_t)numtowrite) {
2022 SCVAL(outbuf,smb_rcls,ERRHRD);
2023 SSVAL(outbuf,smb_err,ERRdiskfull);
2026 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2028 END_PROFILE(SMBwrite);
2029 return(outsize);
2033 /****************************************************************************
2034 reply to a write and X
2035 ****************************************************************************/
2036 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2038 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2039 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2040 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2041 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2042 ssize_t nwritten = -1;
2043 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2044 unsigned int smblen = smb_len(inbuf);
2045 char *data;
2046 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2047 START_PROFILE(SMBwriteX);
2049 /* If it's an IPC, pass off the pipe handler. */
2050 if (IS_IPC(conn)) {
2051 END_PROFILE(SMBwriteX);
2052 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2055 CHECK_FSP(fsp,conn);
2056 CHECK_WRITE(fsp);
2058 /* Deal with possible LARGE_WRITEX */
2059 if (large_writeX)
2060 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2062 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2063 END_PROFILE(SMBwriteX);
2064 return ERROR_DOS(ERRDOS,ERRbadmem);
2067 data = smb_base(inbuf) + smb_doff;
2069 if(CVAL(inbuf,smb_wct) == 14) {
2070 #ifdef LARGE_SMB_OFF_T
2072 * This is a large offset (64 bit) write.
2074 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2076 #else /* !LARGE_SMB_OFF_T */
2079 * Ensure we haven't been sent a >32 bit offset.
2082 if(IVAL(inbuf,smb_vwv12) != 0) {
2083 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2084 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2085 END_PROFILE(SMBwriteX);
2086 return ERROR_DOS(ERRDOS,ERRbadaccess);
2089 #endif /* LARGE_SMB_OFF_T */
2092 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2093 END_PROFILE(SMBwriteX);
2094 return ERROR_DOS(ERRDOS,ERRlock);
2097 /* X/Open SMB protocol says that, unlike SMBwrite
2098 if the length is zero then NO truncation is
2099 done, just a write of zero. To truncate a file,
2100 use SMBwrite. */
2101 if(numtowrite == 0)
2102 nwritten = 0;
2103 else
2104 nwritten = write_file(fsp,data,startpos,numtowrite);
2106 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2107 END_PROFILE(SMBwriteX);
2108 return(UNIXERROR(ERRDOS,ERRnoaccess));
2111 set_message(outbuf,6,0,True);
2113 SSVAL(outbuf,smb_vwv2,nwritten);
2114 if (large_writeX)
2115 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2117 if (nwritten < (ssize_t)numtowrite) {
2118 SCVAL(outbuf,smb_rcls,ERRHRD);
2119 SSVAL(outbuf,smb_err,ERRdiskfull);
2122 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2123 fsp->fnum, (int)numtowrite, (int)nwritten));
2125 if (lp_syncalways(SNUM(conn)) || write_through)
2126 sync_file(conn,fsp);
2128 END_PROFILE(SMBwriteX);
2129 return chain_reply(inbuf,outbuf,length,bufsize);
2133 /****************************************************************************
2134 reply to a lseek
2135 ****************************************************************************/
2137 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2139 SMB_OFF_T startpos;
2140 SMB_OFF_T res= -1;
2141 int mode,umode;
2142 int outsize = 0;
2143 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2144 START_PROFILE(SMBlseek);
2146 CHECK_FSP(fsp,conn);
2148 flush_write_cache(fsp, SEEK_FLUSH);
2150 mode = SVAL(inbuf,smb_vwv1) & 3;
2151 startpos = IVALS(inbuf,smb_vwv2);
2153 switch (mode) {
2154 case 0: umode = SEEK_SET; break;
2155 case 1: umode = SEEK_CUR; break;
2156 case 2: umode = SEEK_END; break;
2157 default:
2158 umode = SEEK_SET; break;
2161 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2163 * Check for the special case where a seek before the start
2164 * of the file sets the offset to zero. Added in the CIFS spec,
2165 * section 4.2.7.
2168 if(errno == EINVAL) {
2169 SMB_OFF_T current_pos = startpos;
2171 if(umode == SEEK_CUR) {
2173 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2174 END_PROFILE(SMBlseek);
2175 return(UNIXERROR(ERRDOS,ERRnoaccess));
2178 current_pos += startpos;
2180 } else if (umode == SEEK_END) {
2182 SMB_STRUCT_STAT sbuf;
2184 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2185 END_PROFILE(SMBlseek);
2186 return(UNIXERROR(ERRDOS,ERRnoaccess));
2189 current_pos += sbuf.st_size;
2192 if(current_pos < 0)
2193 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2196 if(res == -1) {
2197 END_PROFILE(SMBlseek);
2198 return(UNIXERROR(ERRDOS,ERRnoaccess));
2202 fsp->pos = res;
2204 outsize = set_message(outbuf,2,0,True);
2205 SIVAL(outbuf,smb_vwv0,res);
2207 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2208 fsp->fnum, (double)startpos, (double)res, mode));
2210 END_PROFILE(SMBlseek);
2211 return(outsize);
2214 /****************************************************************************
2215 reply to a flush
2216 ****************************************************************************/
2218 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2220 int outsize = set_message(outbuf,0,0,True);
2221 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2222 START_PROFILE(SMBflush);
2224 CHECK_FSP(fsp,conn);
2226 if (!fsp) {
2227 file_sync_all(conn);
2228 } else {
2229 sync_file(conn,fsp);
2232 DEBUG(3,("flush\n"));
2233 END_PROFILE(SMBflush);
2234 return(outsize);
2238 /****************************************************************************
2239 reply to a exit
2240 ****************************************************************************/
2241 int reply_exit(connection_struct *conn,
2242 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2244 int outsize;
2245 START_PROFILE(SMBexit);
2246 outsize = set_message(outbuf,0,0,True);
2248 DEBUG(3,("exit\n"));
2250 END_PROFILE(SMBexit);
2251 return(outsize);
2255 /****************************************************************************
2256 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2257 ****************************************************************************/
2258 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2259 int dum_buffsize)
2261 int outsize = 0;
2262 time_t mtime;
2263 int32 eclass = 0, err = 0;
2264 files_struct *fsp = NULL;
2265 START_PROFILE(SMBclose);
2267 outsize = set_message(outbuf,0,0,True);
2269 /* If it's an IPC, pass off to the pipe handler. */
2270 if (IS_IPC(conn)) {
2271 END_PROFILE(SMBclose);
2272 return reply_pipe_close(conn, inbuf,outbuf);
2275 fsp = file_fsp(inbuf,smb_vwv0);
2278 * We can only use CHECK_FSP if we know it's not a directory.
2281 if(!fsp || (fsp->conn != conn)) {
2282 END_PROFILE(SMBclose);
2283 return ERROR_DOS(ERRDOS,ERRbadfid);
2286 if(fsp->is_directory) {
2288 * Special case - close NT SMB directory handle.
2290 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2291 close_file(fsp,True);
2292 } else {
2294 * Close ordinary file.
2296 int close_err;
2297 pstring file_name;
2299 /* Save the name for time set in close. */
2300 pstrcpy( file_name, fsp->fsp_name);
2302 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2303 fsp->fd, fsp->fnum,
2304 conn->num_files_open));
2307 * close_file() returns the unix errno if an error
2308 * was detected on close - normally this is due to
2309 * a disk full error. If not then it was probably an I/O error.
2312 if((close_err = close_file(fsp,True)) != 0) {
2313 errno = close_err;
2314 END_PROFILE(SMBclose);
2315 return (UNIXERROR(ERRHRD,ERRgeneral));
2319 * Now take care of any time sent in the close.
2322 mtime = make_unix_date3(inbuf+smb_vwv1);
2324 /* try and set the date */
2325 set_filetime(conn, file_name, mtime);
2329 /* We have a cached error */
2330 if(eclass || err) {
2331 END_PROFILE(SMBclose);
2332 return ERROR_DOS(eclass,err);
2335 END_PROFILE(SMBclose);
2336 return(outsize);
2340 /****************************************************************************
2341 reply to a writeclose (Core+ protocol)
2342 ****************************************************************************/
2344 int reply_writeclose(connection_struct *conn,
2345 char *inbuf,char *outbuf, int size, int dum_buffsize)
2347 size_t numtowrite;
2348 ssize_t nwritten = -1;
2349 int outsize = 0;
2350 int close_err = 0;
2351 SMB_OFF_T startpos;
2352 char *data;
2353 time_t mtime;
2354 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2355 START_PROFILE(SMBwriteclose);
2357 CHECK_FSP(fsp,conn);
2358 CHECK_WRITE(fsp);
2360 numtowrite = SVAL(inbuf,smb_vwv1);
2361 startpos = IVAL(inbuf,smb_vwv2);
2362 mtime = make_unix_date3(inbuf+smb_vwv4);
2363 data = smb_buf(inbuf) + 1;
2365 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2366 END_PROFILE(SMBwriteclose);
2367 return ERROR_DOS(ERRDOS,ERRlock);
2370 nwritten = write_file(fsp,data,startpos,numtowrite);
2372 set_filetime(conn, fsp->fsp_name,mtime);
2374 close_err = close_file(fsp,True);
2376 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2377 fsp->fnum, (int)numtowrite, (int)nwritten,
2378 conn->num_files_open));
2380 if (nwritten <= 0) {
2381 END_PROFILE(SMBwriteclose);
2382 return(UNIXERROR(ERRDOS,ERRnoaccess));
2385 if(close_err != 0) {
2386 errno = close_err;
2387 END_PROFILE(SMBwriteclose);
2388 return(UNIXERROR(ERRHRD,ERRgeneral));
2391 outsize = set_message(outbuf,1,0,True);
2393 SSVAL(outbuf,smb_vwv0,nwritten);
2394 END_PROFILE(SMBwriteclose);
2395 return(outsize);
2399 /****************************************************************************
2400 reply to a lock
2401 ****************************************************************************/
2402 int reply_lock(connection_struct *conn,
2403 char *inbuf,char *outbuf, int length, int dum_buffsize)
2405 int outsize = set_message(outbuf,0,0,True);
2406 SMB_BIG_UINT count,offset;
2407 NTSTATUS status;
2408 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2409 START_PROFILE(SMBlock);
2411 CHECK_FSP(fsp,conn);
2413 release_level_2_oplocks_on_change(fsp);
2415 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2416 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2418 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2419 fsp->fd, fsp->fnum, (double)offset, (double)count));
2421 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2422 if (NT_STATUS_V(status)) {
2423 if (lp_blocking_locks(SNUM(conn))) {
2425 * A blocking lock was requested. Package up
2426 * this smb into a queued request and push it
2427 * onto the blocking lock queue.
2429 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2430 END_PROFILE(SMBlock);
2431 return -1;
2434 END_PROFILE(SMBlock);
2435 return ERROR_NT(status);
2438 END_PROFILE(SMBlock);
2439 return(outsize);
2443 /****************************************************************************
2444 reply to a unlock
2445 ****************************************************************************/
2446 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2447 int dum_buffsize)
2449 int outsize = set_message(outbuf,0,0,True);
2450 SMB_BIG_UINT count,offset;
2451 NTSTATUS status;
2452 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2453 START_PROFILE(SMBunlock);
2455 CHECK_FSP(fsp,conn);
2457 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2458 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2460 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2461 if (NT_STATUS_V(status)) {
2462 END_PROFILE(SMBunlock);
2463 return ERROR_NT(status);
2466 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2467 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2469 END_PROFILE(SMBunlock);
2470 return(outsize);
2474 /****************************************************************************
2475 reply to a tdis
2476 ****************************************************************************/
2477 int reply_tdis(connection_struct *conn,
2478 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2480 int outsize = set_message(outbuf,0,0,True);
2481 uint16 vuid;
2482 START_PROFILE(SMBtdis);
2484 vuid = SVAL(inbuf,smb_uid);
2486 if (!conn) {
2487 DEBUG(4,("Invalid connection in tdis\n"));
2488 END_PROFILE(SMBtdis);
2489 return ERROR_DOS(ERRSRV,ERRinvnid);
2492 conn->used = False;
2494 close_cnum(conn,vuid);
2496 END_PROFILE(SMBtdis);
2497 return outsize;
2502 /****************************************************************************
2503 reply to a echo
2504 ****************************************************************************/
2505 int reply_echo(connection_struct *conn,
2506 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2508 int smb_reverb = SVAL(inbuf,smb_vwv0);
2509 int seq_num;
2510 unsigned int data_len = smb_buflen(inbuf);
2511 int outsize = set_message(outbuf,1,data_len,True);
2512 START_PROFILE(SMBecho);
2514 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2516 /* copy any incoming data back out */
2517 if (data_len > 0)
2518 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2520 if (smb_reverb > 100) {
2521 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2522 smb_reverb = 100;
2525 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2526 SSVAL(outbuf,smb_vwv0,seq_num);
2528 smb_setlen(outbuf,outsize - 4);
2530 if (!send_smb(smbd_server_fd(),outbuf))
2531 exit_server("reply_echo: send_smb failed.");
2534 DEBUG(3,("echo %d times\n", smb_reverb));
2536 smb_echo_count++;
2538 END_PROFILE(SMBecho);
2539 return -1;
2543 /****************************************************************************
2544 reply to a printopen
2545 ****************************************************************************/
2546 int reply_printopen(connection_struct *conn,
2547 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2549 int outsize = 0;
2550 files_struct *fsp;
2551 START_PROFILE(SMBsplopen);
2553 if (!CAN_PRINT(conn)) {
2554 END_PROFILE(SMBsplopen);
2555 return ERROR_DOS(ERRDOS,ERRnoaccess);
2558 /* Open for exclusive use, write only. */
2559 fsp = print_fsp_open(conn, NULL);
2561 if (!fsp) {
2562 END_PROFILE(SMBsplopen);
2563 return(UNIXERROR(ERRDOS,ERRnoaccess));
2566 outsize = set_message(outbuf,1,0,True);
2567 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2569 DEBUG(3,("openprint fd=%d fnum=%d\n",
2570 fsp->fd, fsp->fnum));
2572 END_PROFILE(SMBsplopen);
2573 return(outsize);
2577 /****************************************************************************
2578 reply to a printclose
2579 ****************************************************************************/
2580 int reply_printclose(connection_struct *conn,
2581 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2583 int outsize = set_message(outbuf,0,0,True);
2584 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2585 int close_err = 0;
2586 START_PROFILE(SMBsplclose);
2588 CHECK_FSP(fsp,conn);
2590 if (!CAN_PRINT(conn)) {
2591 END_PROFILE(SMBsplclose);
2592 return ERROR_DOS(ERRDOS,ERRnoaccess);
2595 DEBUG(3,("printclose fd=%d fnum=%d\n",
2596 fsp->fd,fsp->fnum));
2598 close_err = close_file(fsp,True);
2600 if(close_err != 0) {
2601 errno = close_err;
2602 END_PROFILE(SMBsplclose);
2603 return(UNIXERROR(ERRHRD,ERRgeneral));
2606 END_PROFILE(SMBsplclose);
2607 return(outsize);
2611 /****************************************************************************
2612 reply to a printqueue
2613 ****************************************************************************/
2614 int reply_printqueue(connection_struct *conn,
2615 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2617 int outsize = set_message(outbuf,2,3,True);
2618 int max_count = SVAL(inbuf,smb_vwv0);
2619 int start_index = SVAL(inbuf,smb_vwv1);
2620 START_PROFILE(SMBsplretq);
2622 /* we used to allow the client to get the cnum wrong, but that
2623 is really quite gross and only worked when there was only
2624 one printer - I think we should now only accept it if they
2625 get it right (tridge) */
2626 if (!CAN_PRINT(conn)) {
2627 END_PROFILE(SMBsplretq);
2628 return ERROR_DOS(ERRDOS,ERRnoaccess);
2631 SSVAL(outbuf,smb_vwv0,0);
2632 SSVAL(outbuf,smb_vwv1,0);
2633 SCVAL(smb_buf(outbuf),0,1);
2634 SSVAL(smb_buf(outbuf),1,0);
2636 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2637 start_index, max_count));
2640 print_queue_struct *queue = NULL;
2641 print_status_struct status;
2642 char *p = smb_buf(outbuf) + 3;
2643 int count = print_queue_status(SNUM(conn), &queue, &status);
2644 int num_to_get = ABS(max_count);
2645 int first = (max_count>0?start_index:start_index+max_count+1);
2646 int i;
2648 if (first >= count)
2649 num_to_get = 0;
2650 else
2651 num_to_get = MIN(num_to_get,count-first);
2654 for (i=first;i<first+num_to_get;i++) {
2655 put_dos_date2(p,0,queue[i].time);
2656 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2657 SSVAL(p,5, queue[i].job);
2658 SIVAL(p,7,queue[i].size);
2659 SCVAL(p,11,0);
2660 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2661 p += 28;
2664 if (count > 0) {
2665 outsize = set_message(outbuf,2,28*count+3,False);
2666 SSVAL(outbuf,smb_vwv0,count);
2667 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2668 SCVAL(smb_buf(outbuf),0,1);
2669 SSVAL(smb_buf(outbuf),1,28*count);
2672 SAFE_FREE(queue);
2674 DEBUG(3,("%d entries returned in queue\n",count));
2677 END_PROFILE(SMBsplretq);
2678 return(outsize);
2682 /****************************************************************************
2683 reply to a printwrite
2684 ****************************************************************************/
2685 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2687 int numtowrite;
2688 int outsize = set_message(outbuf,0,0,True);
2689 char *data;
2690 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2691 START_PROFILE(SMBsplwr);
2693 if (!CAN_PRINT(conn)) {
2694 END_PROFILE(SMBsplwr);
2695 return ERROR_DOS(ERRDOS,ERRnoaccess);
2698 CHECK_FSP(fsp,conn);
2699 CHECK_WRITE(fsp);
2701 numtowrite = SVAL(smb_buf(inbuf),1);
2702 data = smb_buf(inbuf) + 3;
2704 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2705 END_PROFILE(SMBsplwr);
2706 return(UNIXERROR(ERRDOS,ERRnoaccess));
2709 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2711 END_PROFILE(SMBsplwr);
2712 return(outsize);
2716 /****************************************************************************
2717 The guts of the mkdir command, split out so it may be called by the NT SMB
2718 code.
2719 ****************************************************************************/
2720 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2722 BOOL bad_path = False;
2723 SMB_STRUCT_STAT sbuf;
2724 int ret= -1;
2726 unix_convert(directory,conn,0,&bad_path,&sbuf);
2728 if (check_name(directory, conn))
2729 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2731 if (ret == -1) {
2732 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2733 if (!NT_STATUS_IS_OK(nterr))
2734 return nterr;
2735 return map_nt_error_from_unix(errno);
2738 return NT_STATUS_OK;
2741 /****************************************************************************
2742 Reply to a mkdir.
2743 ****************************************************************************/
2745 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2747 pstring directory;
2748 int outsize;
2749 NTSTATUS status;
2750 START_PROFILE(SMBmkdir);
2752 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2754 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2756 status = mkdir_internal(conn, directory);
2757 if (!NT_STATUS_IS_OK(status))
2758 return ERROR_NT(status);
2760 outsize = set_message(outbuf,0,0,True);
2762 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2764 END_PROFILE(SMBmkdir);
2765 return(outsize);
2768 /****************************************************************************
2769 Static function used by reply_rmdir to delete an entire directory
2770 tree recursively. Return False on ok, True on fail.
2771 ****************************************************************************/
2773 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2775 char *dname = NULL;
2776 BOOL ret = False;
2777 void *dirptr = OpenDir(conn, directory, False);
2779 if(dirptr == NULL)
2780 return True;
2782 while((dname = ReadDirName(dirptr))) {
2783 pstring fullname;
2784 SMB_STRUCT_STAT st;
2786 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2787 continue;
2789 /* Construct the full name. */
2790 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2791 errno = ENOMEM;
2792 ret = True;
2793 break;
2796 pstrcpy(fullname, directory);
2797 pstrcat(fullname, "/");
2798 pstrcat(fullname, dname);
2800 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2801 ret = True;
2802 break;
2805 if(st.st_mode & S_IFDIR) {
2806 if(recursive_rmdir(conn, fullname)!=0) {
2807 ret = True;
2808 break;
2810 if(vfs_rmdir(conn,fullname) != 0) {
2811 ret = True;
2812 break;
2814 } else if(vfs_unlink(conn,fullname) != 0) {
2815 ret = True;
2816 break;
2819 CloseDir(dirptr);
2820 return ret;
2823 /****************************************************************************
2824 The internals of the rmdir code - called elsewhere.
2825 ****************************************************************************/
2827 BOOL rmdir_internals(connection_struct *conn, char *directory)
2829 BOOL ok;
2831 ok = (vfs_rmdir(conn,directory) == 0);
2832 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2834 * Check to see if the only thing in this directory are
2835 * vetoed files/directories. If so then delete them and
2836 * retry. If we fail to delete any of them (and we *don't*
2837 * do a recursive delete) then fail the rmdir.
2839 BOOL all_veto_files = True;
2840 char *dname;
2841 void *dirptr = OpenDir(conn, directory, False);
2843 if(dirptr != NULL) {
2844 int dirpos = TellDir(dirptr);
2845 while ((dname = ReadDirName(dirptr))) {
2846 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2847 continue;
2848 if(!IS_VETO_PATH(conn, dname)) {
2849 all_veto_files = False;
2850 break;
2854 if(all_veto_files) {
2855 SeekDir(dirptr,dirpos);
2856 while ((dname = ReadDirName(dirptr))) {
2857 pstring fullname;
2858 SMB_STRUCT_STAT st;
2860 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2861 continue;
2863 /* Construct the full name. */
2864 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2865 errno = ENOMEM;
2866 break;
2869 pstrcpy(fullname, directory);
2870 pstrcat(fullname, "/");
2871 pstrcat(fullname, dname);
2873 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2874 break;
2875 if(st.st_mode & S_IFDIR) {
2876 if(lp_recursive_veto_delete(SNUM(conn))) {
2877 if(recursive_rmdir(conn, fullname) != 0)
2878 break;
2880 if(vfs_rmdir(conn,fullname) != 0)
2881 break;
2882 } else if(vfs_unlink(conn,fullname) != 0)
2883 break;
2885 CloseDir(dirptr);
2886 /* Retry the rmdir */
2887 ok = (vfs_rmdir(conn,directory) == 0);
2888 } else {
2889 CloseDir(dirptr);
2891 } else {
2892 errno = ENOTEMPTY;
2896 if (!ok)
2897 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2899 return ok;
2902 /****************************************************************************
2903 Reply to a rmdir.
2904 ****************************************************************************/
2906 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2908 pstring directory;
2909 int outsize = 0;
2910 BOOL ok = False;
2911 BOOL bad_path = False;
2912 SMB_STRUCT_STAT sbuf;
2913 START_PROFILE(SMBrmdir);
2915 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2917 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
2919 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
2921 if (check_name(directory,conn))
2923 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2924 ok = rmdir_internals(conn, directory);
2927 if (!ok)
2929 set_bad_path_error(errno, bad_path);
2930 END_PROFILE(SMBrmdir);
2931 return(UNIXERROR(ERRDOS,ERRbadpath));
2934 outsize = set_message(outbuf,0,0,True);
2936 DEBUG( 3, ( "rmdir %s\n", directory ) );
2938 END_PROFILE(SMBrmdir);
2939 return(outsize);
2943 /*******************************************************************
2944 resolve wildcards in a filename rename
2945 ********************************************************************/
2946 static BOOL resolve_wildcards(char *name1,char *name2)
2948 fstring root1,root2;
2949 fstring ext1,ext2;
2950 char *p,*p2;
2952 name1 = strrchr_m(name1,'/');
2953 name2 = strrchr_m(name2,'/');
2955 if (!name1 || !name2) return(False);
2957 fstrcpy(root1,name1);
2958 fstrcpy(root2,name2);
2959 p = strrchr_m(root1,'.');
2960 if (p) {
2961 *p = 0;
2962 fstrcpy(ext1,p+1);
2963 } else {
2964 fstrcpy(ext1,"");
2966 p = strrchr_m(root2,'.');
2967 if (p) {
2968 *p = 0;
2969 fstrcpy(ext2,p+1);
2970 } else {
2971 fstrcpy(ext2,"");
2974 p = root1;
2975 p2 = root2;
2976 while (*p2) {
2977 if (*p2 == '?') {
2978 *p2 = *p;
2979 p2++;
2980 } else {
2981 p2++;
2983 if (*p) p++;
2986 p = ext1;
2987 p2 = ext2;
2988 while (*p2) {
2989 if (*p2 == '?') {
2990 *p2 = *p;
2991 p2++;
2992 } else {
2993 p2++;
2995 if (*p) p++;
2998 pstrcpy(name2,root2);
2999 if (ext2[0]) {
3000 pstrcat(name2,".");
3001 pstrcat(name2,ext2);
3004 return(True);
3007 /****************************************************************************
3008 The guts of the rename command, split out so it may be called by the NT SMB
3009 code.
3010 ****************************************************************************/
3012 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3014 pstring directory;
3015 pstring mask;
3016 pstring newname_last_component;
3017 char *p;
3018 BOOL has_wild;
3019 BOOL bad_path1 = False;
3020 BOOL bad_path2 = False;
3021 int count=0;
3022 NTSTATUS error = NT_STATUS_OK;
3023 BOOL rc = True;
3024 SMB_STRUCT_STAT sbuf1, sbuf2;
3026 *directory = *mask = 0;
3028 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3029 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3032 * Split the old name into directory and last component
3033 * strings. Note that unix_convert may have stripped off a
3034 * leading ./ from both name and newname if the rename is
3035 * at the root of the share. We need to make sure either both
3036 * name and newname contain a / character or neither of them do
3037 * as this is checked in resolve_wildcards().
3040 p = strrchr_m(name,'/');
3041 if (!p) {
3042 pstrcpy(directory,".");
3043 pstrcpy(mask,name);
3044 } else {
3045 *p = 0;
3046 pstrcpy(directory,name);
3047 pstrcpy(mask,p+1);
3048 *p = '/'; /* Replace needed for exceptional test below. */
3052 * We should only check the mangled cache
3053 * here if unix_convert failed. This means
3054 * that the path in 'mask' doesn't exist
3055 * on the file system and so we need to look
3056 * for a possible mangle. This patch from
3057 * Tine Smukavec <valentin.smukavec@hermes.si>.
3060 if (!rc && mangle_is_mangled(mask))
3061 mangle_check_cache( mask );
3063 has_wild = ms_has_wild(mask);
3065 if (!has_wild) {
3067 * No wildcards - just process the one file.
3069 BOOL is_short_name = mangle_is_8_3(name, True);
3071 /* Add a terminating '/' to the directory name. */
3072 pstrcat(directory,"/");
3073 pstrcat(directory,mask);
3075 /* Ensure newname contains a '/' also */
3076 if(strrchr_m(newname,'/') == 0) {
3077 pstring tmpstr;
3079 pstrcpy(tmpstr, "./");
3080 pstrcat(tmpstr, newname);
3081 pstrcpy(newname, tmpstr);
3084 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3085 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3086 case_sensitive, case_preserve, short_case_preserve, directory,
3087 newname, newname_last_component, is_short_name));
3090 * Check for special case with case preserving and not
3091 * case sensitive, if directory and newname are identical,
3092 * and the old last component differs from the original
3093 * last component only by case, then we should allow
3094 * the rename (user is trying to change the case of the
3095 * filename).
3097 if((case_sensitive == False) &&
3098 (((case_preserve == True) &&
3099 (is_short_name == False)) ||
3100 ((short_case_preserve == True) &&
3101 (is_short_name == True))) &&
3102 strcsequal(directory, newname)) {
3103 pstring newname_modified_last_component;
3106 * Get the last component of the modified name.
3107 * Note that we guarantee that newname contains a '/'
3108 * character above.
3110 p = strrchr_m(newname,'/');
3111 pstrcpy(newname_modified_last_component,p+1);
3113 if(strcsequal(newname_modified_last_component,
3114 newname_last_component) == False) {
3116 * Replace the modified last component with
3117 * the original.
3119 pstrcpy(p+1, newname_last_component);
3123 resolve_wildcards(directory,newname);
3126 * The source object must exist.
3129 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3130 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3131 directory,newname));
3133 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3135 * Must return different errors depending on whether the parent
3136 * directory existed or not.
3139 p = strrchr_m(directory, '/');
3140 if (!p)
3141 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3142 *p = '\0';
3143 if (vfs_object_exist(conn, directory, NULL))
3144 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3145 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3147 error = map_nt_error_from_unix(errno);
3148 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3149 nt_errstr(error), directory,newname));
3151 return error;
3154 error = can_rename(directory,conn,&sbuf1);
3156 if (!NT_STATUS_IS_OK(error)) {
3157 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3158 nt_errstr(error), directory,newname));
3159 return error;
3163 * If the src and dest names are identical - including case,
3164 * don't do the rename, just return success.
3167 if (strcsequal(directory, newname)) {
3168 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3169 return NT_STATUS_OK;
3172 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3173 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3174 directory,newname));
3175 return NT_STATUS_OBJECT_NAME_COLLISION;
3178 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3179 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3180 directory,newname));
3181 return NT_STATUS_OK;
3184 if (errno == ENOTDIR || errno == EISDIR)
3185 error = NT_STATUS_OBJECT_NAME_COLLISION;
3186 else
3187 error = map_nt_error_from_unix(errno);
3189 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3190 nt_errstr(error), directory,newname));
3192 return error;
3193 } else {
3195 * Wildcards - process each file that matches.
3197 void *dirptr = NULL;
3198 char *dname;
3199 pstring destname;
3201 if (check_name(directory,conn))
3202 dirptr = OpenDir(conn, directory, True);
3204 if (dirptr) {
3205 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3207 if (strequal(mask,"????????.???"))
3208 pstrcpy(mask,"*");
3210 while ((dname = ReadDirName(dirptr))) {
3211 pstring fname;
3213 pstrcpy(fname,dname);
3215 if(!mask_match(fname, mask, case_sensitive))
3216 continue;
3218 error = NT_STATUS_ACCESS_DENIED;
3219 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3220 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3221 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3222 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3223 continue;
3225 error = can_rename(fname,conn,&sbuf1);
3226 if (!NT_STATUS_IS_OK(error)) {
3227 DEBUG(6,("rename %s refused\n", fname));
3228 continue;
3230 pstrcpy(destname,newname);
3232 if (!resolve_wildcards(fname,destname)) {
3233 DEBUG(6,("resolve_wildcards %s %s failed\n",
3234 fname, destname));
3235 continue;
3238 if (!replace_if_exists &&
3239 vfs_file_exist(conn,destname, NULL)) {
3240 DEBUG(6,("file_exist %s\n", destname));
3241 error = NT_STATUS_OBJECT_NAME_COLLISION;
3242 continue;
3245 if (!conn->vfs_ops.rename(conn,fname,destname))
3246 count++;
3247 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3249 CloseDir(dirptr);
3253 if (count == 0 && NT_STATUS_IS_OK(error)) {
3254 error = map_nt_error_from_unix(errno);
3257 return error;
3260 /****************************************************************************
3261 Reply to a mv.
3262 ****************************************************************************/
3264 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3265 int dum_buffsize)
3267 int outsize = 0;
3268 pstring name;
3269 pstring newname;
3270 char *p;
3271 NTSTATUS status;
3273 START_PROFILE(SMBmv);
3275 p = smb_buf(inbuf) + 1;
3276 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3277 p++;
3278 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3280 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3281 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3283 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3285 status = rename_internals(conn, name, newname, False);
3286 if (!NT_STATUS_IS_OK(status)) {
3287 return ERROR_NT(status);
3291 * Win2k needs a changenotify request response before it will
3292 * update after a rename..
3294 process_pending_change_notify_queue((time_t)0);
3295 outsize = set_message(outbuf,0,0,True);
3297 END_PROFILE(SMBmv);
3298 return(outsize);
3301 /*******************************************************************
3302 Copy a file as part of a reply_copy.
3303 ******************************************************************/
3305 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3306 int count,BOOL target_is_directory, int *err_ret)
3308 int Access,action;
3309 SMB_STRUCT_STAT src_sbuf, sbuf2;
3310 SMB_OFF_T ret=-1;
3311 files_struct *fsp1,*fsp2;
3312 pstring dest;
3314 *err_ret = 0;
3316 pstrcpy(dest,dest1);
3317 if (target_is_directory) {
3318 char *p = strrchr_m(src,'/');
3319 if (p)
3320 p++;
3321 else
3322 p = src;
3323 pstrcat(dest,"/");
3324 pstrcat(dest,p);
3327 if (!vfs_file_exist(conn,src,&src_sbuf))
3328 return(False);
3330 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3331 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3333 if (!fsp1)
3334 return(False);
3336 if (!target_is_directory && count)
3337 ofun = FILE_EXISTS_OPEN;
3339 if (vfs_stat(conn,dest,&sbuf2) == -1)
3340 ZERO_STRUCTP(&sbuf2);
3342 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3343 ofun,src_sbuf.st_mode,0,&Access,&action);
3345 if (!fsp2) {
3346 close_file(fsp1,False);
3347 return(False);
3350 if ((ofun&3) == 1) {
3351 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3352 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3354 * Stop the copy from occurring.
3356 ret = -1;
3357 src_sbuf.st_size = 0;
3361 if (src_sbuf.st_size)
3362 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3364 close_file(fsp1,False);
3366 /* Ensure the modtime is set correctly on the destination file. */
3367 fsp2->pending_modtime = src_sbuf.st_mtime;
3370 * As we are opening fsp1 read-only we only expect
3371 * an error on close on fsp2 if we are out of space.
3372 * Thus we don't look at the error return from the
3373 * close of fsp1.
3375 *err_ret = close_file(fsp2,False);
3377 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3380 /****************************************************************************
3381 reply to a file copy.
3382 ****************************************************************************/
3383 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3385 int outsize = 0;
3386 pstring name;
3387 pstring directory;
3388 pstring mask,newname;
3389 char *p;
3390 int count=0;
3391 int error = ERRnoaccess;
3392 int err = 0;
3393 BOOL has_wild;
3394 BOOL exists=False;
3395 int tid2 = SVAL(inbuf,smb_vwv0);
3396 int ofun = SVAL(inbuf,smb_vwv1);
3397 int flags = SVAL(inbuf,smb_vwv2);
3398 BOOL target_is_directory=False;
3399 BOOL bad_path1 = False;
3400 BOOL bad_path2 = False;
3401 BOOL rc = True;
3402 SMB_STRUCT_STAT sbuf1, sbuf2;
3403 START_PROFILE(SMBcopy);
3405 *directory = *mask = 0;
3407 p = smb_buf(inbuf);
3408 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3409 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3411 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3413 if (tid2 != conn->cnum) {
3414 /* can't currently handle inter share copies XXXX */
3415 DEBUG(3,("Rejecting inter-share copy\n"));
3416 END_PROFILE(SMBcopy);
3417 return ERROR_DOS(ERRSRV,ERRinvdevice);
3420 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3421 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3423 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3424 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3426 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3428 if ((flags&1) && target_is_directory) {
3429 END_PROFILE(SMBcopy);
3430 return ERROR_DOS(ERRDOS,ERRbadfile);
3433 if ((flags&2) && !target_is_directory) {
3434 END_PROFILE(SMBcopy);
3435 return ERROR_DOS(ERRDOS,ERRbadpath);
3438 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3439 /* wants a tree copy! XXXX */
3440 DEBUG(3,("Rejecting tree copy\n"));
3441 END_PROFILE(SMBcopy);
3442 return ERROR_DOS(ERRSRV,ERRerror);
3445 p = strrchr_m(name,'/');
3446 if (!p) {
3447 pstrcpy(directory,"./");
3448 pstrcpy(mask,name);
3449 } else {
3450 *p = 0;
3451 pstrcpy(directory,name);
3452 pstrcpy(mask,p+1);
3456 * We should only check the mangled cache
3457 * here if unix_convert failed. This means
3458 * that the path in 'mask' doesn't exist
3459 * on the file system and so we need to look
3460 * for a possible mangle. This patch from
3461 * Tine Smukavec <valentin.smukavec@hermes.si>.
3464 if (!rc && mangle_is_mangled(mask))
3465 mangle_check_cache( mask );
3467 has_wild = ms_has_wild(mask);
3469 if (!has_wild) {
3470 pstrcat(directory,"/");
3471 pstrcat(directory,mask);
3472 if (resolve_wildcards(directory,newname) &&
3473 copy_file(directory,newname,conn,ofun,
3474 count,target_is_directory,&err)) count++;
3475 if(!count && err) {
3476 errno = err;
3477 END_PROFILE(SMBcopy);
3478 return(UNIXERROR(ERRHRD,ERRgeneral));
3480 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3481 } else {
3482 void *dirptr = NULL;
3483 char *dname;
3484 pstring destname;
3486 if (check_name(directory,conn))
3487 dirptr = OpenDir(conn, directory, True);
3489 if (dirptr) {
3490 error = ERRbadfile;
3492 if (strequal(mask,"????????.???"))
3493 pstrcpy(mask,"*");
3495 while ((dname = ReadDirName(dirptr))) {
3496 pstring fname;
3497 pstrcpy(fname,dname);
3499 if(!mask_match(fname, mask, case_sensitive))
3500 continue;
3502 error = ERRnoaccess;
3503 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3504 pstrcpy(destname,newname);
3505 if (resolve_wildcards(fname,destname) &&
3506 copy_file(fname,destname,conn,ofun,
3507 count,target_is_directory,&err)) count++;
3508 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3510 CloseDir(dirptr);
3514 if (count == 0) {
3515 if(err) {
3516 /* Error on close... */
3517 errno = err;
3518 END_PROFILE(SMBcopy);
3519 return(UNIXERROR(ERRHRD,ERRgeneral));
3522 if (exists) {
3523 END_PROFILE(SMBcopy);
3524 return ERROR_DOS(ERRDOS,error);
3525 } else
3527 if((errno == ENOENT) && (bad_path1 || bad_path2))
3529 unix_ERR_class = ERRDOS;
3530 unix_ERR_code = ERRbadpath;
3532 END_PROFILE(SMBcopy);
3533 return(UNIXERROR(ERRDOS,error));
3537 outsize = set_message(outbuf,1,0,True);
3538 SSVAL(outbuf,smb_vwv0,count);
3540 END_PROFILE(SMBcopy);
3541 return(outsize);
3544 /****************************************************************************
3545 reply to a setdir
3546 ****************************************************************************/
3547 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3549 int snum;
3550 int outsize = 0;
3551 BOOL ok = False;
3552 pstring newdir;
3553 START_PROFILE(pathworks_setdir);
3555 snum = SNUM(conn);
3556 if (!CAN_SETDIR(snum)) {
3557 END_PROFILE(pathworks_setdir);
3558 return ERROR_DOS(ERRDOS,ERRnoaccess);
3561 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3563 if (strlen(newdir) == 0) {
3564 ok = True;
3565 } else {
3566 ok = vfs_directory_exist(conn,newdir,NULL);
3567 if (ok) {
3568 string_set(&conn->connectpath,newdir);
3572 if (!ok) {
3573 END_PROFILE(pathworks_setdir);
3574 return ERROR_DOS(ERRDOS,ERRbadpath);
3577 outsize = set_message(outbuf,0,0,True);
3578 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3580 DEBUG(3,("setdir %s\n", newdir));
3582 END_PROFILE(pathworks_setdir);
3583 return(outsize);
3586 /****************************************************************************
3587 Get a lock pid, dealing with large count requests.
3588 ****************************************************************************/
3590 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3592 if(!large_file_format)
3593 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3594 else
3595 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3598 /****************************************************************************
3599 Get a lock count, dealing with large count requests.
3600 ****************************************************************************/
3602 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3604 SMB_BIG_UINT count = 0;
3606 if(!large_file_format) {
3607 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3608 } else {
3610 #if defined(HAVE_LONGLONG)
3611 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3612 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3613 #else /* HAVE_LONGLONG */
3616 * NT4.x seems to be broken in that it sends large file (64 bit)
3617 * lockingX calls even if the CAP_LARGE_FILES was *not*
3618 * negotiated. For boxes without large unsigned ints truncate the
3619 * lock count by dropping the top 32 bits.
3622 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3623 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3624 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3625 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3626 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3629 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3630 #endif /* HAVE_LONGLONG */
3633 return count;
3636 #if !defined(HAVE_LONGLONG)
3637 /****************************************************************************
3638 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3639 ****************************************************************************/
3640 static uint32 map_lock_offset(uint32 high, uint32 low)
3642 unsigned int i;
3643 uint32 mask = 0;
3644 uint32 highcopy = high;
3647 * Try and find out how many significant bits there are in high.
3650 for(i = 0; highcopy; i++)
3651 highcopy >>= 1;
3654 * We use 31 bits not 32 here as POSIX
3655 * lock offsets may not be negative.
3658 mask = (~0) << (31 - i);
3660 if(low & mask)
3661 return 0; /* Fail. */
3663 high <<= (31 - i);
3665 return (high|low);
3667 #endif /* !defined(HAVE_LONGLONG) */
3669 /****************************************************************************
3670 Get a lock offset, dealing with large offset requests.
3671 ****************************************************************************/
3673 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3675 SMB_BIG_UINT offset = 0;
3677 *err = False;
3679 if(!large_file_format) {
3680 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3681 } else {
3683 #if defined(HAVE_LONGLONG)
3684 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3685 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3686 #else /* HAVE_LONGLONG */
3689 * NT4.x seems to be broken in that it sends large file (64 bit)
3690 * lockingX calls even if the CAP_LARGE_FILES was *not*
3691 * negotiated. For boxes without large unsigned ints mangle the
3692 * lock offset by mapping the top 32 bits onto the lower 32.
3695 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3696 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3697 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3698 uint32 new_low = 0;
3700 if((new_low = map_lock_offset(high, low)) == 0) {
3701 *err = True;
3702 return (SMB_BIG_UINT)-1;
3705 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3706 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3707 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3708 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3711 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3712 #endif /* HAVE_LONGLONG */
3715 return offset;
3718 /****************************************************************************
3719 reply to a lockingX request
3720 ****************************************************************************/
3722 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3724 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3725 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3726 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3727 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3728 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3729 SMB_BIG_UINT count = 0, offset = 0;
3730 uint16 lock_pid;
3731 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3732 int i;
3733 char *data;
3734 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3735 BOOL err;
3736 NTSTATUS status;
3738 START_PROFILE(SMBlockingX);
3740 CHECK_FSP(fsp,conn);
3742 data = smb_buf(inbuf);
3744 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3745 /* we don't support these - and CANCEL_LOCK makes w2k
3746 and XP reboot so I don't really want to be
3747 compatible! (tridge) */
3748 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3751 /* Check if this is an oplock break on a file
3752 we have granted an oplock on.
3754 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3755 /* Client can insist on breaking to none. */
3756 BOOL break_to_none = (oplocklevel == 0);
3758 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3759 (unsigned int)oplocklevel, fsp->fnum ));
3762 * Make sure we have granted an exclusive or batch oplock on this file.
3765 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3766 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3767 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3769 /* if this is a pure oplock break request then don't send a reply */
3770 if (num_locks == 0 && num_ulocks == 0) {
3771 END_PROFILE(SMBlockingX);
3772 return -1;
3773 } else {
3774 END_PROFILE(SMBlockingX);
3775 return ERROR_DOS(ERRDOS,ERRlock);
3779 if (remove_oplock(fsp, break_to_none) == False) {
3780 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3781 fsp->fsp_name ));
3784 /* if this is a pure oplock break request then don't send a reply */
3785 if (num_locks == 0 && num_ulocks == 0) {
3786 /* Sanity check - ensure a pure oplock break is not a
3787 chained request. */
3788 if(CVAL(inbuf,smb_vwv0) != 0xff)
3789 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3790 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3791 END_PROFILE(SMBlockingX);
3792 return -1;
3797 * We do this check *after* we have checked this is not a oplock break
3798 * response message. JRA.
3801 release_level_2_oplocks_on_change(fsp);
3803 /* Data now points at the beginning of the list
3804 of smb_unlkrng structs */
3805 for(i = 0; i < (int)num_ulocks; i++) {
3806 lock_pid = get_lock_pid( data, i, large_file_format);
3807 count = get_lock_count( data, i, large_file_format);
3808 offset = get_lock_offset( data, i, large_file_format, &err);
3811 * There is no error code marked "stupid client bug".... :-).
3813 if(err) {
3814 END_PROFILE(SMBlockingX);
3815 return ERROR_DOS(ERRDOS,ERRnoaccess);
3818 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3819 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3821 status = do_unlock(fsp,conn,lock_pid,count,offset);
3822 if (NT_STATUS_V(status)) {
3823 END_PROFILE(SMBlockingX);
3824 return ERROR_NT(status);
3828 /* Setup the timeout in seconds. */
3830 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3832 /* Now do any requested locks */
3833 data += ((large_file_format ? 20 : 10)*num_ulocks);
3835 /* Data now points at the beginning of the list
3836 of smb_lkrng structs */
3838 for(i = 0; i < (int)num_locks; i++) {
3839 lock_pid = get_lock_pid( data, i, large_file_format);
3840 count = get_lock_count( data, i, large_file_format);
3841 offset = get_lock_offset( data, i, large_file_format, &err);
3844 * There is no error code marked "stupid client bug".... :-).
3846 if(err) {
3847 END_PROFILE(SMBlockingX);
3848 return ERROR_DOS(ERRDOS,ERRnoaccess);
3851 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3852 (double)offset, (double)count, (unsigned int)lock_pid,
3853 fsp->fsp_name, (int)lock_timeout ));
3855 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3856 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3857 if (NT_STATUS_V(status)) {
3858 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3860 * A blocking lock was requested. Package up
3861 * this smb into a queued request and push it
3862 * onto the blocking lock queue.
3864 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3865 END_PROFILE(SMBlockingX);
3866 return -1;
3869 break;
3873 /* If any of the above locks failed, then we must unlock
3874 all of the previous locks (X/Open spec). */
3875 if (i != num_locks && num_locks != 0) {
3877 * Ensure we don't do a remove on the lock that just failed,
3878 * as under POSIX rules, if we have a lock already there, we
3879 * will delete it (and we shouldn't) .....
3881 for(i--; i >= 0; i--) {
3882 lock_pid = get_lock_pid( data, i, large_file_format);
3883 count = get_lock_count( data, i, large_file_format);
3884 offset = get_lock_offset( data, i, large_file_format, &err);
3887 * There is no error code marked "stupid client bug".... :-).
3889 if(err) {
3890 END_PROFILE(SMBlockingX);
3891 return ERROR_DOS(ERRDOS,ERRnoaccess);
3894 do_unlock(fsp,conn,lock_pid,count,offset);
3896 END_PROFILE(SMBlockingX);
3897 return ERROR_NT(status);
3900 set_message(outbuf,2,0,True);
3902 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3903 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3905 END_PROFILE(SMBlockingX);
3906 return chain_reply(inbuf,outbuf,length,bufsize);
3909 /****************************************************************************
3910 Reply to a SMBreadbmpx (read block multiplex) request.
3911 ****************************************************************************/
3913 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3915 ssize_t nread = -1;
3916 ssize_t total_read;
3917 char *data;
3918 SMB_OFF_T startpos;
3919 int outsize;
3920 size_t maxcount;
3921 int max_per_packet;
3922 size_t tcount;
3923 int pad;
3924 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3925 START_PROFILE(SMBreadBmpx);
3927 /* this function doesn't seem to work - disable by default */
3928 if (!lp_readbmpx()) {
3929 END_PROFILE(SMBreadBmpx);
3930 return ERROR_DOS(ERRSRV,ERRuseSTD);
3933 outsize = set_message(outbuf,8,0,True);
3935 CHECK_FSP(fsp,conn);
3936 CHECK_READ(fsp);
3938 startpos = IVAL(inbuf,smb_vwv1);
3939 maxcount = SVAL(inbuf,smb_vwv3);
3941 data = smb_buf(outbuf);
3942 pad = ((long)data)%4;
3943 if (pad)
3944 pad = 4 - pad;
3945 data += pad;
3947 max_per_packet = bufsize-(outsize+pad);
3948 tcount = maxcount;
3949 total_read = 0;
3951 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
3952 END_PROFILE(SMBreadBmpx);
3953 return ERROR_DOS(ERRDOS,ERRlock);
3956 do {
3957 size_t N = MIN(max_per_packet,tcount-total_read);
3959 nread = read_file(fsp,data,startpos,N);
3961 if (nread <= 0)
3962 nread = 0;
3964 if (nread < (ssize_t)N)
3965 tcount = total_read + nread;
3967 set_message(outbuf,8,nread,False);
3968 SIVAL(outbuf,smb_vwv0,startpos);
3969 SSVAL(outbuf,smb_vwv2,tcount);
3970 SSVAL(outbuf,smb_vwv6,nread);
3971 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3973 if (!send_smb(smbd_server_fd(),outbuf))
3974 exit_server("reply_readbmpx: send_smb failed.");
3976 total_read += nread;
3977 startpos += nread;
3978 } while (total_read < (ssize_t)tcount);
3980 END_PROFILE(SMBreadBmpx);
3981 return(-1);
3984 /****************************************************************************
3985 Reply to a SMBsetattrE.
3986 ****************************************************************************/
3988 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3990 struct utimbuf unix_times;
3991 int outsize = 0;
3992 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3993 START_PROFILE(SMBsetattrE);
3995 outsize = set_message(outbuf,0,0,True);
3997 if(!fsp || (fsp->conn != conn)) {
3998 END_PROFILE(SMBgetattrE);
3999 return ERROR_DOS(ERRDOS,ERRbadfid);
4003 * Convert the DOS times into unix times. Ignore create
4004 * time as UNIX can't set this.
4007 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4008 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4011 * Patch from Ray Frush <frush@engr.colostate.edu>
4012 * Sometimes times are sent as zero - ignore them.
4015 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4016 /* Ignore request */
4017 if( DEBUGLVL( 3 ) ) {
4018 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4019 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4021 END_PROFILE(SMBsetattrE);
4022 return(outsize);
4023 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4024 /* set modify time = to access time if modify time was 0 */
4025 unix_times.modtime = unix_times.actime;
4028 /* Set the date on this file */
4029 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4030 END_PROFILE(SMBsetattrE);
4031 return ERROR_DOS(ERRDOS,ERRnoaccess);
4034 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4035 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4037 END_PROFILE(SMBsetattrE);
4038 return(outsize);
4042 /* Back from the dead for OS/2..... JRA. */
4044 /****************************************************************************
4045 Reply to a SMBwritebmpx (write block multiplex primary) request.
4046 ****************************************************************************/
4048 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4050 size_t numtowrite;
4051 ssize_t nwritten = -1;
4052 int outsize = 0;
4053 SMB_OFF_T startpos;
4054 size_t tcount;
4055 BOOL write_through;
4056 int smb_doff;
4057 char *data;
4058 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4059 START_PROFILE(SMBwriteBmpx);
4061 CHECK_FSP(fsp,conn);
4062 CHECK_WRITE(fsp);
4063 CHECK_ERROR(fsp);
4065 tcount = SVAL(inbuf,smb_vwv1);
4066 startpos = IVAL(inbuf,smb_vwv3);
4067 write_through = BITSETW(inbuf+smb_vwv7,0);
4068 numtowrite = SVAL(inbuf,smb_vwv10);
4069 smb_doff = SVAL(inbuf,smb_vwv11);
4071 data = smb_base(inbuf) + smb_doff;
4073 /* If this fails we need to send an SMBwriteC response,
4074 not an SMBwritebmpx - set this up now so we don't forget */
4075 SCVAL(outbuf,smb_com,SMBwritec);
4077 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4078 END_PROFILE(SMBwriteBmpx);
4079 return(ERROR_DOS(ERRDOS,ERRlock));
4082 nwritten = write_file(fsp,data,startpos,numtowrite);
4084 if(lp_syncalways(SNUM(conn)) || write_through)
4085 sync_file(conn,fsp);
4087 if(nwritten < (ssize_t)numtowrite) {
4088 END_PROFILE(SMBwriteBmpx);
4089 return(UNIXERROR(ERRHRD,ERRdiskfull));
4092 /* If the maximum to be written to this file
4093 is greater than what we just wrote then set
4094 up a secondary struct to be attached to this
4095 fd, we will use this to cache error messages etc. */
4097 if((ssize_t)tcount > nwritten) {
4098 write_bmpx_struct *wbms;
4099 if(fsp->wbmpx_ptr != NULL)
4100 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4101 else
4102 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4103 if(!wbms) {
4104 DEBUG(0,("Out of memory in reply_readmpx\n"));
4105 END_PROFILE(SMBwriteBmpx);
4106 return(ERROR_DOS(ERRSRV,ERRnoresource));
4108 wbms->wr_mode = write_through;
4109 wbms->wr_discard = False; /* No errors yet */
4110 wbms->wr_total_written = nwritten;
4111 wbms->wr_errclass = 0;
4112 wbms->wr_error = 0;
4113 fsp->wbmpx_ptr = wbms;
4116 /* We are returning successfully, set the message type back to
4117 SMBwritebmpx */
4118 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4120 outsize = set_message(outbuf,1,0,True);
4122 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4124 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4125 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4127 if (write_through && tcount==nwritten) {
4128 /* We need to send both a primary and a secondary response */
4129 smb_setlen(outbuf,outsize - 4);
4130 if (!send_smb(smbd_server_fd(),outbuf))
4131 exit_server("reply_writebmpx: send_smb failed.");
4133 /* Now the secondary */
4134 outsize = set_message(outbuf,1,0,True);
4135 SCVAL(outbuf,smb_com,SMBwritec);
4136 SSVAL(outbuf,smb_vwv0,nwritten);
4139 END_PROFILE(SMBwriteBmpx);
4140 return(outsize);
4143 /****************************************************************************
4144 Reply to a SMBwritebs (write block multiplex secondary) request.
4145 ****************************************************************************/
4147 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4149 size_t numtowrite;
4150 ssize_t nwritten = -1;
4151 int outsize = 0;
4152 SMB_OFF_T startpos;
4153 size_t tcount;
4154 BOOL write_through;
4155 int smb_doff;
4156 char *data;
4157 write_bmpx_struct *wbms;
4158 BOOL send_response = False;
4159 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4160 START_PROFILE(SMBwriteBs);
4162 CHECK_FSP(fsp,conn);
4163 CHECK_WRITE(fsp);
4165 tcount = SVAL(inbuf,smb_vwv1);
4166 startpos = IVAL(inbuf,smb_vwv2);
4167 numtowrite = SVAL(inbuf,smb_vwv6);
4168 smb_doff = SVAL(inbuf,smb_vwv7);
4170 data = smb_base(inbuf) + smb_doff;
4172 /* We need to send an SMBwriteC response, not an SMBwritebs */
4173 SCVAL(outbuf,smb_com,SMBwritec);
4175 /* This fd should have an auxiliary struct attached,
4176 check that it does */
4177 wbms = fsp->wbmpx_ptr;
4178 if(!wbms) {
4179 END_PROFILE(SMBwriteBs);
4180 return(-1);
4183 /* If write through is set we can return errors, else we must cache them */
4184 write_through = wbms->wr_mode;
4186 /* Check for an earlier error */
4187 if(wbms->wr_discard) {
4188 END_PROFILE(SMBwriteBs);
4189 return -1; /* Just discard the packet */
4192 nwritten = write_file(fsp,data,startpos,numtowrite);
4194 if(lp_syncalways(SNUM(conn)) || write_through)
4195 sync_file(conn,fsp);
4197 if (nwritten < (ssize_t)numtowrite) {
4198 if(write_through) {
4199 /* We are returning an error - we can delete the aux struct */
4200 if (wbms)
4201 free((char *)wbms);
4202 fsp->wbmpx_ptr = NULL;
4203 END_PROFILE(SMBwriteBs);
4204 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4206 END_PROFILE(SMBwriteBs);
4207 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4210 /* Increment the total written, if this matches tcount
4211 we can discard the auxiliary struct (hurrah !) and return a writeC */
4212 wbms->wr_total_written += nwritten;
4213 if(wbms->wr_total_written >= tcount) {
4214 if (write_through) {
4215 outsize = set_message(outbuf,1,0,True);
4216 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4217 send_response = True;
4220 free((char *)wbms);
4221 fsp->wbmpx_ptr = NULL;
4224 if(send_response) {
4225 END_PROFILE(SMBwriteBs);
4226 return(outsize);
4229 END_PROFILE(SMBwriteBs);
4230 return(-1);
4233 /****************************************************************************
4234 Reply to a SMBgetattrE.
4235 ****************************************************************************/
4237 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4239 SMB_STRUCT_STAT sbuf;
4240 int outsize = 0;
4241 int mode;
4242 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4243 START_PROFILE(SMBgetattrE);
4245 outsize = set_message(outbuf,11,0,True);
4247 if(!fsp || (fsp->conn != conn)) {
4248 END_PROFILE(SMBgetattrE);
4249 return ERROR_DOS(ERRDOS,ERRbadfid);
4252 /* Do an fstat on this file */
4253 if(fsp_stat(fsp, &sbuf)) {
4254 END_PROFILE(SMBgetattrE);
4255 return(UNIXERROR(ERRDOS,ERRnoaccess));
4258 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4261 * Convert the times into dos times. Set create
4262 * date to be last modify date as UNIX doesn't save
4263 * this.
4266 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4267 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4268 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4270 if (mode & aDIR) {
4271 SIVAL(outbuf,smb_vwv6,0);
4272 SIVAL(outbuf,smb_vwv8,0);
4273 } else {
4274 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4275 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4277 SSVAL(outbuf,smb_vwv10, mode);
4279 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4281 END_PROFILE(SMBgetattrE);
4282 return(outsize);