make sure we give an error for unknown lockingX locktype bits
[Samba/gebeck_regimport.git] / source / smbd / reply.c
blob9d5d34e410fa2bc04e5def92e08ba1ee0c373963
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 fstring remote_machine;
42 extern BOOL global_encrypted_passwords_negotiated;
45 /****************************************************************************
46 reply to an special message
47 ****************************************************************************/
49 int reply_special(char *inbuf,char *outbuf)
51 int outsize = 4;
52 int msg_type = CVAL(inbuf,0);
53 int msg_flags = CVAL(inbuf,1);
54 pstring name1,name2;
56 extern fstring local_machine;
57 int len;
58 char name_type = 0;
60 *name1 = *name2 = 0;
62 memset(outbuf,'\0',smb_size);
64 smb_setlen(outbuf,0);
66 switch (msg_type) {
67 case 0x81: /* session request */
68 SCVAL(outbuf,0,0x82);
69 SCVAL(outbuf,3,0);
70 if (name_len(inbuf+4) > 50 ||
71 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
72 DEBUG(0,("Invalid name length in session request\n"));
73 return(0);
75 name_extract(inbuf,4,name1);
76 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
77 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
78 name1,name2));
80 fstrcpy(remote_machine,name2);
81 remote_machine[15] = 0;
82 trim_string(remote_machine," "," ");
83 strlower(remote_machine);
84 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
86 fstrcpy(local_machine,name1);
87 len = strlen(local_machine);
88 if (len == 16) {
89 name_type = local_machine[15];
90 local_machine[15] = 0;
92 trim_string(local_machine," "," ");
93 strlower(local_machine);
94 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
96 DEBUG(2,("netbios connect: local=%s remote=%s\n",
97 local_machine, remote_machine ));
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(remote_machine);
113 reload_services(True);
114 reopen_logs();
116 claim_connection(NULL,"",MAXSTATUS,True);
118 break;
120 case 0x89: /* session keepalive request
121 (some old clients produce this?) */
122 SCVAL(outbuf,0,SMBkeepalive);
123 SCVAL(outbuf,3,0);
124 break;
126 case 0x82: /* positive session response */
127 case 0x83: /* negative session response */
128 case 0x84: /* retarget session response */
129 DEBUG(0,("Unexpected session response\n"));
130 break;
132 case SMBkeepalive: /* session keepalive */
133 default:
134 return(0);
137 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
138 msg_type, msg_flags));
140 return(outsize);
144 /****************************************************************************
145 Reply to a tcon.
146 ****************************************************************************/
148 int reply_tcon(connection_struct *conn,
149 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
151 pstring service;
152 pstring password;
153 pstring dev;
154 int outsize = 0;
155 uint16 vuid = SVAL(inbuf,smb_uid);
156 int pwlen=0;
157 NTSTATUS nt_status;
158 char *p;
159 DATA_BLOB password_blob;
161 START_PROFILE(SMBtcon);
163 *service = *password = *dev = 0;
165 p = smb_buf(inbuf)+1;
166 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
167 pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
168 p += pwlen;
169 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
171 p = strrchr_m(service,'\\');
172 if (p) {
173 pstrcpy(service, p+1);
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
182 if (!conn) {
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
196 return(outsize);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
205 fstring service;
206 DATA_BLOB password;
207 pstring devicename;
208 NTSTATUS nt_status;
209 uint16 vuid = SVAL(inbuf,smb_uid);
210 int passlen = SVAL(inbuf,smb_vwv3);
211 pstring path;
212 char *p, *q;
213 extern BOOL global_encrypted_passwords_negotiated;
214 START_PROFILE(SMBtconX);
216 *service = *devicename = 0;
218 /* we might have to close an old one */
219 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
220 close_cnum(conn,vuid);
223 if (passlen > MAX_PASS_LEN) {
224 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
227 if (global_encrypted_passwords_negotiated) {
228 password = data_blob(smb_buf(inbuf),passlen);
229 } else {
230 password = data_blob(smb_buf(inbuf),passlen+1);
231 /* Ensure correct termination */
232 password.data[passlen]=0;
235 p = smb_buf(inbuf) + passlen;
236 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
239 * the service name can be either: \\server\share
240 * or share directly like on the DELL PowerVault 705
242 if (*path=='\\') {
243 q = strchr_m(path+2,'\\');
244 if (!q) {
245 END_PROFILE(SMBtconX);
246 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
248 fstrcpy(service,q+1);
250 else
251 fstrcpy(service,path);
253 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
255 DEBUG(4,("Got device type %s\n",devicename));
257 conn = make_connection(service,password,devicename,vuid,&nt_status);
259 data_blob_clear_free(&password);
261 if (!conn) {
262 END_PROFILE(SMBtconX);
263 return ERROR_NT(nt_status);
266 if (Protocol < PROTOCOL_NT1) {
267 set_message(outbuf,2,0,True);
268 p = smb_buf(outbuf);
269 p += srvstr_push(outbuf, p, devicename, -1,
270 STR_TERMINATE|STR_ASCII);
271 set_message_end(outbuf,p);
272 } else {
273 /* NT sets the fstype of IPC$ to the null string */
274 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
276 set_message(outbuf,3,0,True);
278 p = smb_buf(outbuf);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 p += srvstr_push(outbuf, p, fsname, -1,
282 STR_TERMINATE);
284 set_message_end(outbuf,p);
286 /* what does setting this bit do? It is set by NT4 and
287 may affect the ability to autorun mounted cdroms */
288 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
290 init_dfsroot(conn, inbuf, outbuf);
294 DEBUG(3,("tconX service=%s \n",
295 service));
297 /* set the incoming and outgoing tid to the just created one */
298 SSVAL(inbuf,smb_tid,conn->cnum);
299 SSVAL(outbuf,smb_tid,conn->cnum);
301 END_PROFILE(SMBtconX);
302 return chain_reply(inbuf,outbuf,length,bufsize);
306 /****************************************************************************
307 reply to an unknown type
308 ****************************************************************************/
309 int reply_unknown(char *inbuf,char *outbuf)
311 int type;
312 type = CVAL(inbuf,smb_com);
314 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
315 smb_fn_name(type), type, type));
317 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
321 /****************************************************************************
322 reply to an ioctl
323 ****************************************************************************/
324 int reply_ioctl(connection_struct *conn,
325 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
327 uint16 device = SVAL(inbuf,smb_vwv1);
328 uint16 function = SVAL(inbuf,smb_vwv2);
329 uint32 ioctl_code = (device << 16) + function;
330 int replysize, outsize;
331 char *p;
332 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
333 START_PROFILE(SMBioctl);
335 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
337 switch (ioctl_code)
339 case IOCTL_QUERY_JOB_INFO:
340 replysize = 32;
341 break;
342 default:
343 END_PROFILE(SMBioctl);
344 return(ERROR_DOS(ERRSRV,ERRnosupport));
347 outsize = set_message(outbuf,8,replysize+1,True);
348 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
349 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
350 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
351 p = smb_buf(outbuf) + 1; /* Allow for alignment */
353 switch (ioctl_code)
355 case IOCTL_QUERY_JOB_INFO:
356 SSVAL(p,0,fsp->print_jobid); /* Job number */
357 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
358 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
359 break;
362 END_PROFILE(SMBioctl);
363 return outsize;
366 /****************************************************************************
367 reply to a chkpth
368 ****************************************************************************/
369 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
371 int outsize = 0;
372 int mode;
373 pstring name;
374 BOOL ok = False;
375 BOOL bad_path = False;
376 SMB_STRUCT_STAT sbuf;
377 START_PROFILE(SMBchkpth);
379 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
381 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
383 unix_convert(name,conn,0,&bad_path,&sbuf);
385 mode = SVAL(inbuf,smb_vwv0);
387 if (check_name(name,conn)) {
388 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
389 ok = S_ISDIR(sbuf.st_mode);
392 if (!ok) {
393 /* We special case this - as when a Windows machine
394 is parsing a path is steps through the components
395 one at a time - if a component fails it expects
396 ERRbadpath, not ERRbadfile.
398 if(errno == ENOENT) {
399 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
402 return(UNIXERROR(ERRDOS,ERRbadpath));
405 outsize = set_message(outbuf,0,0,True);
407 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
409 END_PROFILE(SMBchkpth);
410 return(outsize);
414 /****************************************************************************
415 reply to a getatr
416 ****************************************************************************/
417 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
419 pstring fname;
420 int outsize = 0;
421 SMB_STRUCT_STAT sbuf;
422 BOOL ok = False;
423 int mode=0;
424 SMB_OFF_T size=0;
425 time_t mtime=0;
426 BOOL bad_path = False;
427 char *p;
428 START_PROFILE(SMBgetatr);
430 p = smb_buf(inbuf) + 1;
431 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
433 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
435 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
436 under WfWg - weird! */
437 if (! (*fname))
439 mode = aHIDDEN | aDIR;
440 if (!CAN_WRITE(conn)) mode |= aRONLY;
441 size = 0;
442 mtime = 0;
443 ok = True;
445 else
447 unix_convert(fname,conn,0,&bad_path,&sbuf);
448 if (check_name(fname,conn))
450 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
452 mode = dos_mode(conn,fname,&sbuf);
453 size = sbuf.st_size;
454 mtime = sbuf.st_mtime;
455 if (mode & aDIR)
456 size = 0;
457 ok = True;
459 else
460 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
464 if (!ok)
466 if((errno == ENOENT) && bad_path)
468 unix_ERR_class = ERRDOS;
469 unix_ERR_code = ERRbadpath;
472 END_PROFILE(SMBgetatr);
473 return(UNIXERROR(ERRDOS,ERRbadfile));
476 outsize = set_message(outbuf,10,0,True);
478 SSVAL(outbuf,smb_vwv0,mode);
479 if(lp_dos_filetime_resolution(SNUM(conn)) )
480 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
481 else
482 put_dos_date3(outbuf,smb_vwv1,mtime);
483 SIVAL(outbuf,smb_vwv3,(uint32)size);
485 if (Protocol >= PROTOCOL_NT1)
486 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
488 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
490 END_PROFILE(SMBgetatr);
491 return(outsize);
495 /****************************************************************************
496 reply to a setatr
497 ****************************************************************************/
498 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
500 pstring fname;
501 int outsize = 0;
502 BOOL ok=False;
503 int mode;
504 time_t mtime;
505 SMB_STRUCT_STAT sbuf;
506 BOOL bad_path = False;
507 char *p;
509 START_PROFILE(SMBsetatr);
511 p = smb_buf(inbuf) + 1;
512 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
513 unix_convert(fname,conn,0,&bad_path,&sbuf);
515 mode = SVAL(inbuf,smb_vwv0);
516 mtime = make_unix_date3(inbuf+smb_vwv1);
518 if (VALID_STAT_OF_DIR(sbuf))
519 mode |= aDIR;
520 else
521 mode &= ~aDIR;
523 if (check_name(fname,conn))
524 ok = (file_chmod(conn,fname,mode,NULL) == 0);
525 if (ok)
526 ok = set_filetime(conn,fname,mtime);
528 if (!ok)
530 if((errno == ENOENT) && bad_path)
532 unix_ERR_class = ERRDOS;
533 unix_ERR_code = ERRbadpath;
536 END_PROFILE(SMBsetatr);
537 return(UNIXERROR(ERRDOS,ERRnoaccess));
540 outsize = set_message(outbuf,0,0,True);
542 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
544 END_PROFILE(SMBsetatr);
545 return(outsize);
549 /****************************************************************************
550 reply to a dskattr
551 ****************************************************************************/
552 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
554 int outsize = 0;
555 SMB_BIG_UINT dfree,dsize,bsize;
556 START_PROFILE(SMBdskattr);
558 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
560 outsize = set_message(outbuf,5,0,True);
562 SSVAL(outbuf,smb_vwv0,dsize);
563 SSVAL(outbuf,smb_vwv1,bsize/512);
564 SSVAL(outbuf,smb_vwv2,512);
565 SSVAL(outbuf,smb_vwv3,dfree);
567 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
569 END_PROFILE(SMBdskattr);
570 return(outsize);
574 /****************************************************************************
575 reply to a search
576 Can be called from SMBsearch, SMBffirst or SMBfunique.
577 ****************************************************************************/
578 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
580 pstring mask;
581 pstring directory;
582 pstring fname;
583 SMB_OFF_T size;
584 int mode;
585 time_t date;
586 int dirtype;
587 int outsize = 0;
588 int numentries = 0;
589 BOOL finished = False;
590 int maxentries;
591 int i;
592 char *p;
593 BOOL ok = False;
594 int status_len;
595 pstring path;
596 char status[21];
597 int dptr_num= -1;
598 BOOL check_descend = False;
599 BOOL expect_close = False;
600 BOOL can_open = True;
601 BOOL bad_path = False;
602 START_PROFILE(SMBsearch);
604 *mask = *directory = *fname = 0;
606 /* If we were called as SMBffirst then we must expect close. */
607 if(CVAL(inbuf,smb_com) == SMBffirst)
608 expect_close = True;
610 outsize = set_message(outbuf,1,3,True);
611 maxentries = SVAL(inbuf,smb_vwv0);
612 dirtype = SVAL(inbuf,smb_vwv1);
613 p = smb_buf(inbuf) + 1;
614 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
615 p++;
616 status_len = SVAL(p, 0);
617 p += 2;
619 /* dirtype &= ~aDIR; */
621 if (status_len == 0)
623 SMB_STRUCT_STAT sbuf;
624 pstring dir2;
626 pstrcpy(directory,path);
627 pstrcpy(dir2,path);
628 unix_convert(directory,conn,0,&bad_path,&sbuf);
629 unix_format(dir2);
631 if (!check_name(directory,conn))
632 can_open = False;
634 p = strrchr_m(dir2,'/');
635 if (p == NULL)
637 pstrcpy(mask,dir2);
638 *dir2 = 0;
640 else
642 *p = 0;
643 pstrcpy(mask,p+1);
646 p = strrchr_m(directory,'/');
647 if (!p)
648 *directory = 0;
649 else
650 *p = 0;
652 if (strlen(directory) == 0)
653 pstrcpy(directory,"./");
654 memset((char *)status,'\0',21);
655 SCVAL(status,0,dirtype);
657 else
659 memcpy(status,p,21);
660 dirtype = CVAL(status,0) & 0x1F;
661 conn->dirptr = dptr_fetch(status+12,&dptr_num);
662 if (!conn->dirptr)
663 goto SearchEmpty;
664 string_set(&conn->dirpath,dptr_path(dptr_num));
665 fstrcpy(mask, dptr_wcard(dptr_num));
668 if (can_open)
670 p = smb_buf(outbuf) + 3;
672 ok = True;
674 if (status_len == 0)
676 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
677 if (dptr_num < 0)
679 if(dptr_num == -2)
681 if((errno == ENOENT) && bad_path)
683 unix_ERR_class = ERRDOS;
684 unix_ERR_code = ERRbadpath;
686 END_PROFILE(SMBsearch);
687 return (UNIXERROR(ERRDOS,ERRnofids));
689 END_PROFILE(SMBsearch);
690 return ERROR_DOS(ERRDOS,ERRnofids);
692 dptr_set_wcard(dptr_num, strdup(mask));
695 DEBUG(4,("dptr_num is %d\n",dptr_num));
697 if (ok)
699 if ((dirtype&0x1F) == aVOLID)
701 memcpy(p,status,21);
702 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
703 dptr_fill(p+12,dptr_num);
704 if (dptr_zero(p+12) && (status_len==0))
705 numentries = 1;
706 else
707 numentries = 0;
708 p += DIR_STRUCT_SIZE;
710 else
712 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
713 conn->dirpath,lp_dontdescend(SNUM(conn))));
714 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
715 check_descend = True;
717 for (i=numentries;(i<maxentries) && !finished;i++)
719 finished =
720 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
721 if (!finished)
723 memcpy(p,status,21);
724 make_dir_struct(p,mask,fname,size,mode,date);
725 dptr_fill(p+12,dptr_num);
726 numentries++;
728 p += DIR_STRUCT_SIZE;
731 } /* if (ok ) */
735 SearchEmpty:
737 if (numentries == 0 || !ok)
739 SCVAL(outbuf,smb_rcls,ERRDOS);
740 SSVAL(outbuf,smb_err,ERRnofiles);
741 dptr_close(&dptr_num);
744 /* If we were called as SMBffirst with smb_search_id == NULL
745 and no entries were found then return error and close dirptr
746 (X/Open spec) */
748 if(ok && expect_close && numentries == 0 && status_len == 0)
750 SCVAL(outbuf,smb_rcls,ERRDOS);
751 SSVAL(outbuf,smb_err,ERRnofiles);
752 /* Also close the dptr - we know it's gone */
753 dptr_close(&dptr_num);
756 /* If we were called as SMBfunique, then we can close the dirptr now ! */
757 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
758 dptr_close(&dptr_num);
760 SSVAL(outbuf,smb_vwv0,numentries);
761 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
762 SCVAL(smb_buf(outbuf),0,5);
763 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
765 if (Protocol >= PROTOCOL_NT1)
766 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
768 outsize += DIR_STRUCT_SIZE*numentries;
769 smb_setlen(outbuf,outsize - 4);
771 if ((! *directory) && dptr_path(dptr_num))
772 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
774 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
775 smb_fn_name(CVAL(inbuf,smb_com)),
776 mask, directory, dirtype, numentries, maxentries ) );
778 END_PROFILE(SMBsearch);
779 return(outsize);
783 /****************************************************************************
784 reply to a fclose (stop directory search)
785 ****************************************************************************/
786 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
788 int outsize = 0;
789 int status_len;
790 pstring path;
791 char status[21];
792 int dptr_num= -2;
793 char *p;
795 START_PROFILE(SMBfclose);
797 outsize = set_message(outbuf,1,0,True);
798 p = smb_buf(inbuf) + 1;
799 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
800 p++;
801 status_len = SVAL(p,0);
802 p += 2;
804 if (status_len == 0) {
805 END_PROFILE(SMBfclose);
806 return ERROR_DOS(ERRSRV,ERRsrverror);
809 memcpy(status,p,21);
811 if(dptr_fetch(status+12,&dptr_num)) {
812 /* Close the dptr - we know it's gone */
813 dptr_close(&dptr_num);
816 SSVAL(outbuf,smb_vwv0,0);
818 DEBUG(3,("search close\n"));
820 END_PROFILE(SMBfclose);
821 return(outsize);
825 /****************************************************************************
826 reply to an open
827 ****************************************************************************/
829 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
831 pstring fname;
832 int outsize = 0;
833 int fmode=0;
834 int share_mode;
835 SMB_OFF_T size = 0;
836 time_t mtime=0;
837 mode_t unixmode;
838 int rmode=0;
839 SMB_STRUCT_STAT sbuf;
840 BOOL bad_path = False;
841 files_struct *fsp;
842 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
843 START_PROFILE(SMBopen);
845 share_mode = SVAL(inbuf,smb_vwv0);
847 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
849 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
851 unix_convert(fname,conn,0,&bad_path,&sbuf);
853 unixmode = unix_mode(conn,aARCH,fname);
855 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
856 unixmode, oplock_request,&rmode,NULL);
858 if (!fsp)
860 if((errno == ENOENT) && bad_path)
862 unix_ERR_class = ERRDOS;
863 unix_ERR_code = ERRbadpath;
865 END_PROFILE(SMBopen);
866 return(UNIXERROR(ERRDOS,ERRnoaccess));
869 size = sbuf.st_size;
870 fmode = dos_mode(conn,fname,&sbuf);
871 mtime = sbuf.st_mtime;
873 if (fmode & aDIR) {
874 DEBUG(3,("attempt to open a directory %s\n",fname));
875 close_file(fsp,False);
876 END_PROFILE(SMBopen);
877 return ERROR_DOS(ERRDOS,ERRnoaccess);
880 outsize = set_message(outbuf,7,0,True);
881 SSVAL(outbuf,smb_vwv0,fsp->fnum);
882 SSVAL(outbuf,smb_vwv1,fmode);
883 if(lp_dos_filetime_resolution(SNUM(conn)) )
884 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
885 else
886 put_dos_date3(outbuf,smb_vwv2,mtime);
887 SIVAL(outbuf,smb_vwv4,(uint32)size);
888 SSVAL(outbuf,smb_vwv6,rmode);
890 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
891 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
894 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
895 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
896 END_PROFILE(SMBopen);
897 return(outsize);
901 /****************************************************************************
902 reply to an open and X
903 ****************************************************************************/
904 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
906 pstring fname;
907 int smb_mode = SVAL(inbuf,smb_vwv3);
908 int smb_attr = SVAL(inbuf,smb_vwv5);
909 /* Breakout the oplock request bits so we can set the
910 reply bits separately. */
911 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
912 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
913 BOOL oplock_request = ex_oplock_request | core_oplock_request;
914 #if 0
915 int open_flags = SVAL(inbuf,smb_vwv2);
916 int smb_sattr = SVAL(inbuf,smb_vwv4);
917 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
918 #endif
919 int smb_ofun = SVAL(inbuf,smb_vwv8);
920 mode_t unixmode;
921 SMB_OFF_T size=0;
922 int fmode=0,mtime=0,rmode=0;
923 SMB_STRUCT_STAT sbuf;
924 int smb_action = 0;
925 BOOL bad_path = False;
926 files_struct *fsp;
927 START_PROFILE(SMBopenX);
929 /* If it's an IPC, pass off the pipe handler. */
930 if (IS_IPC(conn)) {
931 if (lp_nt_pipe_support()) {
932 END_PROFILE(SMBopenX);
933 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
934 } else {
935 END_PROFILE(SMBopenX);
936 return ERROR_DOS(ERRSRV,ERRaccess);
940 /* XXXX we need to handle passed times, sattr and flags */
941 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
943 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
945 unix_convert(fname,conn,0,&bad_path,&sbuf);
947 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
949 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
950 oplock_request, &rmode,&smb_action);
952 if (!fsp)
954 if((errno == ENOENT) && bad_path)
956 unix_ERR_class = ERRDOS;
957 unix_ERR_code = ERRbadpath;
959 END_PROFILE(SMBopenX);
960 return(UNIXERROR(ERRDOS,ERRnoaccess));
963 size = sbuf.st_size;
964 fmode = dos_mode(conn,fname,&sbuf);
965 mtime = sbuf.st_mtime;
966 if (fmode & aDIR) {
967 close_file(fsp,False);
968 END_PROFILE(SMBopenX);
969 return ERROR_DOS(ERRDOS,ERRnoaccess);
972 /* If the caller set the extended oplock request bit
973 and we granted one (by whatever means) - set the
974 correct bit for extended oplock reply.
977 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
978 smb_action |= EXTENDED_OPLOCK_GRANTED;
981 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
982 smb_action |= EXTENDED_OPLOCK_GRANTED;
985 /* If the caller set the core oplock request bit
986 and we granted one (by whatever means) - set the
987 correct bit for core oplock reply.
990 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
991 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
994 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
995 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
998 set_message(outbuf,15,0,True);
999 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1000 SSVAL(outbuf,smb_vwv3,fmode);
1001 if(lp_dos_filetime_resolution(SNUM(conn)) )
1002 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1003 else
1004 put_dos_date3(outbuf,smb_vwv4,mtime);
1005 SIVAL(outbuf,smb_vwv6,(uint32)size);
1006 SSVAL(outbuf,smb_vwv8,rmode);
1007 SSVAL(outbuf,smb_vwv11,smb_action);
1009 END_PROFILE(SMBopenX);
1010 return chain_reply(inbuf,outbuf,length,bufsize);
1014 /****************************************************************************
1015 reply to a SMBulogoffX
1016 ****************************************************************************/
1017 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1019 uint16 vuid = SVAL(inbuf,smb_uid);
1020 user_struct *vuser = get_valid_user_struct(vuid);
1021 START_PROFILE(SMBulogoffX);
1023 if(vuser == 0) {
1024 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1027 /* in user level security we are supposed to close any files
1028 open by this user */
1029 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1030 file_close_user(vuid);
1033 invalidate_vuid(vuid);
1035 set_message(outbuf,2,0,True);
1037 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1039 END_PROFILE(SMBulogoffX);
1040 return chain_reply(inbuf,outbuf,length,bufsize);
1044 /****************************************************************************
1045 reply to a mknew or a create
1046 ****************************************************************************/
1047 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1049 pstring fname;
1050 int com;
1051 int outsize = 0;
1052 int createmode;
1053 mode_t unixmode;
1054 int ofun = 0;
1055 BOOL bad_path = False;
1056 files_struct *fsp;
1057 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1058 SMB_STRUCT_STAT sbuf;
1059 START_PROFILE(SMBcreate);
1061 com = SVAL(inbuf,smb_com);
1063 createmode = SVAL(inbuf,smb_vwv0);
1064 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1066 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1068 unix_convert(fname,conn,0,&bad_path,&sbuf);
1070 if (createmode & aVOLID) {
1071 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1074 unixmode = unix_mode(conn,createmode,fname);
1076 if(com == SMBmknew)
1078 /* We should fail if file exists. */
1079 ofun = FILE_CREATE_IF_NOT_EXIST;
1081 else
1083 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1084 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1087 /* Open file in dos compatibility share mode. */
1088 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1089 ofun, unixmode, oplock_request, NULL, NULL);
1091 if (!fsp)
1093 if((errno == ENOENT) && bad_path)
1095 unix_ERR_class = ERRDOS;
1096 unix_ERR_code = ERRbadpath;
1098 END_PROFILE(SMBcreate);
1099 return(UNIXERROR(ERRDOS,ERRnoaccess));
1102 outsize = set_message(outbuf,1,0,True);
1103 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1105 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1106 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1109 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1110 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1112 DEBUG( 2, ( "new file %s\n", fname ) );
1113 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1114 fname, fsp->fd, createmode, (int)unixmode ) );
1116 END_PROFILE(SMBcreate);
1117 return(outsize);
1121 /****************************************************************************
1122 reply to a create temporary file
1123 ****************************************************************************/
1124 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1126 pstring fname;
1127 int outsize = 0;
1128 int createmode;
1129 mode_t unixmode;
1130 BOOL bad_path = False;
1131 files_struct *fsp;
1132 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1133 int tmpfd;
1134 SMB_STRUCT_STAT sbuf;
1135 char *p, *s;
1137 START_PROFILE(SMBctemp);
1139 createmode = SVAL(inbuf,smb_vwv0);
1140 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1141 pstrcat(fname,"\\TMXXXXXX");
1143 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1145 unix_convert(fname,conn,0,&bad_path,&sbuf);
1147 unixmode = unix_mode(conn,createmode,fname);
1149 tmpfd = smb_mkstemp(fname);
1150 if (tmpfd == -1) {
1151 END_PROFILE(SMBctemp);
1152 return(UNIXERROR(ERRDOS,ERRnoaccess));
1155 vfs_stat(conn,fname,&sbuf);
1157 /* Open file in dos compatibility share mode. */
1158 /* We should fail if file does not exist. */
1159 fsp = open_file_shared(conn,fname,&sbuf,
1160 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1161 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1162 unixmode, oplock_request, NULL, NULL);
1164 /* close fd from smb_mkstemp() */
1165 close(tmpfd);
1167 if (!fsp) {
1168 if((errno == ENOENT) && bad_path) {
1169 unix_ERR_class = ERRDOS;
1170 unix_ERR_code = ERRbadpath;
1172 END_PROFILE(SMBctemp);
1173 return(UNIXERROR(ERRDOS,ERRnoaccess));
1176 outsize = set_message(outbuf,1,0,True);
1177 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1179 /* the returned filename is relative to the directory */
1180 s = strrchr_m(fname, '/');
1181 if (!s) {
1182 s = fname;
1183 } else {
1184 s++;
1187 p = smb_buf(outbuf);
1188 SSVALS(p, 0, -1); /* what is this? not in spec */
1189 SSVAL(p, 2, strlen(s));
1190 p += 4;
1191 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1192 outsize = set_message_end(outbuf, p);
1194 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1195 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1198 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1199 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1201 DEBUG( 2, ( "created temp file %s\n", fname ) );
1202 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1203 fname, fsp->fd, createmode, (int)unixmode ) );
1205 END_PROFILE(SMBctemp);
1206 return(outsize);
1209 /*******************************************************************
1210 Check if a user is allowed to delete a file.
1211 ********************************************************************/
1213 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1215 SMB_STRUCT_STAT sbuf;
1216 int fmode;
1218 if (!CAN_WRITE(conn))
1219 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1221 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1222 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1224 fmode = dos_mode(conn,fname,&sbuf);
1225 if (fmode & aDIR)
1226 return NT_STATUS_FILE_IS_A_DIRECTORY;
1227 if (!lp_delete_readonly(SNUM(conn))) {
1228 if (fmode & aRONLY)
1229 return NT_STATUS_CANNOT_DELETE;
1231 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1232 return NT_STATUS_CANNOT_DELETE;
1234 if (!check_file_sharing(conn,fname,False))
1235 return NT_STATUS_SHARING_VIOLATION;
1237 return NT_STATUS_OK;
1240 /****************************************************************************
1241 The guts of the unlink command, split out so it may be called by the NT SMB
1242 code.
1243 ****************************************************************************/
1245 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1247 pstring directory;
1248 pstring mask;
1249 char *p;
1250 int count=0;
1251 NTSTATUS error = NT_STATUS_OK;
1252 BOOL has_wild;
1253 BOOL exists=False;
1254 BOOL bad_path = False;
1255 BOOL rc = True;
1256 SMB_STRUCT_STAT sbuf;
1258 *directory = *mask = 0;
1260 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1262 p = strrchr_m(name,'/');
1263 if (!p) {
1264 pstrcpy(directory,"./");
1265 pstrcpy(mask,name);
1266 } else {
1267 *p = 0;
1268 pstrcpy(directory,name);
1269 pstrcpy(mask,p+1);
1273 * We should only check the mangled cache
1274 * here if unix_convert failed. This means
1275 * that the path in 'mask' doesn't exist
1276 * on the file system and so we need to look
1277 * for a possible mangle. This patch from
1278 * Tine Smukavec <valentin.smukavec@hermes.si>.
1281 if (!rc && is_mangled(mask))
1282 check_mangled_cache( mask );
1284 has_wild = ms_has_wild(mask);
1286 if (!has_wild) {
1287 pstrcat(directory,"/");
1288 pstrcat(directory,mask);
1289 error = can_delete(directory,conn,dirtype);
1290 if (!NT_STATUS_IS_OK(error)) return error;
1292 if (vfs_unlink(conn,directory) == 0) {
1293 count++;
1295 if (!count)
1296 exists = vfs_file_exist(conn,directory,&sbuf);
1297 } else {
1298 void *dirptr = NULL;
1299 char *dname;
1301 if (check_name(directory,conn))
1302 dirptr = OpenDir(conn, directory, True);
1304 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1305 the pattern matches against the long name, otherwise the short name
1306 We don't implement this yet XXXX
1309 if (dirptr) {
1310 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1312 if (strequal(mask,"????????.???"))
1313 pstrcpy(mask,"*");
1315 while ((dname = ReadDirName(dirptr))) {
1316 pstring fname;
1317 pstrcpy(fname,dname);
1319 if(!mask_match(fname, mask, case_sensitive)) continue;
1321 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1322 error = can_delete(fname,conn,dirtype);
1323 if (!NT_STATUS_IS_OK(error)) continue;
1324 if (vfs_unlink(conn,fname) == 0) count++;
1325 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1327 CloseDir(dirptr);
1331 if (count == 0 && NT_STATUS_IS_OK(error)) {
1332 error = map_nt_error_from_unix(errno);
1335 return error;
1338 /****************************************************************************
1339 Reply to a unlink
1340 ****************************************************************************/
1342 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1343 int dum_buffsize)
1345 int outsize = 0;
1346 pstring name;
1347 int dirtype;
1348 NTSTATUS status;
1349 START_PROFILE(SMBunlink);
1351 dirtype = SVAL(inbuf,smb_vwv0);
1353 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1355 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1357 DEBUG(3,("reply_unlink : %s\n",name));
1359 status = unlink_internals(conn, dirtype, name);
1360 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1363 * Win2k needs a changenotify request response before it will
1364 * update after a rename..
1366 process_pending_change_notify_queue((time_t)0);
1368 outsize = set_message(outbuf,0,0,True);
1370 END_PROFILE(SMBunlink);
1371 return outsize;
1374 /****************************************************************************
1375 Fail for readbraw.
1376 ****************************************************************************/
1378 void fail_readraw(void)
1380 pstring errstr;
1381 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1382 strerror(errno) );
1383 exit_server(errstr);
1386 /****************************************************************************
1387 Reply to a readbraw (core+ protocol).
1388 ****************************************************************************/
1390 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1392 ssize_t maxcount,mincount;
1393 size_t nread = 0;
1394 SMB_OFF_T startpos;
1395 char *header = outbuf;
1396 ssize_t ret=0;
1397 files_struct *fsp;
1398 START_PROFILE(SMBreadbraw);
1401 * Special check if an oplock break has been issued
1402 * and the readraw request croses on the wire, we must
1403 * return a zero length response here.
1406 if(global_oplock_break) {
1407 _smb_setlen(header,0);
1408 if (write_data(smbd_server_fd(),header,4) != 4)
1409 fail_readraw();
1410 DEBUG(5,("readbraw - oplock break finished\n"));
1411 END_PROFILE(SMBreadbraw);
1412 return -1;
1415 fsp = file_fsp(inbuf,smb_vwv0);
1417 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1419 * fsp could be NULL here so use the value from the packet. JRA.
1421 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1422 _smb_setlen(header,0);
1423 if (write_data(smbd_server_fd(),header,4) != 4)
1424 fail_readraw();
1425 END_PROFILE(SMBreadbraw);
1426 return(-1);
1429 CHECK_FSP(fsp,conn);
1431 flush_write_cache(fsp, READRAW_FLUSH);
1433 startpos = IVAL(inbuf,smb_vwv1);
1434 if(CVAL(inbuf,smb_wct) == 10) {
1436 * This is a large offset (64 bit) read.
1438 #ifdef LARGE_SMB_OFF_T
1440 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1442 #else /* !LARGE_SMB_OFF_T */
1445 * Ensure we haven't been sent a >32 bit offset.
1448 if(IVAL(inbuf,smb_vwv8) != 0) {
1449 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1450 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1451 _smb_setlen(header,0);
1452 if (write_data(smbd_server_fd(),header,4) != 4)
1453 fail_readraw();
1454 END_PROFILE(SMBreadbraw);
1455 return(-1);
1458 #endif /* LARGE_SMB_OFF_T */
1460 if(startpos < 0) {
1461 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1462 _smb_setlen(header,0);
1463 if (write_data(smbd_server_fd(),header,4) != 4)
1464 fail_readraw();
1465 END_PROFILE(SMBreadbraw);
1466 return(-1);
1469 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1470 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1472 /* ensure we don't overrun the packet size */
1473 maxcount = MIN(65535,maxcount);
1474 maxcount = MAX(mincount,maxcount);
1476 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1477 SMB_OFF_T size = fsp->size;
1478 SMB_OFF_T sizeneeded = startpos + maxcount;
1480 if (size < sizeneeded) {
1481 SMB_STRUCT_STAT st;
1482 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1483 size = st.st_size;
1484 if (!fsp->can_write)
1485 fsp->size = size;
1488 if (startpos >= size)
1489 nread = 0;
1490 else
1491 nread = MIN(maxcount,(size - startpos));
1494 if (nread < mincount)
1495 nread = 0;
1497 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1498 (int)maxcount, (int)mincount, (int)nread ) );
1500 if (nread > 0) {
1501 ret = read_file(fsp,header+4,startpos,nread);
1502 if (ret < mincount)
1503 ret = 0;
1506 _smb_setlen(header,ret);
1507 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1508 fail_readraw();
1510 DEBUG(5,("readbraw finished\n"));
1511 END_PROFILE(SMBreadbraw);
1512 return -1;
1515 /****************************************************************************
1516 reply to a lockread (core+ protocol)
1517 ****************************************************************************/
1518 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1520 ssize_t nread = -1;
1521 char *data;
1522 int outsize = 0;
1523 SMB_OFF_T startpos;
1524 size_t numtoread;
1525 NTSTATUS status;
1526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1527 START_PROFILE(SMBlockread);
1529 CHECK_FSP(fsp,conn);
1530 CHECK_READ(fsp);
1532 release_level_2_oplocks_on_change(fsp);
1534 numtoread = SVAL(inbuf,smb_vwv1);
1535 startpos = IVAL(inbuf,smb_vwv2);
1537 outsize = set_message(outbuf,5,3,True);
1538 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1539 data = smb_buf(outbuf) + 3;
1542 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1543 * protocol request that predates the read/write lock concept.
1544 * Thus instead of asking for a read lock here we need to ask
1545 * for a write lock. JRA.
1548 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid),
1549 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1551 if (NT_STATUS_V(status)) {
1552 if (lp_blocking_locks(SNUM(conn))) {
1554 * A blocking lock was requested. Package up
1555 * this smb into a queued request and push it
1556 * onto the blocking lock queue.
1558 if(push_blocking_lock_request(inbuf, length, -1, 0))
1559 END_PROFILE(SMBlockread);
1560 return -1;
1562 END_PROFILE(SMBlockread);
1563 return ERROR_NT(status);
1566 nread = read_file(fsp,data,startpos,numtoread);
1568 if (nread < 0) {
1569 END_PROFILE(SMBlockread);
1570 return(UNIXERROR(ERRDOS,ERRnoaccess));
1573 outsize += nread;
1574 SSVAL(outbuf,smb_vwv0,nread);
1575 SSVAL(outbuf,smb_vwv5,nread+3);
1576 SSVAL(smb_buf(outbuf),1,nread);
1578 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1579 fsp->fnum, (int)numtoread, (int)nread));
1581 END_PROFILE(SMBlockread);
1582 return(outsize);
1586 /****************************************************************************
1587 reply to a read
1588 ****************************************************************************/
1590 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1592 size_t numtoread;
1593 ssize_t nread = 0;
1594 char *data;
1595 SMB_OFF_T startpos;
1596 int outsize = 0;
1597 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1598 START_PROFILE(SMBread);
1600 CHECK_FSP(fsp,conn);
1601 CHECK_READ(fsp);
1603 numtoread = SVAL(inbuf,smb_vwv1);
1604 startpos = IVAL(inbuf,smb_vwv2);
1607 outsize = set_message(outbuf,5,3,True);
1608 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1609 data = smb_buf(outbuf) + 3;
1611 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1612 END_PROFILE(SMBread);
1613 return ERROR_DOS(ERRDOS,ERRlock);
1616 if (numtoread > 0)
1617 nread = read_file(fsp,data,startpos,numtoread);
1619 if (nread < 0) {
1620 END_PROFILE(SMBread);
1621 return(UNIXERROR(ERRDOS,ERRnoaccess));
1624 outsize += nread;
1625 SSVAL(outbuf,smb_vwv0,nread);
1626 SSVAL(outbuf,smb_vwv5,nread+3);
1627 SCVAL(smb_buf(outbuf),0,1);
1628 SSVAL(smb_buf(outbuf),1,nread);
1630 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1631 fsp->fnum, (int)numtoread, (int)nread ) );
1633 END_PROFILE(SMBread);
1634 return(outsize);
1638 /****************************************************************************
1639 reply to a read and X
1640 ****************************************************************************/
1641 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1643 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1644 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1645 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1646 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1647 ssize_t nread = -1;
1648 char *data;
1649 START_PROFILE(SMBreadX);
1651 /* If it's an IPC, pass off the pipe handler. */
1652 if (IS_IPC(conn)) {
1653 END_PROFILE(SMBreadX);
1654 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1657 CHECK_FSP(fsp,conn);
1658 CHECK_READ(fsp);
1660 set_message(outbuf,12,0,True);
1661 data = smb_buf(outbuf);
1663 if(CVAL(inbuf,smb_wct) == 12) {
1664 #ifdef LARGE_SMB_OFF_T
1666 * This is a large offset (64 bit) read.
1668 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1670 #else /* !LARGE_SMB_OFF_T */
1673 * Ensure we haven't been sent a >32 bit offset.
1676 if(IVAL(inbuf,smb_vwv10) != 0) {
1677 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1678 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1679 END_PROFILE(SMBreadX);
1680 return ERROR_DOS(ERRDOS,ERRbadaccess);
1683 #endif /* LARGE_SMB_OFF_T */
1687 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1688 END_PROFILE(SMBreadX);
1689 return ERROR_DOS(ERRDOS,ERRlock);
1691 nread = read_file(fsp,data,startpos,smb_maxcnt);
1693 if (nread < 0) {
1694 END_PROFILE(SMBreadX);
1695 return(UNIXERROR(ERRDOS,ERRnoaccess));
1698 SSVAL(outbuf,smb_vwv5,nread);
1699 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1700 SSVAL(smb_buf(outbuf),-2,nread);
1702 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1703 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
1705 END_PROFILE(SMBreadX);
1706 return chain_reply(inbuf,outbuf,length,bufsize);
1709 /****************************************************************************
1710 reply to a writebraw (core+ or LANMAN1.0 protocol)
1711 ****************************************************************************/
1713 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1715 ssize_t nwritten=0;
1716 ssize_t total_written=0;
1717 size_t numtowrite=0;
1718 size_t tcount;
1719 SMB_OFF_T startpos;
1720 char *data=NULL;
1721 BOOL write_through;
1722 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1723 int outsize = 0;
1724 START_PROFILE(SMBwritebraw);
1726 CHECK_FSP(fsp,conn);
1727 CHECK_WRITE(fsp);
1729 tcount = IVAL(inbuf,smb_vwv1);
1730 startpos = IVAL(inbuf,smb_vwv3);
1731 write_through = BITSETW(inbuf+smb_vwv7,0);
1733 /* We have to deal with slightly different formats depending
1734 on whether we are using the core+ or lanman1.0 protocol */
1736 if(Protocol <= PROTOCOL_COREPLUS) {
1737 numtowrite = SVAL(smb_buf(inbuf),-2);
1738 data = smb_buf(inbuf);
1739 } else {
1740 numtowrite = SVAL(inbuf,smb_vwv10);
1741 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1744 /* force the error type */
1745 SCVAL(inbuf,smb_com,SMBwritec);
1746 SCVAL(outbuf,smb_com,SMBwritec);
1748 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1749 END_PROFILE(SMBwritebraw);
1750 return(ERROR_DOS(ERRDOS,ERRlock));
1753 if (numtowrite>0)
1754 nwritten = write_file(fsp,data,startpos,numtowrite);
1756 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1757 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1759 if (nwritten < numtowrite) {
1760 END_PROFILE(SMBwritebraw);
1761 return(UNIXERROR(ERRHRD,ERRdiskfull));
1764 total_written = nwritten;
1766 /* Return a message to the redirector to tell it to send more bytes */
1767 SCVAL(outbuf,smb_com,SMBwritebraw);
1768 SSVALS(outbuf,smb_vwv0,-1);
1769 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1770 if (!send_smb(smbd_server_fd(),outbuf))
1771 exit_server("reply_writebraw: send_smb failed.");
1773 /* Now read the raw data into the buffer and write it */
1774 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1775 exit_server("secondary writebraw failed");
1778 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1779 numtowrite = smb_len(inbuf);
1781 /* Set up outbuf to return the correct return */
1782 outsize = set_message(outbuf,1,0,True);
1783 SCVAL(outbuf,smb_com,SMBwritec);
1784 SSVAL(outbuf,smb_vwv0,total_written);
1786 if (numtowrite != 0) {
1788 if (numtowrite > BUFFER_SIZE) {
1789 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1790 (unsigned int)numtowrite ));
1791 exit_server("secondary writebraw failed");
1794 if (tcount > nwritten+numtowrite) {
1795 DEBUG(3,("Client overestimated the write %d %d %d\n",
1796 (int)tcount,(int)nwritten,(int)numtowrite));
1799 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1800 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1801 strerror(errno) ));
1802 exit_server("secondary writebraw failed");
1805 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1807 if (nwritten < (ssize_t)numtowrite) {
1808 SCVAL(outbuf,smb_rcls,ERRHRD);
1809 SSVAL(outbuf,smb_err,ERRdiskfull);
1812 if (nwritten > 0)
1813 total_written += nwritten;
1816 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1817 sync_file(conn,fsp);
1819 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1820 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1822 /* we won't return a status if write through is not selected - this follows what WfWg does */
1823 END_PROFILE(SMBwritebraw);
1824 if (!write_through && total_written==tcount) {
1826 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1827 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1829 if (!send_keepalive(smbd_server_fd()))
1830 exit_server("reply_writebraw: send of keepalive failed");
1831 return(-1);
1834 return(outsize);
1837 /****************************************************************************
1838 reply to a writeunlock (core+)
1839 ****************************************************************************/
1841 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1842 int size, int dum_buffsize)
1844 ssize_t nwritten = -1;
1845 size_t numtowrite;
1846 SMB_OFF_T startpos;
1847 char *data;
1848 NTSTATUS status;
1849 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1850 int outsize = 0;
1851 START_PROFILE(SMBwriteunlock);
1853 CHECK_FSP(fsp,conn);
1854 CHECK_WRITE(fsp);
1856 numtowrite = SVAL(inbuf,smb_vwv1);
1857 startpos = IVAL(inbuf,smb_vwv2);
1858 data = smb_buf(inbuf) + 3;
1860 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1861 WRITE_LOCK,False)) {
1862 END_PROFILE(SMBwriteunlock);
1863 return ERROR_DOS(ERRDOS,ERRlock);
1866 /* The special X/Open SMB protocol handling of
1867 zero length writes is *NOT* done for
1868 this call */
1869 if(numtowrite == 0)
1870 nwritten = 0;
1871 else
1872 nwritten = write_file(fsp,data,startpos,numtowrite);
1874 if (lp_syncalways(SNUM(conn)))
1875 sync_file(conn,fsp);
1877 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1878 END_PROFILE(SMBwriteunlock);
1879 return(UNIXERROR(ERRDOS,ERRnoaccess));
1882 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
1883 (SMB_BIG_UINT)startpos);
1884 if (NT_STATUS_V(status)) {
1885 END_PROFILE(SMBwriteunlock);
1886 return ERROR_NT(status);
1889 outsize = set_message(outbuf,1,0,True);
1891 SSVAL(outbuf,smb_vwv0,nwritten);
1893 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
1894 fsp->fnum, (int)numtowrite, (int)nwritten));
1896 END_PROFILE(SMBwriteunlock);
1897 return outsize;
1901 /****************************************************************************
1902 Reply to a write.
1903 ****************************************************************************/
1905 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
1907 size_t numtowrite;
1908 ssize_t nwritten = -1;
1909 SMB_OFF_T startpos;
1910 char *data;
1911 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1912 int outsize = 0;
1913 START_PROFILE(SMBwrite);
1915 /* If it's an IPC, pass off the pipe handler. */
1916 if (IS_IPC(conn)) {
1917 END_PROFILE(SMBwrite);
1918 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
1921 CHECK_FSP(fsp,conn);
1922 CHECK_WRITE(fsp);
1924 numtowrite = SVAL(inbuf,smb_vwv1);
1925 startpos = IVAL(inbuf,smb_vwv2);
1926 data = smb_buf(inbuf) + 3;
1928 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1929 END_PROFILE(SMBwrite);
1930 return ERROR_DOS(ERRDOS,ERRlock);
1934 * X/Open SMB protocol says that if smb_vwv1 is
1935 * zero then the file size should be extended or
1936 * truncated to the size given in smb_vwv[2-3].
1939 if(numtowrite == 0) {
1941 * This is actually an allocate call, and set EOF. JRA.
1943 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
1944 if (nwritten < 0) {
1945 END_PROFILE(SMBwrite);
1946 return ERROR_NT(NT_STATUS_DISK_FULL);
1948 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
1949 if (nwritten < 0) {
1950 END_PROFILE(SMBwrite);
1951 return ERROR_NT(NT_STATUS_DISK_FULL);
1953 } else
1954 nwritten = write_file(fsp,data,startpos,numtowrite);
1956 if (lp_syncalways(SNUM(conn)))
1957 sync_file(conn,fsp);
1959 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1960 END_PROFILE(SMBwrite);
1961 return(UNIXERROR(ERRDOS,ERRnoaccess));
1964 outsize = set_message(outbuf,1,0,True);
1966 SSVAL(outbuf,smb_vwv0,nwritten);
1968 if (nwritten < (ssize_t)numtowrite) {
1969 SCVAL(outbuf,smb_rcls,ERRHRD);
1970 SSVAL(outbuf,smb_err,ERRdiskfull);
1973 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
1975 END_PROFILE(SMBwrite);
1976 return(outsize);
1980 /****************************************************************************
1981 reply to a write and X
1982 ****************************************************************************/
1983 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1985 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1986 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1987 size_t numtowrite = SVAL(inbuf,smb_vwv10);
1988 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1989 ssize_t nwritten = -1;
1990 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
1991 unsigned int smblen = smb_len(inbuf);
1992 char *data;
1993 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
1994 START_PROFILE(SMBwriteX);
1996 /* If it's an IPC, pass off the pipe handler. */
1997 if (IS_IPC(conn)) {
1998 END_PROFILE(SMBwriteX);
1999 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2002 CHECK_FSP(fsp,conn);
2003 CHECK_WRITE(fsp);
2005 /* Deal with possible LARGE_WRITEX */
2006 if (large_writeX)
2007 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2009 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2010 END_PROFILE(SMBwriteX);
2011 return ERROR_DOS(ERRDOS,ERRbadmem);
2014 data = smb_base(inbuf) + smb_doff;
2016 if(CVAL(inbuf,smb_wct) == 14) {
2017 #ifdef LARGE_SMB_OFF_T
2019 * This is a large offset (64 bit) write.
2021 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2023 #else /* !LARGE_SMB_OFF_T */
2026 * Ensure we haven't been sent a >32 bit offset.
2029 if(IVAL(inbuf,smb_vwv12) != 0) {
2030 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2031 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2032 END_PROFILE(SMBwriteX);
2033 return ERROR_DOS(ERRDOS,ERRbadaccess);
2036 #endif /* LARGE_SMB_OFF_T */
2039 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2040 END_PROFILE(SMBwriteX);
2041 return ERROR_DOS(ERRDOS,ERRlock);
2044 /* X/Open SMB protocol says that, unlike SMBwrite
2045 if the length is zero then NO truncation is
2046 done, just a write of zero. To truncate a file,
2047 use SMBwrite. */
2048 if(numtowrite == 0)
2049 nwritten = 0;
2050 else
2051 nwritten = write_file(fsp,data,startpos,numtowrite);
2053 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2054 END_PROFILE(SMBwriteX);
2055 return(UNIXERROR(ERRDOS,ERRnoaccess));
2058 set_message(outbuf,6,0,True);
2060 SSVAL(outbuf,smb_vwv2,nwritten);
2061 if (large_writeX)
2062 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2064 if (nwritten < (ssize_t)numtowrite) {
2065 SCVAL(outbuf,smb_rcls,ERRHRD);
2066 SSVAL(outbuf,smb_err,ERRdiskfull);
2069 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2070 fsp->fnum, (int)numtowrite, (int)nwritten));
2072 if (lp_syncalways(SNUM(conn)) || write_through)
2073 sync_file(conn,fsp);
2075 END_PROFILE(SMBwriteX);
2076 return chain_reply(inbuf,outbuf,length,bufsize);
2080 /****************************************************************************
2081 reply to a lseek
2082 ****************************************************************************/
2084 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2086 SMB_OFF_T startpos;
2087 SMB_OFF_T res= -1;
2088 int mode,umode;
2089 int outsize = 0;
2090 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2091 START_PROFILE(SMBlseek);
2093 CHECK_FSP(fsp,conn);
2095 flush_write_cache(fsp, SEEK_FLUSH);
2097 mode = SVAL(inbuf,smb_vwv1) & 3;
2098 startpos = IVALS(inbuf,smb_vwv2);
2100 switch (mode) {
2101 case 0: umode = SEEK_SET; break;
2102 case 1: umode = SEEK_CUR; break;
2103 case 2: umode = SEEK_END; break;
2104 default:
2105 umode = SEEK_SET; break;
2108 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2110 * Check for the special case where a seek before the start
2111 * of the file sets the offset to zero. Added in the CIFS spec,
2112 * section 4.2.7.
2115 if(errno == EINVAL) {
2116 SMB_OFF_T current_pos = startpos;
2118 if(umode == SEEK_CUR) {
2120 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2121 END_PROFILE(SMBlseek);
2122 return(UNIXERROR(ERRDOS,ERRnoaccess));
2125 current_pos += startpos;
2127 } else if (umode == SEEK_END) {
2129 SMB_STRUCT_STAT sbuf;
2131 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2132 END_PROFILE(SMBlseek);
2133 return(UNIXERROR(ERRDOS,ERRnoaccess));
2136 current_pos += sbuf.st_size;
2139 if(current_pos < 0)
2140 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2143 if(res == -1) {
2144 END_PROFILE(SMBlseek);
2145 return(UNIXERROR(ERRDOS,ERRnoaccess));
2149 fsp->pos = res;
2151 outsize = set_message(outbuf,2,0,True);
2152 SIVAL(outbuf,smb_vwv0,res);
2154 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2155 fsp->fnum, (double)startpos, (double)res, mode));
2157 END_PROFILE(SMBlseek);
2158 return(outsize);
2161 /****************************************************************************
2162 reply to a flush
2163 ****************************************************************************/
2165 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2167 int outsize = set_message(outbuf,0,0,True);
2168 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2169 START_PROFILE(SMBflush);
2171 CHECK_FSP(fsp,conn);
2173 if (!fsp) {
2174 file_sync_all(conn);
2175 } else {
2176 sync_file(conn,fsp);
2179 DEBUG(3,("flush\n"));
2180 END_PROFILE(SMBflush);
2181 return(outsize);
2185 /****************************************************************************
2186 reply to a exit
2187 ****************************************************************************/
2188 int reply_exit(connection_struct *conn,
2189 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2191 int outsize;
2192 START_PROFILE(SMBexit);
2193 outsize = set_message(outbuf,0,0,True);
2195 DEBUG(3,("exit\n"));
2197 END_PROFILE(SMBexit);
2198 return(outsize);
2202 /****************************************************************************
2203 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2204 ****************************************************************************/
2205 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2206 int dum_buffsize)
2208 int outsize = 0;
2209 time_t mtime;
2210 int32 eclass = 0, err = 0;
2211 files_struct *fsp = NULL;
2212 START_PROFILE(SMBclose);
2214 outsize = set_message(outbuf,0,0,True);
2216 /* If it's an IPC, pass off to the pipe handler. */
2217 if (IS_IPC(conn)) {
2218 END_PROFILE(SMBclose);
2219 return reply_pipe_close(conn, inbuf,outbuf);
2222 fsp = file_fsp(inbuf,smb_vwv0);
2225 * We can only use CHECK_FSP if we know it's not a directory.
2228 if(!fsp || (fsp->conn != conn)) {
2229 END_PROFILE(SMBclose);
2230 return ERROR_DOS(ERRDOS,ERRbadfid);
2233 if(fsp->is_directory || fsp->stat_open) {
2235 * Special case - close NT SMB directory or stat file
2236 * handle.
2238 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2239 close_file(fsp,True);
2240 } else {
2242 * Close ordinary file.
2244 int close_err;
2245 pstring file_name;
2247 /* Save the name for time set in close. */
2248 pstrcpy( file_name, fsp->fsp_name);
2250 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2251 fsp->fd, fsp->fnum,
2252 conn->num_files_open));
2255 * close_file() returns the unix errno if an error
2256 * was detected on close - normally this is due to
2257 * a disk full error. If not then it was probably an I/O error.
2260 if((close_err = close_file(fsp,True)) != 0) {
2261 errno = close_err;
2262 END_PROFILE(SMBclose);
2263 return (UNIXERROR(ERRHRD,ERRgeneral));
2267 * Now take care of any time sent in the close.
2270 mtime = make_unix_date3(inbuf+smb_vwv1);
2272 /* try and set the date */
2273 set_filetime(conn, file_name, mtime);
2277 /* We have a cached error */
2278 if(eclass || err) {
2279 END_PROFILE(SMBclose);
2280 return ERROR_DOS(eclass,err);
2283 END_PROFILE(SMBclose);
2284 return(outsize);
2288 /****************************************************************************
2289 reply to a writeclose (Core+ protocol)
2290 ****************************************************************************/
2292 int reply_writeclose(connection_struct *conn,
2293 char *inbuf,char *outbuf, int size, int dum_buffsize)
2295 size_t numtowrite;
2296 ssize_t nwritten = -1;
2297 int outsize = 0;
2298 int close_err = 0;
2299 SMB_OFF_T startpos;
2300 char *data;
2301 time_t mtime;
2302 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2303 START_PROFILE(SMBwriteclose);
2305 CHECK_FSP(fsp,conn);
2306 CHECK_WRITE(fsp);
2308 numtowrite = SVAL(inbuf,smb_vwv1);
2309 startpos = IVAL(inbuf,smb_vwv2);
2310 mtime = make_unix_date3(inbuf+smb_vwv4);
2311 data = smb_buf(inbuf) + 1;
2313 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2314 END_PROFILE(SMBwriteclose);
2315 return ERROR_DOS(ERRDOS,ERRlock);
2318 nwritten = write_file(fsp,data,startpos,numtowrite);
2320 set_filetime(conn, fsp->fsp_name,mtime);
2322 close_err = close_file(fsp,True);
2324 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2325 fsp->fnum, (int)numtowrite, (int)nwritten,
2326 conn->num_files_open));
2328 if (nwritten <= 0) {
2329 END_PROFILE(SMBwriteclose);
2330 return(UNIXERROR(ERRDOS,ERRnoaccess));
2333 if(close_err != 0) {
2334 errno = close_err;
2335 END_PROFILE(SMBwriteclose);
2336 return(UNIXERROR(ERRHRD,ERRgeneral));
2339 outsize = set_message(outbuf,1,0,True);
2341 SSVAL(outbuf,smb_vwv0,nwritten);
2342 END_PROFILE(SMBwriteclose);
2343 return(outsize);
2347 /****************************************************************************
2348 reply to a lock
2349 ****************************************************************************/
2350 int reply_lock(connection_struct *conn,
2351 char *inbuf,char *outbuf, int length, int dum_buffsize)
2353 int outsize = set_message(outbuf,0,0,True);
2354 SMB_BIG_UINT count,offset;
2355 NTSTATUS status;
2356 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2357 START_PROFILE(SMBlock);
2359 CHECK_FSP(fsp,conn);
2361 release_level_2_oplocks_on_change(fsp);
2363 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2364 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2366 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2367 fsp->fd, fsp->fnum, (double)offset, (double)count));
2369 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2370 if (NT_STATUS_V(status)) {
2371 if (lp_blocking_locks(SNUM(conn))) {
2373 * A blocking lock was requested. Package up
2374 * this smb into a queued request and push it
2375 * onto the blocking lock queue.
2377 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2378 END_PROFILE(SMBlock);
2379 return -1;
2382 END_PROFILE(SMBlock);
2383 return ERROR_NT(status);
2386 END_PROFILE(SMBlock);
2387 return(outsize);
2391 /****************************************************************************
2392 reply to a unlock
2393 ****************************************************************************/
2394 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2395 int dum_buffsize)
2397 int outsize = set_message(outbuf,0,0,True);
2398 SMB_BIG_UINT count,offset;
2399 NTSTATUS status;
2400 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2401 START_PROFILE(SMBunlock);
2403 CHECK_FSP(fsp,conn);
2405 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2406 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2408 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2409 if (NT_STATUS_V(status)) {
2410 END_PROFILE(SMBunlock);
2411 return ERROR_NT(status);
2414 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2415 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2417 END_PROFILE(SMBunlock);
2418 return(outsize);
2422 /****************************************************************************
2423 reply to a tdis
2424 ****************************************************************************/
2425 int reply_tdis(connection_struct *conn,
2426 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2428 int outsize = set_message(outbuf,0,0,True);
2429 uint16 vuid;
2430 START_PROFILE(SMBtdis);
2432 vuid = SVAL(inbuf,smb_uid);
2434 if (!conn) {
2435 DEBUG(4,("Invalid connection in tdis\n"));
2436 END_PROFILE(SMBtdis);
2437 return ERROR_DOS(ERRSRV,ERRinvnid);
2440 conn->used = False;
2442 close_cnum(conn,vuid);
2444 END_PROFILE(SMBtdis);
2445 return outsize;
2450 /****************************************************************************
2451 reply to a echo
2452 ****************************************************************************/
2453 int reply_echo(connection_struct *conn,
2454 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2456 int smb_reverb = SVAL(inbuf,smb_vwv0);
2457 int seq_num;
2458 unsigned int data_len = smb_buflen(inbuf);
2459 int outsize = set_message(outbuf,1,data_len,True);
2460 START_PROFILE(SMBecho);
2462 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2464 /* copy any incoming data back out */
2465 if (data_len > 0)
2466 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2468 if (smb_reverb > 100) {
2469 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2470 smb_reverb = 100;
2473 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2474 SSVAL(outbuf,smb_vwv0,seq_num);
2476 smb_setlen(outbuf,outsize - 4);
2478 if (!send_smb(smbd_server_fd(),outbuf))
2479 exit_server("reply_echo: send_smb failed.");
2482 DEBUG(3,("echo %d times\n", smb_reverb));
2484 smb_echo_count++;
2486 END_PROFILE(SMBecho);
2487 return -1;
2491 /****************************************************************************
2492 reply to a printopen
2493 ****************************************************************************/
2494 int reply_printopen(connection_struct *conn,
2495 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2497 int outsize = 0;
2498 files_struct *fsp;
2499 START_PROFILE(SMBsplopen);
2501 if (!CAN_PRINT(conn)) {
2502 END_PROFILE(SMBsplopen);
2503 return ERROR_DOS(ERRDOS,ERRnoaccess);
2506 /* Open for exclusive use, write only. */
2507 fsp = print_fsp_open(conn, NULL);
2509 if (!fsp) {
2510 END_PROFILE(SMBsplopen);
2511 return(UNIXERROR(ERRDOS,ERRnoaccess));
2514 outsize = set_message(outbuf,1,0,True);
2515 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2517 DEBUG(3,("openprint fd=%d fnum=%d\n",
2518 fsp->fd, fsp->fnum));
2520 END_PROFILE(SMBsplopen);
2521 return(outsize);
2525 /****************************************************************************
2526 reply to a printclose
2527 ****************************************************************************/
2528 int reply_printclose(connection_struct *conn,
2529 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2531 int outsize = set_message(outbuf,0,0,True);
2532 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2533 int close_err = 0;
2534 START_PROFILE(SMBsplclose);
2536 CHECK_FSP(fsp,conn);
2538 if (!CAN_PRINT(conn)) {
2539 END_PROFILE(SMBsplclose);
2540 return ERROR_DOS(ERRDOS,ERRnoaccess);
2543 DEBUG(3,("printclose fd=%d fnum=%d\n",
2544 fsp->fd,fsp->fnum));
2546 close_err = close_file(fsp,True);
2548 if(close_err != 0) {
2549 errno = close_err;
2550 END_PROFILE(SMBsplclose);
2551 return(UNIXERROR(ERRHRD,ERRgeneral));
2554 END_PROFILE(SMBsplclose);
2555 return(outsize);
2559 /****************************************************************************
2560 reply to a printqueue
2561 ****************************************************************************/
2562 int reply_printqueue(connection_struct *conn,
2563 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2565 int outsize = set_message(outbuf,2,3,True);
2566 int max_count = SVAL(inbuf,smb_vwv0);
2567 int start_index = SVAL(inbuf,smb_vwv1);
2568 START_PROFILE(SMBsplretq);
2570 /* we used to allow the client to get the cnum wrong, but that
2571 is really quite gross and only worked when there was only
2572 one printer - I think we should now only accept it if they
2573 get it right (tridge) */
2574 if (!CAN_PRINT(conn)) {
2575 END_PROFILE(SMBsplretq);
2576 return ERROR_DOS(ERRDOS,ERRnoaccess);
2579 SSVAL(outbuf,smb_vwv0,0);
2580 SSVAL(outbuf,smb_vwv1,0);
2581 SCVAL(smb_buf(outbuf),0,1);
2582 SSVAL(smb_buf(outbuf),1,0);
2584 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2585 start_index, max_count));
2588 print_queue_struct *queue = NULL;
2589 print_status_struct status;
2590 char *p = smb_buf(outbuf) + 3;
2591 int count = print_queue_status(SNUM(conn), &queue, &status);
2592 int num_to_get = ABS(max_count);
2593 int first = (max_count>0?start_index:start_index+max_count+1);
2594 int i;
2596 if (first >= count)
2597 num_to_get = 0;
2598 else
2599 num_to_get = MIN(num_to_get,count-first);
2602 for (i=first;i<first+num_to_get;i++) {
2603 put_dos_date2(p,0,queue[i].time);
2604 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2605 SSVAL(p,5, queue[i].job);
2606 SIVAL(p,7,queue[i].size);
2607 SCVAL(p,11,0);
2608 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
2609 p += 28;
2612 if (count > 0) {
2613 outsize = set_message(outbuf,2,28*count+3,False);
2614 SSVAL(outbuf,smb_vwv0,count);
2615 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2616 SCVAL(smb_buf(outbuf),0,1);
2617 SSVAL(smb_buf(outbuf),1,28*count);
2620 SAFE_FREE(queue);
2622 DEBUG(3,("%d entries returned in queue\n",count));
2625 END_PROFILE(SMBsplretq);
2626 return(outsize);
2630 /****************************************************************************
2631 reply to a printwrite
2632 ****************************************************************************/
2633 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2635 int numtowrite;
2636 int outsize = set_message(outbuf,0,0,True);
2637 char *data;
2638 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2639 START_PROFILE(SMBsplwr);
2641 if (!CAN_PRINT(conn)) {
2642 END_PROFILE(SMBsplwr);
2643 return ERROR_DOS(ERRDOS,ERRnoaccess);
2646 CHECK_FSP(fsp,conn);
2647 CHECK_WRITE(fsp);
2649 numtowrite = SVAL(smb_buf(inbuf),1);
2650 data = smb_buf(inbuf) + 3;
2652 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2653 END_PROFILE(SMBsplwr);
2654 return(UNIXERROR(ERRDOS,ERRnoaccess));
2657 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2659 END_PROFILE(SMBsplwr);
2660 return(outsize);
2664 /****************************************************************************
2665 The guts of the mkdir command, split out so it may be called by the NT SMB
2666 code.
2667 ****************************************************************************/
2668 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2670 BOOL bad_path = False;
2671 SMB_STRUCT_STAT sbuf;
2672 int ret= -1;
2674 unix_convert(directory,conn,0,&bad_path,&sbuf);
2676 if (check_name(directory, conn))
2677 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2679 if (ret == -1) {
2680 return map_nt_error_from_unix(errno);
2683 return NT_STATUS_OK;
2686 /****************************************************************************
2687 Reply to a mkdir.
2688 ****************************************************************************/
2690 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2692 pstring directory;
2693 int outsize;
2694 NTSTATUS status;
2695 START_PROFILE(SMBmkdir);
2697 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
2699 status = mkdir_internal(conn, directory);
2700 if (!NT_STATUS_IS_OK(status))
2701 return ERROR_NT(status);
2703 outsize = set_message(outbuf,0,0,True);
2705 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2707 END_PROFILE(SMBmkdir);
2708 return(outsize);
2711 /****************************************************************************
2712 Static function used by reply_rmdir to delete an entire directory
2713 tree recursively. Return False on ok, True on fail.
2714 ****************************************************************************/
2716 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2718 char *dname = NULL;
2719 BOOL ret = False;
2720 void *dirptr = OpenDir(conn, directory, False);
2722 if(dirptr == NULL)
2723 return True;
2725 while((dname = ReadDirName(dirptr))) {
2726 pstring fullname;
2727 SMB_STRUCT_STAT st;
2729 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2730 continue;
2732 /* Construct the full name. */
2733 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2734 errno = ENOMEM;
2735 ret = True;
2736 break;
2739 pstrcpy(fullname, directory);
2740 pstrcat(fullname, "/");
2741 pstrcat(fullname, dname);
2743 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2744 ret = True;
2745 break;
2748 if(st.st_mode & S_IFDIR) {
2749 if(recursive_rmdir(conn, fullname)!=0) {
2750 ret = True;
2751 break;
2753 if(vfs_rmdir(conn,fullname) != 0) {
2754 ret = True;
2755 break;
2757 } else if(vfs_unlink(conn,fullname) != 0) {
2758 ret = True;
2759 break;
2762 CloseDir(dirptr);
2763 return ret;
2766 /****************************************************************************
2767 The internals of the rmdir code - called elsewhere.
2768 ****************************************************************************/
2770 BOOL rmdir_internals(connection_struct *conn, char *directory)
2772 BOOL ok;
2774 ok = (vfs_rmdir(conn,directory) == 0);
2775 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2777 * Check to see if the only thing in this directory are
2778 * vetoed files/directories. If so then delete them and
2779 * retry. If we fail to delete any of them (and we *don't*
2780 * do a recursive delete) then fail the rmdir.
2782 BOOL all_veto_files = True;
2783 char *dname;
2784 void *dirptr = OpenDir(conn, directory, False);
2786 if(dirptr != NULL) {
2787 int dirpos = TellDir(dirptr);
2788 while ((dname = ReadDirName(dirptr))) {
2789 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2790 continue;
2791 if(!IS_VETO_PATH(conn, dname)) {
2792 all_veto_files = False;
2793 break;
2797 if(all_veto_files) {
2798 SeekDir(dirptr,dirpos);
2799 while ((dname = ReadDirName(dirptr))) {
2800 pstring fullname;
2801 SMB_STRUCT_STAT st;
2803 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2804 continue;
2806 /* Construct the full name. */
2807 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2808 errno = ENOMEM;
2809 break;
2812 pstrcpy(fullname, directory);
2813 pstrcat(fullname, "/");
2814 pstrcat(fullname, dname);
2816 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2817 break;
2818 if(st.st_mode & S_IFDIR) {
2819 if(lp_recursive_veto_delete(SNUM(conn))) {
2820 if(recursive_rmdir(conn, fullname) != 0)
2821 break;
2823 if(vfs_rmdir(conn,fullname) != 0)
2824 break;
2825 } else if(vfs_unlink(conn,fullname) != 0)
2826 break;
2828 CloseDir(dirptr);
2829 /* Retry the rmdir */
2830 ok = (vfs_rmdir(conn,directory) == 0);
2831 } else {
2832 CloseDir(dirptr);
2834 } else {
2835 errno = ENOTEMPTY;
2839 if (!ok)
2840 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2842 return ok;
2845 /****************************************************************************
2846 Reply to a rmdir.
2847 ****************************************************************************/
2849 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2851 pstring directory;
2852 int outsize = 0;
2853 BOOL ok = False;
2854 BOOL bad_path = False;
2855 SMB_STRUCT_STAT sbuf;
2856 START_PROFILE(SMBrmdir);
2858 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
2860 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
2862 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
2864 if (check_name(directory,conn))
2866 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2867 ok = rmdir_internals(conn, directory);
2870 if (!ok)
2872 if((errno == ENOENT) && bad_path)
2874 unix_ERR_class = ERRDOS;
2875 unix_ERR_code = ERRbadpath;
2877 END_PROFILE(SMBrmdir);
2878 return(UNIXERROR(ERRDOS,ERRbadpath));
2881 outsize = set_message(outbuf,0,0,True);
2883 DEBUG( 3, ( "rmdir %s\n", directory ) );
2885 END_PROFILE(SMBrmdir);
2886 return(outsize);
2890 /*******************************************************************
2891 resolve wildcards in a filename rename
2892 ********************************************************************/
2893 static BOOL resolve_wildcards(char *name1,char *name2)
2895 fstring root1,root2;
2896 fstring ext1,ext2;
2897 char *p,*p2;
2899 name1 = strrchr_m(name1,'/');
2900 name2 = strrchr_m(name2,'/');
2902 if (!name1 || !name2) return(False);
2904 fstrcpy(root1,name1);
2905 fstrcpy(root2,name2);
2906 p = strrchr_m(root1,'.');
2907 if (p) {
2908 *p = 0;
2909 fstrcpy(ext1,p+1);
2910 } else {
2911 fstrcpy(ext1,"");
2913 p = strrchr_m(root2,'.');
2914 if (p) {
2915 *p = 0;
2916 fstrcpy(ext2,p+1);
2917 } else {
2918 fstrcpy(ext2,"");
2921 p = root1;
2922 p2 = root2;
2923 while (*p2) {
2924 if (*p2 == '?') {
2925 *p2 = *p;
2926 p2++;
2927 } else {
2928 p2++;
2930 if (*p) p++;
2933 p = ext1;
2934 p2 = ext2;
2935 while (*p2) {
2936 if (*p2 == '?') {
2937 *p2 = *p;
2938 p2++;
2939 } else {
2940 p2++;
2942 if (*p) p++;
2945 pstrcpy(name2,root2);
2946 if (ext2[0]) {
2947 pstrcat(name2,".");
2948 pstrcat(name2,ext2);
2951 return(True);
2954 /*******************************************************************
2955 Check if a user is allowed to rename a file.
2956 ********************************************************************/
2958 static NTSTATUS can_rename(char *fname,connection_struct *conn)
2960 if (!CAN_WRITE(conn))
2961 return NT_STATUS_ACCESS_DENIED;
2963 if (!check_file_sharing(conn,fname,True))
2964 return NT_STATUS_SHARING_VIOLATION;
2966 return NT_STATUS_OK;
2969 /****************************************************************************
2970 The guts of the rename command, split out so it may be called by the NT SMB
2971 code.
2972 ****************************************************************************/
2974 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
2976 pstring directory;
2977 pstring mask;
2978 pstring newname_last_component;
2979 char *p;
2980 BOOL has_wild;
2981 BOOL bad_path1 = False;
2982 BOOL bad_path2 = False;
2983 int count=0;
2984 NTSTATUS error = NT_STATUS_OK;
2985 BOOL rc = True;
2986 SMB_STRUCT_STAT sbuf1, sbuf2;
2988 *directory = *mask = 0;
2990 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
2991 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
2994 * Split the old name into directory and last component
2995 * strings. Note that unix_convert may have stripped off a
2996 * leading ./ from both name and newname if the rename is
2997 * at the root of the share. We need to make sure either both
2998 * name and newname contain a / character or neither of them do
2999 * as this is checked in resolve_wildcards().
3002 p = strrchr_m(name,'/');
3003 if (!p) {
3004 pstrcpy(directory,".");
3005 pstrcpy(mask,name);
3006 } else {
3007 *p = 0;
3008 pstrcpy(directory,name);
3009 pstrcpy(mask,p+1);
3010 *p = '/'; /* Replace needed for exceptional test below. */
3014 * We should only check the mangled cache
3015 * here if unix_convert failed. This means
3016 * that the path in 'mask' doesn't exist
3017 * on the file system and so we need to look
3018 * for a possible mangle. This patch from
3019 * Tine Smukavec <valentin.smukavec@hermes.si>.
3022 #if 0
3023 if (!rc && is_mangled(mask))
3024 check_mangled_cache( mask );
3025 #endif
3026 if (!rc)
3028 char *unmangled;
3030 unmangled = dos_unmangle(mask);
3031 if (unmangled)
3032 strncpy(mask, unmangled, strlen(unmangled) + 1);
3034 SAFE_FREE(unmangled);
3037 has_wild = ms_has_wild(mask);
3039 if (!has_wild) {
3041 * No wildcards - just process the one file.
3043 BOOL is_short_name = is_8_3(name, True);
3045 /* Add a terminating '/' to the directory name. */
3046 pstrcat(directory,"/");
3047 pstrcat(directory,mask);
3049 /* Ensure newname contains a '/' also */
3050 if(strrchr_m(newname,'/') == 0) {
3051 pstring tmpstr;
3053 pstrcpy(tmpstr, "./");
3054 pstrcat(tmpstr, newname);
3055 pstrcpy(newname, tmpstr);
3058 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3059 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3060 case_sensitive, case_preserve, short_case_preserve, directory,
3061 newname, newname_last_component, is_short_name));
3064 * Check for special case with case preserving and not
3065 * case sensitive, if directory and newname are identical,
3066 * and the old last component differs from the original
3067 * last component only by case, then we should allow
3068 * the rename (user is trying to change the case of the
3069 * filename).
3071 if((case_sensitive == False) &&
3072 (((case_preserve == True) &&
3073 (is_short_name == False)) ||
3074 ((short_case_preserve == True) &&
3075 (is_short_name == True))) &&
3076 strcsequal(directory, newname)) {
3077 pstring newname_modified_last_component;
3080 * Get the last component of the modified name.
3081 * Note that we guarantee that newname contains a '/'
3082 * character above.
3084 p = strrchr_m(newname,'/');
3085 pstrcpy(newname_modified_last_component,p+1);
3087 if(strcsequal(newname_modified_last_component,
3088 newname_last_component) == False) {
3090 * Replace the modified last component with
3091 * the original.
3093 pstrcpy(p+1, newname_last_component);
3097 resolve_wildcards(directory,newname);
3100 * The source object must exist.
3103 if (!vfs_object_exist(conn, directory, NULL)) {
3104 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3105 directory,newname));
3107 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3109 * Must return different errors depending on whether the parent
3110 * directory existed or not.
3113 p = strrchr_m(directory, '/');
3114 if (!p)
3115 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3116 *p = '\0';
3117 if (vfs_object_exist(conn, directory, NULL))
3118 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3119 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3121 error = map_nt_error_from_unix(errno);
3122 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3123 get_nt_error_msg(error), directory,newname));
3125 return error;
3128 error = can_rename(directory,conn);
3130 if (!NT_STATUS_IS_OK(error)) {
3131 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3132 get_nt_error_msg(error), directory,newname));
3133 return error;
3137 * If the src and dest names are identical - including case,
3138 * don't do the rename, just return success.
3141 if (strcsequal(directory, newname)) {
3142 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3143 return NT_STATUS_OK;
3146 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3147 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3148 directory,newname));
3149 return NT_STATUS_OBJECT_NAME_COLLISION;
3152 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3153 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3154 directory,newname));
3155 return NT_STATUS_OK;
3158 if (errno == ENOTDIR || errno == EISDIR)
3159 error = NT_STATUS_OBJECT_NAME_COLLISION;
3160 else
3161 error = map_nt_error_from_unix(errno);
3163 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3164 get_nt_error_msg(error), directory,newname));
3166 return error;
3167 } else {
3169 * Wildcards - process each file that matches.
3171 void *dirptr = NULL;
3172 char *dname;
3173 pstring destname;
3175 if (check_name(directory,conn))
3176 dirptr = OpenDir(conn, directory, True);
3178 if (dirptr) {
3179 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3181 if (strequal(mask,"????????.???"))
3182 pstrcpy(mask,"*");
3184 while ((dname = ReadDirName(dirptr))) {
3185 pstring fname;
3187 pstrcpy(fname,dname);
3189 if(!mask_match(fname, mask, case_sensitive))
3190 continue;
3192 error = NT_STATUS_ACCESS_DENIED;
3193 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3194 error = can_rename(fname,conn);
3195 if (!NT_STATUS_IS_OK(error)) {
3196 DEBUG(6,("rename %s refused\n", fname));
3197 continue;
3199 pstrcpy(destname,newname);
3201 if (!resolve_wildcards(fname,destname)) {
3202 DEBUG(6,("resolve_wildcards %s %s failed\n",
3203 fname, destname));
3204 continue;
3207 if (!replace_if_exists &&
3208 vfs_file_exist(conn,destname, NULL)) {
3209 DEBUG(6,("file_exist %s\n", destname));
3210 error = NT_STATUS_OBJECT_NAME_COLLISION;
3211 continue;
3214 if (!conn->vfs_ops.rename(conn,fname,destname))
3215 count++;
3216 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3218 CloseDir(dirptr);
3222 if (count == 0 && NT_STATUS_IS_OK(error)) {
3223 error = map_nt_error_from_unix(errno);
3226 return error;
3229 /****************************************************************************
3230 Reply to a mv.
3231 ****************************************************************************/
3233 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3234 int dum_buffsize)
3236 int outsize = 0;
3237 pstring name;
3238 pstring newname;
3239 char *p;
3240 NTSTATUS status;
3242 START_PROFILE(SMBmv);
3244 p = smb_buf(inbuf) + 1;
3245 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3246 p++;
3247 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3249 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3250 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3252 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3254 status = rename_internals(conn, name, newname, False);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 return ERROR_NT(status);
3260 * Win2k needs a changenotify request response before it will
3261 * update after a rename..
3263 process_pending_change_notify_queue((time_t)0);
3264 outsize = set_message(outbuf,0,0,True);
3266 END_PROFILE(SMBmv);
3267 return(outsize);
3270 /*******************************************************************
3271 Copy a file as part of a reply_copy.
3272 ******************************************************************/
3274 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3275 int count,BOOL target_is_directory, int *err_ret)
3277 int Access,action;
3278 SMB_STRUCT_STAT src_sbuf, sbuf2;
3279 SMB_OFF_T ret=-1;
3280 files_struct *fsp1,*fsp2;
3281 pstring dest;
3283 *err_ret = 0;
3285 pstrcpy(dest,dest1);
3286 if (target_is_directory) {
3287 char *p = strrchr_m(src,'/');
3288 if (p)
3289 p++;
3290 else
3291 p = src;
3292 pstrcat(dest,"/");
3293 pstrcat(dest,p);
3296 if (!vfs_file_exist(conn,src,&src_sbuf))
3297 return(False);
3299 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3300 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3302 if (!fsp1)
3303 return(False);
3305 if (!target_is_directory && count)
3306 ofun = FILE_EXISTS_OPEN;
3308 if (vfs_stat(conn,dest,&sbuf2) == -1)
3309 ZERO_STRUCTP(&sbuf2);
3311 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3312 ofun,src_sbuf.st_mode,0,&Access,&action);
3314 if (!fsp2) {
3315 close_file(fsp1,False);
3316 return(False);
3319 if ((ofun&3) == 1) {
3320 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3321 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3323 * Stop the copy from occurring.
3325 ret = -1;
3326 src_sbuf.st_size = 0;
3330 if (src_sbuf.st_size)
3331 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3333 close_file(fsp1,False);
3335 /* Ensure the modtime is set correctly on the destination file. */
3336 fsp2->pending_modtime = src_sbuf.st_mtime;
3339 * As we are opening fsp1 read-only we only expect
3340 * an error on close on fsp2 if we are out of space.
3341 * Thus we don't look at the error return from the
3342 * close of fsp1.
3344 *err_ret = close_file(fsp2,False);
3346 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3349 /****************************************************************************
3350 reply to a file copy.
3351 ****************************************************************************/
3352 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3354 int outsize = 0;
3355 pstring name;
3356 pstring directory;
3357 pstring mask,newname;
3358 char *p;
3359 int count=0;
3360 int error = ERRnoaccess;
3361 int err = 0;
3362 BOOL has_wild;
3363 BOOL exists=False;
3364 int tid2 = SVAL(inbuf,smb_vwv0);
3365 int ofun = SVAL(inbuf,smb_vwv1);
3366 int flags = SVAL(inbuf,smb_vwv2);
3367 BOOL target_is_directory=False;
3368 BOOL bad_path1 = False;
3369 BOOL bad_path2 = False;
3370 BOOL rc = True;
3371 SMB_STRUCT_STAT sbuf1, sbuf2;
3372 START_PROFILE(SMBcopy);
3374 *directory = *mask = 0;
3376 p = smb_buf(inbuf);
3377 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3378 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3380 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3382 if (tid2 != conn->cnum) {
3383 /* can't currently handle inter share copies XXXX */
3384 DEBUG(3,("Rejecting inter-share copy\n"));
3385 END_PROFILE(SMBcopy);
3386 return ERROR_DOS(ERRSRV,ERRinvdevice);
3389 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3390 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3392 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3393 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3395 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3397 if ((flags&1) && target_is_directory) {
3398 END_PROFILE(SMBcopy);
3399 return ERROR_DOS(ERRDOS,ERRbadfile);
3402 if ((flags&2) && !target_is_directory) {
3403 END_PROFILE(SMBcopy);
3404 return ERROR_DOS(ERRDOS,ERRbadpath);
3407 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3408 /* wants a tree copy! XXXX */
3409 DEBUG(3,("Rejecting tree copy\n"));
3410 END_PROFILE(SMBcopy);
3411 return ERROR_DOS(ERRSRV,ERRerror);
3414 p = strrchr_m(name,'/');
3415 if (!p) {
3416 pstrcpy(directory,"./");
3417 pstrcpy(mask,name);
3418 } else {
3419 *p = 0;
3420 pstrcpy(directory,name);
3421 pstrcpy(mask,p+1);
3425 * We should only check the mangled cache
3426 * here if unix_convert failed. This means
3427 * that the path in 'mask' doesn't exist
3428 * on the file system and so we need to look
3429 * for a possible mangle. This patch from
3430 * Tine Smukavec <valentin.smukavec@hermes.si>.
3433 #if 0
3434 if (!rc && is_mangled(mask))
3435 check_mangled_cache( mask );
3436 #endif
3437 if (!rc)
3439 char *unmangled;
3441 unmangled = dos_unmangle(mask);
3442 if (unmangled)
3443 strncpy(mask, unmangled, strlen(unmangled) + 1);
3445 SAFE_FREE(unmangled);
3449 has_wild = ms_has_wild(mask);
3451 if (!has_wild) {
3452 pstrcat(directory,"/");
3453 pstrcat(directory,mask);
3454 if (resolve_wildcards(directory,newname) &&
3455 copy_file(directory,newname,conn,ofun,
3456 count,target_is_directory,&err)) count++;
3457 if(!count && err) {
3458 errno = err;
3459 END_PROFILE(SMBcopy);
3460 return(UNIXERROR(ERRHRD,ERRgeneral));
3462 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3463 } else {
3464 void *dirptr = NULL;
3465 char *dname;
3466 pstring destname;
3468 if (check_name(directory,conn))
3469 dirptr = OpenDir(conn, directory, True);
3471 if (dirptr) {
3472 error = ERRbadfile;
3474 if (strequal(mask,"????????.???"))
3475 pstrcpy(mask,"*");
3477 while ((dname = ReadDirName(dirptr))) {
3478 pstring fname;
3479 pstrcpy(fname,dname);
3481 if(!mask_match(fname, mask, case_sensitive))
3482 continue;
3484 error = ERRnoaccess;
3485 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3486 pstrcpy(destname,newname);
3487 if (resolve_wildcards(fname,destname) &&
3488 copy_file(fname,destname,conn,ofun,
3489 count,target_is_directory,&err)) count++;
3490 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3492 CloseDir(dirptr);
3496 if (count == 0) {
3497 if(err) {
3498 /* Error on close... */
3499 errno = err;
3500 END_PROFILE(SMBcopy);
3501 return(UNIXERROR(ERRHRD,ERRgeneral));
3504 if (exists) {
3505 END_PROFILE(SMBcopy);
3506 return ERROR_DOS(ERRDOS,error);
3507 } else
3509 if((errno == ENOENT) && (bad_path1 || bad_path2))
3511 unix_ERR_class = ERRDOS;
3512 unix_ERR_code = ERRbadpath;
3514 END_PROFILE(SMBcopy);
3515 return(UNIXERROR(ERRDOS,error));
3519 outsize = set_message(outbuf,1,0,True);
3520 SSVAL(outbuf,smb_vwv0,count);
3522 END_PROFILE(SMBcopy);
3523 return(outsize);
3526 /****************************************************************************
3527 reply to a setdir
3528 ****************************************************************************/
3529 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3531 int snum;
3532 int outsize = 0;
3533 BOOL ok = False;
3534 pstring newdir;
3535 START_PROFILE(pathworks_setdir);
3537 snum = SNUM(conn);
3538 if (!CAN_SETDIR(snum)) {
3539 END_PROFILE(pathworks_setdir);
3540 return ERROR_DOS(ERRDOS,ERRnoaccess);
3543 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
3545 if (strlen(newdir) == 0) {
3546 ok = True;
3547 } else {
3548 ok = vfs_directory_exist(conn,newdir,NULL);
3549 if (ok) {
3550 string_set(&conn->connectpath,newdir);
3554 if (!ok) {
3555 END_PROFILE(pathworks_setdir);
3556 return ERROR_DOS(ERRDOS,ERRbadpath);
3559 outsize = set_message(outbuf,0,0,True);
3560 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3562 DEBUG(3,("setdir %s\n", newdir));
3564 END_PROFILE(pathworks_setdir);
3565 return(outsize);
3568 /****************************************************************************
3569 Get a lock pid, dealing with large count requests.
3570 ****************************************************************************/
3572 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3574 if(!large_file_format)
3575 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3576 else
3577 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3580 /****************************************************************************
3581 Get a lock count, dealing with large count requests.
3582 ****************************************************************************/
3584 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3586 SMB_BIG_UINT count = 0;
3588 if(!large_file_format) {
3589 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3590 } else {
3592 #if defined(HAVE_LONGLONG)
3593 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3594 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3595 #else /* HAVE_LONGLONG */
3598 * NT4.x seems to be broken in that it sends large file (64 bit)
3599 * lockingX calls even if the CAP_LARGE_FILES was *not*
3600 * negotiated. For boxes without large unsigned ints truncate the
3601 * lock count by dropping the top 32 bits.
3604 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3605 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3606 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3607 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3608 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3611 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3612 #endif /* HAVE_LONGLONG */
3615 return count;
3618 #if !defined(HAVE_LONGLONG)
3619 /****************************************************************************
3620 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3621 ****************************************************************************/
3622 static uint32 map_lock_offset(uint32 high, uint32 low)
3624 unsigned int i;
3625 uint32 mask = 0;
3626 uint32 highcopy = high;
3629 * Try and find out how many significant bits there are in high.
3632 for(i = 0; highcopy; i++)
3633 highcopy >>= 1;
3636 * We use 31 bits not 32 here as POSIX
3637 * lock offsets may not be negative.
3640 mask = (~0) << (31 - i);
3642 if(low & mask)
3643 return 0; /* Fail. */
3645 high <<= (31 - i);
3647 return (high|low);
3649 #endif /* !defined(HAVE_LONGLONG) */
3651 /****************************************************************************
3652 Get a lock offset, dealing with large offset requests.
3653 ****************************************************************************/
3655 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3657 SMB_BIG_UINT offset = 0;
3659 *err = False;
3661 if(!large_file_format) {
3662 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3663 } else {
3665 #if defined(HAVE_LONGLONG)
3666 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3667 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3668 #else /* HAVE_LONGLONG */
3671 * NT4.x seems to be broken in that it sends large file (64 bit)
3672 * lockingX calls even if the CAP_LARGE_FILES was *not*
3673 * negotiated. For boxes without large unsigned ints mangle the
3674 * lock offset by mapping the top 32 bits onto the lower 32.
3677 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3678 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3679 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3680 uint32 new_low = 0;
3682 if((new_low = map_lock_offset(high, low)) == 0) {
3683 *err = True;
3684 return (SMB_BIG_UINT)-1;
3687 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3688 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3689 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3690 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3693 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3694 #endif /* HAVE_LONGLONG */
3697 return offset;
3700 /****************************************************************************
3701 reply to a lockingX request
3702 ****************************************************************************/
3704 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3706 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3707 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3708 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3709 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3710 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3711 SMB_BIG_UINT count = 0, offset = 0;
3712 uint16 lock_pid;
3713 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3714 int i;
3715 char *data;
3716 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3717 BOOL err;
3718 NTSTATUS status;
3720 START_PROFILE(SMBlockingX);
3722 CHECK_FSP(fsp,conn);
3724 data = smb_buf(inbuf);
3726 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3727 /* we don't support these - and CANCEL_LOCK makes w2k
3728 and XP reboot so I don't really want to be
3729 compatible! (tridge) */
3730 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3733 /* Check if this is an oplock break on a file
3734 we have granted an oplock on.
3736 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3737 /* Client can insist on breaking to none. */
3738 BOOL break_to_none = (oplocklevel == 0);
3740 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3741 (unsigned int)oplocklevel, fsp->fnum ));
3744 * Make sure we have granted an exclusive or batch oplock on this file.
3747 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3748 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3749 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3751 /* if this is a pure oplock break request then don't send a reply */
3752 if (num_locks == 0 && num_ulocks == 0) {
3753 END_PROFILE(SMBlockingX);
3754 return -1;
3755 } else {
3756 END_PROFILE(SMBlockingX);
3757 return ERROR_DOS(ERRDOS,ERRlock);
3761 if (remove_oplock(fsp, break_to_none) == False) {
3762 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3763 fsp->fsp_name ));
3766 /* if this is a pure oplock break request then don't send a reply */
3767 if (num_locks == 0 && num_ulocks == 0) {
3768 /* Sanity check - ensure a pure oplock break is not a
3769 chained request. */
3770 if(CVAL(inbuf,smb_vwv0) != 0xff)
3771 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3772 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3773 END_PROFILE(SMBlockingX);
3774 return -1;
3779 * We do this check *after* we have checked this is not a oplock break
3780 * response message. JRA.
3783 release_level_2_oplocks_on_change(fsp);
3785 /* Data now points at the beginning of the list
3786 of smb_unlkrng structs */
3787 for(i = 0; i < (int)num_ulocks; i++) {
3788 lock_pid = get_lock_pid( data, i, large_file_format);
3789 count = get_lock_count( data, i, large_file_format);
3790 offset = get_lock_offset( data, i, large_file_format, &err);
3793 * There is no error code marked "stupid client bug".... :-).
3795 if(err) {
3796 END_PROFILE(SMBlockingX);
3797 return ERROR_DOS(ERRDOS,ERRnoaccess);
3800 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3801 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3803 status = do_unlock(fsp,conn,lock_pid,count,offset);
3804 if (NT_STATUS_V(status)) {
3805 END_PROFILE(SMBlockingX);
3806 return ERROR_NT(status);
3810 /* Setup the timeout in seconds. */
3811 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3813 /* Now do any requested locks */
3814 data += ((large_file_format ? 20 : 10)*num_ulocks);
3816 /* Data now points at the beginning of the list
3817 of smb_lkrng structs */
3819 for(i = 0; i < (int)num_locks; i++) {
3820 lock_pid = get_lock_pid( data, i, large_file_format);
3821 count = get_lock_count( data, i, large_file_format);
3822 offset = get_lock_offset( data, i, large_file_format, &err);
3825 * There is no error code marked "stupid client bug".... :-).
3827 if(err) {
3828 END_PROFILE(SMBlockingX);
3829 return ERROR_DOS(ERRDOS,ERRnoaccess);
3832 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
3833 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3835 status = do_lock(fsp,conn,lock_pid, count,offset,
3836 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3837 if (NT_STATUS_V(status)) {
3838 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3840 * A blocking lock was requested. Package up
3841 * this smb into a queued request and push it
3842 * onto the blocking lock queue.
3844 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3845 END_PROFILE(SMBlockingX);
3846 return -1;
3849 break;
3853 /* If any of the above locks failed, then we must unlock
3854 all of the previous locks (X/Open spec). */
3855 if (i != num_locks && num_locks != 0) {
3857 * Ensure we don't do a remove on the lock that just failed,
3858 * as under POSIX rules, if we have a lock already there, we
3859 * will delete it (and we shouldn't) .....
3861 for(i--; i >= 0; i--) {
3862 lock_pid = get_lock_pid( data, i, large_file_format);
3863 count = get_lock_count( data, i, large_file_format);
3864 offset = get_lock_offset( data, i, large_file_format, &err);
3867 * There is no error code marked "stupid client bug".... :-).
3869 if(err) {
3870 END_PROFILE(SMBlockingX);
3871 return ERROR_DOS(ERRDOS,ERRnoaccess);
3874 do_unlock(fsp,conn,lock_pid,count,offset);
3876 END_PROFILE(SMBlockingX);
3877 return ERROR_NT(status);
3880 set_message(outbuf,2,0,True);
3882 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3883 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3885 END_PROFILE(SMBlockingX);
3886 return chain_reply(inbuf,outbuf,length,bufsize);
3889 /****************************************************************************
3890 Reply to a SMBreadbmpx (read block multiplex) request.
3891 ****************************************************************************/
3893 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3895 ssize_t nread = -1;
3896 ssize_t total_read;
3897 char *data;
3898 SMB_OFF_T startpos;
3899 int outsize;
3900 size_t maxcount;
3901 int max_per_packet;
3902 size_t tcount;
3903 int pad;
3904 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3905 START_PROFILE(SMBreadBmpx);
3907 /* this function doesn't seem to work - disable by default */
3908 if (!lp_readbmpx()) {
3909 END_PROFILE(SMBreadBmpx);
3910 return ERROR_DOS(ERRSRV,ERRuseSTD);
3913 outsize = set_message(outbuf,8,0,True);
3915 CHECK_FSP(fsp,conn);
3916 CHECK_READ(fsp);
3918 startpos = IVAL(inbuf,smb_vwv1);
3919 maxcount = SVAL(inbuf,smb_vwv3);
3921 data = smb_buf(outbuf);
3922 pad = ((long)data)%4;
3923 if (pad)
3924 pad = 4 - pad;
3925 data += pad;
3927 max_per_packet = bufsize-(outsize+pad);
3928 tcount = maxcount;
3929 total_read = 0;
3931 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
3932 END_PROFILE(SMBreadBmpx);
3933 return ERROR_DOS(ERRDOS,ERRlock);
3936 do {
3937 size_t N = MIN(max_per_packet,tcount-total_read);
3939 nread = read_file(fsp,data,startpos,N);
3941 if (nread <= 0)
3942 nread = 0;
3944 if (nread < (ssize_t)N)
3945 tcount = total_read + nread;
3947 set_message(outbuf,8,nread,False);
3948 SIVAL(outbuf,smb_vwv0,startpos);
3949 SSVAL(outbuf,smb_vwv2,tcount);
3950 SSVAL(outbuf,smb_vwv6,nread);
3951 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3953 if (!send_smb(smbd_server_fd(),outbuf))
3954 exit_server("reply_readbmpx: send_smb failed.");
3956 total_read += nread;
3957 startpos += nread;
3958 } while (total_read < (ssize_t)tcount);
3960 END_PROFILE(SMBreadBmpx);
3961 return(-1);
3964 /****************************************************************************
3965 Reply to a SMBsetattrE.
3966 ****************************************************************************/
3968 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3970 struct utimbuf unix_times;
3971 int outsize = 0;
3972 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3973 START_PROFILE(SMBsetattrE);
3975 outsize = set_message(outbuf,0,0,True);
3977 CHECK_FSP(fsp,conn);
3979 /* Convert the DOS times into unix times. Ignore create
3980 time as UNIX can't set this.
3982 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3983 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3986 * Patch from Ray Frush <frush@engr.colostate.edu>
3987 * Sometimes times are sent as zero - ignore them.
3990 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3992 /* Ignore request */
3993 if( DEBUGLVL( 3 ) )
3995 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3996 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3998 END_PROFILE(SMBsetattrE);
3999 return(outsize);
4001 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4003 /* set modify time = to access time if modify time was 0 */
4004 unix_times.modtime = unix_times.actime;
4007 /* Set the date on this file */
4008 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4009 END_PROFILE(SMBsetattrE);
4010 return ERROR_DOS(ERRDOS,ERRnoaccess);
4013 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4014 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4016 END_PROFILE(SMBsetattrE);
4017 return(outsize);
4021 /* Back from the dead for OS/2..... JRA. */
4023 /****************************************************************************
4024 Reply to a SMBwritebmpx (write block multiplex primary) request.
4025 ****************************************************************************/
4027 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4029 size_t numtowrite;
4030 ssize_t nwritten = -1;
4031 int outsize = 0;
4032 SMB_OFF_T startpos;
4033 size_t tcount;
4034 BOOL write_through;
4035 int smb_doff;
4036 char *data;
4037 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4038 START_PROFILE(SMBwriteBmpx);
4040 CHECK_FSP(fsp,conn);
4041 CHECK_WRITE(fsp);
4042 CHECK_ERROR(fsp);
4044 tcount = SVAL(inbuf,smb_vwv1);
4045 startpos = IVAL(inbuf,smb_vwv3);
4046 write_through = BITSETW(inbuf+smb_vwv7,0);
4047 numtowrite = SVAL(inbuf,smb_vwv10);
4048 smb_doff = SVAL(inbuf,smb_vwv11);
4050 data = smb_base(inbuf) + smb_doff;
4052 /* If this fails we need to send an SMBwriteC response,
4053 not an SMBwritebmpx - set this up now so we don't forget */
4054 SCVAL(outbuf,smb_com,SMBwritec);
4056 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4057 END_PROFILE(SMBwriteBmpx);
4058 return(ERROR_DOS(ERRDOS,ERRlock));
4061 nwritten = write_file(fsp,data,startpos,numtowrite);
4063 if(lp_syncalways(SNUM(conn)) || write_through)
4064 sync_file(conn,fsp);
4066 if(nwritten < (ssize_t)numtowrite) {
4067 END_PROFILE(SMBwriteBmpx);
4068 return(UNIXERROR(ERRHRD,ERRdiskfull));
4071 /* If the maximum to be written to this file
4072 is greater than what we just wrote then set
4073 up a secondary struct to be attached to this
4074 fd, we will use this to cache error messages etc. */
4076 if((ssize_t)tcount > nwritten) {
4077 write_bmpx_struct *wbms;
4078 if(fsp->wbmpx_ptr != NULL)
4079 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4080 else
4081 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4082 if(!wbms) {
4083 DEBUG(0,("Out of memory in reply_readmpx\n"));
4084 END_PROFILE(SMBwriteBmpx);
4085 return(ERROR_DOS(ERRSRV,ERRnoresource));
4087 wbms->wr_mode = write_through;
4088 wbms->wr_discard = False; /* No errors yet */
4089 wbms->wr_total_written = nwritten;
4090 wbms->wr_errclass = 0;
4091 wbms->wr_error = 0;
4092 fsp->wbmpx_ptr = wbms;
4095 /* We are returning successfully, set the message type back to
4096 SMBwritebmpx */
4097 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4099 outsize = set_message(outbuf,1,0,True);
4101 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4103 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4104 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4106 if (write_through && tcount==nwritten) {
4107 /* We need to send both a primary and a secondary response */
4108 smb_setlen(outbuf,outsize - 4);
4109 if (!send_smb(smbd_server_fd(),outbuf))
4110 exit_server("reply_writebmpx: send_smb failed.");
4112 /* Now the secondary */
4113 outsize = set_message(outbuf,1,0,True);
4114 SCVAL(outbuf,smb_com,SMBwritec);
4115 SSVAL(outbuf,smb_vwv0,nwritten);
4118 END_PROFILE(SMBwriteBmpx);
4119 return(outsize);
4122 /****************************************************************************
4123 Reply to a SMBwritebs (write block multiplex secondary) request.
4124 ****************************************************************************/
4126 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4128 size_t numtowrite;
4129 ssize_t nwritten = -1;
4130 int outsize = 0;
4131 SMB_OFF_T startpos;
4132 size_t tcount;
4133 BOOL write_through;
4134 int smb_doff;
4135 char *data;
4136 write_bmpx_struct *wbms;
4137 BOOL send_response = False;
4138 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4139 START_PROFILE(SMBwriteBs);
4141 CHECK_FSP(fsp,conn);
4142 CHECK_WRITE(fsp);
4144 tcount = SVAL(inbuf,smb_vwv1);
4145 startpos = IVAL(inbuf,smb_vwv2);
4146 numtowrite = SVAL(inbuf,smb_vwv6);
4147 smb_doff = SVAL(inbuf,smb_vwv7);
4149 data = smb_base(inbuf) + smb_doff;
4151 /* We need to send an SMBwriteC response, not an SMBwritebs */
4152 SCVAL(outbuf,smb_com,SMBwritec);
4154 /* This fd should have an auxiliary struct attached,
4155 check that it does */
4156 wbms = fsp->wbmpx_ptr;
4157 if(!wbms) {
4158 END_PROFILE(SMBwriteBs);
4159 return(-1);
4162 /* If write through is set we can return errors, else we must cache them */
4163 write_through = wbms->wr_mode;
4165 /* Check for an earlier error */
4166 if(wbms->wr_discard) {
4167 END_PROFILE(SMBwriteBs);
4168 return -1; /* Just discard the packet */
4171 nwritten = write_file(fsp,data,startpos,numtowrite);
4173 if(lp_syncalways(SNUM(conn)) || write_through)
4174 sync_file(conn,fsp);
4176 if (nwritten < (ssize_t)numtowrite) {
4177 if(write_through) {
4178 /* We are returning an error - we can delete the aux struct */
4179 if (wbms)
4180 free((char *)wbms);
4181 fsp->wbmpx_ptr = NULL;
4182 END_PROFILE(SMBwriteBs);
4183 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4185 END_PROFILE(SMBwriteBs);
4186 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4189 /* Increment the total written, if this matches tcount
4190 we can discard the auxiliary struct (hurrah !) and return a writeC */
4191 wbms->wr_total_written += nwritten;
4192 if(wbms->wr_total_written >= tcount) {
4193 if (write_through) {
4194 outsize = set_message(outbuf,1,0,True);
4195 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4196 send_response = True;
4199 free((char *)wbms);
4200 fsp->wbmpx_ptr = NULL;
4203 if(send_response) {
4204 END_PROFILE(SMBwriteBs);
4205 return(outsize);
4208 END_PROFILE(SMBwriteBs);
4209 return(-1);
4212 /****************************************************************************
4213 Reply to a SMBgetattrE.
4214 ****************************************************************************/
4216 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4218 SMB_STRUCT_STAT sbuf;
4219 int outsize = 0;
4220 int mode;
4221 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4222 START_PROFILE(SMBgetattrE);
4224 outsize = set_message(outbuf,11,0,True);
4226 CHECK_FSP(fsp,conn);
4228 /* Do an fstat on this file */
4229 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4230 END_PROFILE(SMBgetattrE);
4231 return(UNIXERROR(ERRDOS,ERRnoaccess));
4234 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4236 /* Convert the times into dos times. Set create
4237 date to be last modify date as UNIX doesn't save
4238 this */
4239 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4240 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4241 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4242 if (mode & aDIR)
4244 SIVAL(outbuf,smb_vwv6,0);
4245 SIVAL(outbuf,smb_vwv8,0);
4247 else
4249 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4250 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4252 SSVAL(outbuf,smb_vwv10, mode);
4254 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4256 END_PROFILE(SMBgetattrE);
4257 return(outsize);