Fix const warnings.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob138870453d4c67543fd1247c36172a601c03b6b4
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
26 #include "includes.h"
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
47 int outsize = 4;
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
50 pstring name1,name2;
52 int len;
53 char name_type = 0;
55 static BOOL already_got_session = False;
57 *name1 = *name2 = 0;
59 memset(outbuf,'\0',smb_size);
61 smb_setlen(outbuf,0);
63 switch (msg_type) {
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
70 SCVAL(outbuf,0,0x82);
71 SCVAL(outbuf,3,0);
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
75 return(0);
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
80 name1,name2));
82 name1[15] = 0;
84 len = strlen(name2);
85 if (len == 16) {
86 name_type = name2[15];
87 name2[15] = 0;
90 set_local_machine_name(name1, True);
91 set_remote_machine_name(name2, True);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
98 no thanks! */
99 SCVAL(outbuf, 0,0x83);
100 break;
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
111 reopen_logs();
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
116 break;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
121 SCVAL(outbuf,3,0);
122 break;
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
128 break;
130 case SMBkeepalive: /* session keepalive */
131 default:
132 return(0);
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
138 return(outsize);
141 /****************************************************************************
142 Reply to a tcon.
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
148 const char *service;
149 pstring service_buf;
150 pstring password;
151 fstring dev;
152 int outsize = 0;
153 uint16 vuid = SVAL(inbuf,smb_uid);
154 int pwlen=0;
155 NTSTATUS nt_status;
156 char *p;
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
166 p += pwlen;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
170 if (p) {
171 service = p+1;
172 } else {
173 service = service_buf;
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 fstring 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_buf(inbuf, path, p, sizeof(path), 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 const 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|
289 (lp_csc_policy(SNUM(conn)) << 2));
291 init_dfsroot(conn, inbuf, outbuf);
295 DEBUG(3,("tconX service=%s \n",
296 service));
298 /* set the incoming and outgoing tid to the just created one */
299 SSVAL(inbuf,smb_tid,conn->cnum);
300 SSVAL(outbuf,smb_tid,conn->cnum);
302 END_PROFILE(SMBtconX);
303 return chain_reply(inbuf,outbuf,length,bufsize);
306 /****************************************************************************
307 Reply to an unknown type.
308 ****************************************************************************/
310 int reply_unknown(char *inbuf,char *outbuf)
312 int type;
313 type = CVAL(inbuf,smb_com);
315 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
316 smb_fn_name(type), type, type));
318 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
321 /****************************************************************************
322 Reply to an ioctl.
323 ****************************************************************************/
325 int reply_ioctl(connection_struct *conn,
326 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
328 uint16 device = SVAL(inbuf,smb_vwv1);
329 uint16 function = SVAL(inbuf,smb_vwv2);
330 uint32 ioctl_code = (device << 16) + function;
331 int replysize, outsize;
332 char *p;
333 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
334 START_PROFILE(SMBioctl);
336 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
338 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) {
354 case IOCTL_QUERY_JOB_INFO:
356 SSVAL(p,0,fsp->rap_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;
363 END_PROFILE(SMBioctl);
364 return outsize;
367 /****************************************************************************
368 Reply to a chkpth.
369 ****************************************************************************/
371 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
373 int outsize = 0;
374 int mode;
375 pstring name;
376 BOOL ok = False;
377 BOOL bad_path = False;
378 SMB_STRUCT_STAT sbuf;
379 START_PROFILE(SMBchkpth);
381 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
383 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
385 unix_convert(name,conn,0,&bad_path,&sbuf);
387 mode = SVAL(inbuf,smb_vwv0);
389 if (check_name(name,conn)) {
390 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
391 ok = S_ISDIR(sbuf.st_mode);
394 if (!ok) {
395 /* We special case this - as when a Windows machine
396 is parsing a path is steps through the components
397 one at a time - if a component fails it expects
398 ERRbadpath, not ERRbadfile.
400 if(errno == ENOENT)
401 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
403 return(UNIXERROR(ERRDOS,ERRbadpath));
406 outsize = set_message(outbuf,0,0,True);
408 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
410 END_PROFILE(SMBchkpth);
411 return(outsize);
414 /****************************************************************************
415 Reply to a getatr.
416 ****************************************************************************/
418 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
420 pstring fname;
421 int outsize = 0;
422 SMB_STRUCT_STAT sbuf;
423 BOOL ok = False;
424 int mode=0;
425 SMB_OFF_T size=0;
426 time_t mtime=0;
427 BOOL bad_path = False;
428 char *p;
429 START_PROFILE(SMBgetatr);
431 p = smb_buf(inbuf) + 1;
432 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
434 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
436 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
437 under WfWg - weird! */
438 if (! (*fname)) {
439 mode = aHIDDEN | aDIR;
440 if (!CAN_WRITE(conn))
441 mode |= aRONLY;
442 size = 0;
443 mtime = 0;
444 ok = True;
445 } else {
446 unix_convert(fname,conn,0,&bad_path,&sbuf);
447 if (check_name(fname,conn)) {
448 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) {
449 mode = dos_mode(conn,fname,&sbuf);
450 size = sbuf.st_size;
451 mtime = sbuf.st_mtime;
452 if (mode & aDIR)
453 size = 0;
454 ok = True;
455 } else {
456 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
461 if (!ok) {
462 set_bad_path_error(errno, bad_path);
463 END_PROFILE(SMBgetatr);
464 return(UNIXERROR(ERRDOS,ERRbadfile));
467 outsize = set_message(outbuf,10,0,True);
469 SSVAL(outbuf,smb_vwv0,mode);
470 if(lp_dos_filetime_resolution(SNUM(conn)) )
471 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
472 else
473 put_dos_date3(outbuf,smb_vwv1,mtime);
474 SIVAL(outbuf,smb_vwv3,(uint32)size);
476 if (Protocol >= PROTOCOL_NT1)
477 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
479 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
481 END_PROFILE(SMBgetatr);
482 return(outsize);
485 /****************************************************************************
486 Reply to a setatr.
487 ****************************************************************************/
489 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
491 pstring fname;
492 int outsize = 0;
493 BOOL ok=False;
494 int mode;
495 time_t mtime;
496 SMB_STRUCT_STAT sbuf;
497 BOOL bad_path = False;
498 char *p;
500 START_PROFILE(SMBsetatr);
502 p = smb_buf(inbuf) + 1;
503 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
504 unix_convert(fname,conn,0,&bad_path,&sbuf);
506 mode = SVAL(inbuf,smb_vwv0);
507 mtime = make_unix_date3(inbuf+smb_vwv1);
509 if (VALID_STAT_OF_DIR(sbuf))
510 mode |= aDIR;
511 else
512 mode &= ~aDIR;
514 if (check_name(fname,conn))
515 ok = (file_chmod(conn,fname,mode,NULL) == 0);
516 if (ok)
517 ok = set_filetime(conn,fname,mtime);
519 if (!ok) {
520 set_bad_path_error(errno, bad_path);
521 END_PROFILE(SMBsetatr);
522 return(UNIXERROR(ERRDOS,ERRnoaccess));
525 outsize = set_message(outbuf,0,0,True);
527 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
529 END_PROFILE(SMBsetatr);
530 return(outsize);
533 /****************************************************************************
534 Reply to a dskattr.
535 ****************************************************************************/
537 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
539 int outsize = 0;
540 SMB_BIG_UINT dfree,dsize,bsize;
541 START_PROFILE(SMBdskattr);
543 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
545 outsize = set_message(outbuf,5,0,True);
547 if (Protocol <= PROTOCOL_LANMAN2) {
548 double total_space, free_space;
549 /* we need to scale this to a number that DOS6 can handle. We
550 use floating point so we can handle large drives on systems
551 that don't have 64 bit integers
553 we end up displaying a maximum of 2G to DOS systems
555 total_space = dsize * (double)bsize;
556 free_space = dfree * (double)bsize;
558 dsize = (total_space+63*512) / (64*512);
559 dfree = (free_space+63*512) / (64*512);
561 if (dsize > 0xFFFF) dsize = 0xFFFF;
562 if (dfree > 0xFFFF) dfree = 0xFFFF;
564 SSVAL(outbuf,smb_vwv0,dsize);
565 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
566 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
567 SSVAL(outbuf,smb_vwv3,dfree);
568 } else {
569 SSVAL(outbuf,smb_vwv0,dsize);
570 SSVAL(outbuf,smb_vwv1,bsize/512);
571 SSVAL(outbuf,smb_vwv2,512);
572 SSVAL(outbuf,smb_vwv3,dfree);
575 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
577 END_PROFILE(SMBdskattr);
578 return(outsize);
581 /****************************************************************************
582 Reply to a search.
583 Can be called from SMBsearch, SMBffirst or SMBfunique.
584 ****************************************************************************/
586 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
588 pstring mask;
589 pstring directory;
590 pstring fname;
591 SMB_OFF_T size;
592 int mode;
593 time_t date;
594 int dirtype;
595 int outsize = 0;
596 int numentries = 0;
597 BOOL finished = False;
598 int maxentries;
599 int i;
600 char *p;
601 BOOL ok = False;
602 int status_len;
603 pstring path;
604 char status[21];
605 int dptr_num= -1;
606 BOOL check_descend = False;
607 BOOL expect_close = False;
608 BOOL can_open = True;
609 BOOL bad_path = False;
610 START_PROFILE(SMBsearch);
612 *mask = *directory = *fname = 0;
614 /* If we were called as SMBffirst then we must expect close. */
615 if(CVAL(inbuf,smb_com) == SMBffirst)
616 expect_close = True;
618 outsize = set_message(outbuf,1,3,True);
619 maxentries = SVAL(inbuf,smb_vwv0);
620 dirtype = SVAL(inbuf,smb_vwv1);
621 p = smb_buf(inbuf) + 1;
622 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
623 p++;
624 status_len = SVAL(p, 0);
625 p += 2;
627 /* dirtype &= ~aDIR; */
629 if (status_len == 0) {
630 SMB_STRUCT_STAT sbuf;
631 pstring dir2;
633 pstrcpy(directory,path);
634 pstrcpy(dir2,path);
635 unix_convert(directory,conn,0,&bad_path,&sbuf);
636 unix_format(dir2);
638 if (!check_name(directory,conn))
639 can_open = False;
641 p = strrchr_m(dir2,'/');
642 if (p == NULL) {
643 pstrcpy(mask,dir2);
644 *dir2 = 0;
645 } else {
646 *p = 0;
647 pstrcpy(mask,p+1);
650 p = strrchr_m(directory,'/');
651 if (!p)
652 *directory = 0;
653 else
654 *p = 0;
656 if (strlen(directory) == 0)
657 pstrcpy(directory,".");
658 memset((char *)status,'\0',21);
659 SCVAL(status,0,(dirtype & 0x1F));
660 } else {
661 int status_dirtype;
663 memcpy(status,p,21);
664 status_dirtype = CVAL(status,0) & 0x1F;
665 if (status_dirtype != (dirtype & 0x1F))
666 dirtype = status_dirtype;
668 conn->dirptr = dptr_fetch(status+12,&dptr_num);
669 if (!conn->dirptr)
670 goto SearchEmpty;
671 string_set(&conn->dirpath,dptr_path(dptr_num));
672 pstrcpy(mask, dptr_wcard(dptr_num));
675 if (can_open) {
676 p = smb_buf(outbuf) + 3;
677 ok = True;
679 if (status_len == 0) {
680 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
681 if (dptr_num < 0) {
682 if(dptr_num == -2) {
683 set_bad_path_error(errno, bad_path);
684 END_PROFILE(SMBsearch);
685 return (UNIXERROR(ERRDOS,ERRnofids));
687 END_PROFILE(SMBsearch);
688 return ERROR_DOS(ERRDOS,ERRnofids);
690 dptr_set_wcard(dptr_num, strdup(mask));
691 dptr_set_attr(dptr_num, dirtype);
692 } else {
693 dirtype = dptr_attr(dptr_num);
696 DEBUG(4,("dptr_num is %d\n",dptr_num));
698 if (ok) {
699 if ((dirtype&0x1F) == aVOLID) {
700 memcpy(p,status,21);
701 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
702 dptr_fill(p+12,dptr_num);
703 if (dptr_zero(p+12) && (status_len==0))
704 numentries = 1;
705 else
706 numentries = 0;
707 p += DIR_STRUCT_SIZE;
708 } else {
709 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
710 conn->dirpath,lp_dontdescend(SNUM(conn))));
711 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
712 check_descend = True;
714 for (i=numentries;(i<maxentries) && !finished;i++) {
715 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
716 if (!finished) {
717 memcpy(p,status,21);
718 make_dir_struct(p,mask,fname,size,mode,date);
719 dptr_fill(p+12,dptr_num);
720 numentries++;
722 p += DIR_STRUCT_SIZE;
725 } /* if (ok ) */
729 SearchEmpty:
731 if (numentries == 0 || !ok) {
732 SCVAL(outbuf,smb_rcls,ERRDOS);
733 SSVAL(outbuf,smb_err,ERRnofiles);
734 dptr_close(&dptr_num);
737 /* If we were called as SMBffirst with smb_search_id == NULL
738 and no entries were found then return error and close dirptr
739 (X/Open spec) */
741 if(ok && expect_close && numentries == 0 && status_len == 0) {
742 SCVAL(outbuf,smb_rcls,ERRDOS);
743 SSVAL(outbuf,smb_err,ERRnofiles);
744 /* Also close the dptr - we know it's gone */
745 dptr_close(&dptr_num);
748 /* If we were called as SMBfunique, then we can close the dirptr now ! */
749 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
750 dptr_close(&dptr_num);
752 SSVAL(outbuf,smb_vwv0,numentries);
753 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
754 SCVAL(smb_buf(outbuf),0,5);
755 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
757 if (Protocol >= PROTOCOL_NT1)
758 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
760 outsize += DIR_STRUCT_SIZE*numentries;
761 smb_setlen(outbuf,outsize - 4);
763 if ((! *directory) && dptr_path(dptr_num))
764 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
766 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
767 smb_fn_name(CVAL(inbuf,smb_com)),
768 mask, directory, dirtype, numentries, maxentries ) );
770 END_PROFILE(SMBsearch);
771 return(outsize);
774 /****************************************************************************
775 Reply to a fclose (stop directory search).
776 ****************************************************************************/
778 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
780 int outsize = 0;
781 int status_len;
782 pstring path;
783 char status[21];
784 int dptr_num= -2;
785 char *p;
787 START_PROFILE(SMBfclose);
789 outsize = set_message(outbuf,1,0,True);
790 p = smb_buf(inbuf) + 1;
791 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
792 p++;
793 status_len = SVAL(p,0);
794 p += 2;
796 if (status_len == 0) {
797 END_PROFILE(SMBfclose);
798 return ERROR_DOS(ERRSRV,ERRsrverror);
801 memcpy(status,p,21);
803 if(dptr_fetch(status+12,&dptr_num)) {
804 /* Close the dptr - we know it's gone */
805 dptr_close(&dptr_num);
808 SSVAL(outbuf,smb_vwv0,0);
810 DEBUG(3,("search close\n"));
812 END_PROFILE(SMBfclose);
813 return(outsize);
816 /****************************************************************************
817 Reply to an open.
818 ****************************************************************************/
820 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
822 pstring fname;
823 int outsize = 0;
824 int fmode=0;
825 int share_mode;
826 SMB_OFF_T size = 0;
827 time_t mtime=0;
828 mode_t unixmode;
829 int rmode=0;
830 SMB_STRUCT_STAT sbuf;
831 BOOL bad_path = False;
832 files_struct *fsp;
833 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
834 START_PROFILE(SMBopen);
836 share_mode = SVAL(inbuf,smb_vwv0);
838 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
840 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
842 unix_convert(fname,conn,0,&bad_path,&sbuf);
844 unixmode = unix_mode(conn,aARCH,fname);
846 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
847 unixmode, oplock_request,&rmode,NULL);
849 if (!fsp) {
850 set_bad_path_error(errno, bad_path);
851 END_PROFILE(SMBopen);
852 return(UNIXERROR(ERRDOS,ERRnoaccess));
855 size = sbuf.st_size;
856 fmode = dos_mode(conn,fname,&sbuf);
857 mtime = sbuf.st_mtime;
859 if (fmode & aDIR) {
860 DEBUG(3,("attempt to open a directory %s\n",fname));
861 close_file(fsp,False);
862 END_PROFILE(SMBopen);
863 return ERROR_DOS(ERRDOS,ERRnoaccess);
866 outsize = set_message(outbuf,7,0,True);
867 SSVAL(outbuf,smb_vwv0,fsp->fnum);
868 SSVAL(outbuf,smb_vwv1,fmode);
869 if(lp_dos_filetime_resolution(SNUM(conn)) )
870 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
871 else
872 put_dos_date3(outbuf,smb_vwv2,mtime);
873 SIVAL(outbuf,smb_vwv4,(uint32)size);
874 SSVAL(outbuf,smb_vwv6,rmode);
876 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
877 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
879 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
880 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
881 END_PROFILE(SMBopen);
882 return(outsize);
885 /****************************************************************************
886 Reply to an open and X.
887 ****************************************************************************/
889 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
891 pstring fname;
892 int smb_mode = SVAL(inbuf,smb_vwv3);
893 int smb_attr = SVAL(inbuf,smb_vwv5);
894 /* Breakout the oplock request bits so we can set the
895 reply bits separately. */
896 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
897 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
898 BOOL oplock_request = ex_oplock_request | core_oplock_request;
899 #if 0
900 int open_flags = SVAL(inbuf,smb_vwv2);
901 int smb_sattr = SVAL(inbuf,smb_vwv4);
902 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
903 #endif
904 int smb_ofun = SVAL(inbuf,smb_vwv8);
905 mode_t unixmode;
906 SMB_OFF_T size=0;
907 int fmode=0,mtime=0,rmode=0;
908 SMB_STRUCT_STAT sbuf;
909 int smb_action = 0;
910 BOOL bad_path = False;
911 files_struct *fsp;
912 START_PROFILE(SMBopenX);
914 /* If it's an IPC, pass off the pipe handler. */
915 if (IS_IPC(conn)) {
916 if (lp_nt_pipe_support()) {
917 END_PROFILE(SMBopenX);
918 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
919 } else {
920 END_PROFILE(SMBopenX);
921 return ERROR_DOS(ERRSRV,ERRaccess);
925 /* XXXX we need to handle passed times, sattr and flags */
926 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
928 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
930 unix_convert(fname,conn,0,&bad_path,&sbuf);
932 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
934 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
935 oplock_request, &rmode,&smb_action);
937 if (!fsp) {
938 set_bad_path_error(errno, bad_path);
939 END_PROFILE(SMBopenX);
940 return(UNIXERROR(ERRDOS,ERRnoaccess));
943 size = sbuf.st_size;
944 fmode = dos_mode(conn,fname,&sbuf);
945 mtime = sbuf.st_mtime;
946 if (fmode & aDIR) {
947 close_file(fsp,False);
948 END_PROFILE(SMBopenX);
949 return ERROR_DOS(ERRDOS,ERRnoaccess);
952 /* If the caller set the extended oplock request bit
953 and we granted one (by whatever means) - set the
954 correct bit for extended oplock reply.
957 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
958 smb_action |= EXTENDED_OPLOCK_GRANTED;
960 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
961 smb_action |= EXTENDED_OPLOCK_GRANTED;
963 /* If the caller set the core oplock request bit
964 and we granted one (by whatever means) - set the
965 correct bit for core oplock reply.
968 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
969 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
971 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
972 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
974 set_message(outbuf,15,0,True);
975 SSVAL(outbuf,smb_vwv2,fsp->fnum);
976 SSVAL(outbuf,smb_vwv3,fmode);
977 if(lp_dos_filetime_resolution(SNUM(conn)) )
978 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
979 else
980 put_dos_date3(outbuf,smb_vwv4,mtime);
981 SIVAL(outbuf,smb_vwv6,(uint32)size);
982 SSVAL(outbuf,smb_vwv8,rmode);
983 SSVAL(outbuf,smb_vwv11,smb_action);
985 END_PROFILE(SMBopenX);
986 return chain_reply(inbuf,outbuf,length,bufsize);
989 /****************************************************************************
990 Reply to a SMBulogoffX.
991 ****************************************************************************/
993 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
995 uint16 vuid = SVAL(inbuf,smb_uid);
996 user_struct *vuser = get_valid_user_struct(vuid);
997 START_PROFILE(SMBulogoffX);
999 if(vuser == 0)
1000 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1002 /* in user level security we are supposed to close any files
1003 open by this user */
1004 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1005 file_close_user(vuid);
1007 invalidate_vuid(vuid);
1009 set_message(outbuf,2,0,True);
1011 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1013 END_PROFILE(SMBulogoffX);
1014 return chain_reply(inbuf,outbuf,length,bufsize);
1017 /****************************************************************************
1018 Reply to a mknew or a create.
1019 ****************************************************************************/
1021 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 pstring fname;
1024 int com;
1025 int outsize = 0;
1026 int createmode;
1027 mode_t unixmode;
1028 int ofun = 0;
1029 BOOL bad_path = False;
1030 files_struct *fsp;
1031 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1032 SMB_STRUCT_STAT sbuf;
1033 START_PROFILE(SMBcreate);
1035 com = SVAL(inbuf,smb_com);
1037 createmode = SVAL(inbuf,smb_vwv0);
1038 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1040 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1042 unix_convert(fname,conn,0,&bad_path,&sbuf);
1044 if (createmode & aVOLID)
1045 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1047 unixmode = unix_mode(conn,createmode,fname);
1049 if(com == SMBmknew) {
1050 /* We should fail if file exists. */
1051 ofun = FILE_CREATE_IF_NOT_EXIST;
1052 } else {
1053 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1054 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1057 /* Open file in dos compatibility share mode. */
1058 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1059 ofun, unixmode, oplock_request, NULL, NULL);
1061 if (!fsp) {
1062 set_bad_path_error(errno, bad_path);
1063 END_PROFILE(SMBcreate);
1064 return(UNIXERROR(ERRDOS,ERRnoaccess));
1067 outsize = set_message(outbuf,1,0,True);
1068 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1070 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1071 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1073 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1074 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1076 DEBUG( 2, ( "new file %s\n", fname ) );
1077 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1079 END_PROFILE(SMBcreate);
1080 return(outsize);
1083 /****************************************************************************
1084 Reply to a create temporary file.
1085 ****************************************************************************/
1087 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1089 pstring fname;
1090 int outsize = 0;
1091 int createmode;
1092 mode_t unixmode;
1093 BOOL bad_path = False;
1094 files_struct *fsp;
1095 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1096 int tmpfd;
1097 SMB_STRUCT_STAT sbuf;
1098 char *p, *s;
1100 START_PROFILE(SMBctemp);
1102 createmode = SVAL(inbuf,smb_vwv0);
1103 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1104 pstrcat(fname,"\\TMXXXXXX");
1106 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1108 unix_convert(fname,conn,0,&bad_path,&sbuf);
1110 unixmode = unix_mode(conn,createmode,fname);
1112 tmpfd = smb_mkstemp(fname);
1113 if (tmpfd == -1) {
1114 END_PROFILE(SMBctemp);
1115 return(UNIXERROR(ERRDOS,ERRnoaccess));
1118 vfs_stat(conn,fname,&sbuf);
1120 /* Open file in dos compatibility share mode. */
1121 /* We should fail if file does not exist. */
1122 fsp = open_file_shared(conn,fname,&sbuf,
1123 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1124 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1125 unixmode, oplock_request, NULL, NULL);
1127 /* close fd from smb_mkstemp() */
1128 close(tmpfd);
1130 if (!fsp) {
1131 set_bad_path_error(errno, bad_path);
1132 END_PROFILE(SMBctemp);
1133 return(UNIXERROR(ERRDOS,ERRnoaccess));
1136 outsize = set_message(outbuf,1,0,True);
1137 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1139 /* the returned filename is relative to the directory */
1140 s = strrchr_m(fname, '/');
1141 if (!s)
1142 s = fname;
1143 else
1144 s++;
1146 p = smb_buf(outbuf);
1147 SSVALS(p, 0, -1); /* what is this? not in spec */
1148 SSVAL(p, 2, strlen(s));
1149 p += 4;
1150 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1151 outsize = set_message_end(outbuf, p);
1153 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1154 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1156 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1157 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1159 DEBUG( 2, ( "created temp file %s\n", fname ) );
1160 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1161 fname, fsp->fd, createmode, (int)unixmode ) );
1163 END_PROFILE(SMBctemp);
1164 return(outsize);
1167 /*******************************************************************
1168 Check if a user is allowed to rename a file.
1169 ********************************************************************/
1171 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1173 int smb_action;
1174 int access_mode;
1175 files_struct *fsp;
1177 if (!CAN_WRITE(conn))
1178 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1180 if (S_ISDIR(pst->st_mode))
1181 return NT_STATUS_OK;
1183 /* We need a better way to return NT status codes from open... */
1184 unix_ERR_class = 0;
1185 unix_ERR_code = 0;
1187 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1188 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1190 if (!fsp) {
1191 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1192 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1193 ret = NT_STATUS_SHARING_VIOLATION;
1194 unix_ERR_class = 0;
1195 unix_ERR_code = 0;
1196 return ret;
1198 close_file(fsp,False);
1199 return NT_STATUS_OK;
1202 /*******************************************************************
1203 Check if a user is allowed to delete a file.
1204 ********************************************************************/
1206 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1208 SMB_STRUCT_STAT sbuf;
1209 int fmode;
1210 int smb_action;
1211 int access_mode;
1212 files_struct *fsp;
1214 if (!CAN_WRITE(conn))
1215 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1217 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1218 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1220 fmode = dos_mode(conn,fname,&sbuf);
1221 if (fmode & aDIR)
1222 return NT_STATUS_FILE_IS_A_DIRECTORY;
1223 if (!lp_delete_readonly(SNUM(conn))) {
1224 if (fmode & aRONLY)
1225 return NT_STATUS_CANNOT_DELETE;
1227 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1228 return NT_STATUS_CANNOT_DELETE;
1230 /* We need a better way to return NT status codes from open... */
1231 unix_ERR_class = 0;
1232 unix_ERR_code = 0;
1234 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1235 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1237 if (!fsp) {
1238 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1239 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1240 ret = unix_ERR_ntstatus;
1241 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1242 ret = NT_STATUS_SHARING_VIOLATION;
1243 unix_ERR_class = 0;
1244 unix_ERR_code = 0;
1245 unix_ERR_ntstatus = NT_STATUS_OK;
1246 return ret;
1248 close_file(fsp,False);
1249 return NT_STATUS_OK;
1252 /****************************************************************************
1253 The guts of the unlink command, split out so it may be called by the NT SMB
1254 code.
1255 ****************************************************************************/
1257 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1259 pstring directory;
1260 pstring mask;
1261 char *p;
1262 int count=0;
1263 NTSTATUS error = NT_STATUS_OK;
1264 BOOL has_wild;
1265 BOOL bad_path = False;
1266 BOOL rc = True;
1267 SMB_STRUCT_STAT sbuf;
1269 *directory = *mask = 0;
1271 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1273 p = strrchr_m(name,'/');
1274 if (!p) {
1275 pstrcpy(directory,".");
1276 pstrcpy(mask,name);
1277 } else {
1278 *p = 0;
1279 pstrcpy(directory,name);
1280 pstrcpy(mask,p+1);
1284 * We should only check the mangled cache
1285 * here if unix_convert failed. This means
1286 * that the path in 'mask' doesn't exist
1287 * on the file system and so we need to look
1288 * for a possible mangle. This patch from
1289 * Tine Smukavec <valentin.smukavec@hermes.si>.
1292 if (!rc && mangle_is_mangled(mask))
1293 mangle_check_cache( mask );
1295 has_wild = ms_has_wild(mask);
1297 if (!has_wild) {
1298 pstrcat(directory,"/");
1299 pstrcat(directory,mask);
1300 error = can_delete(directory,conn,dirtype);
1301 if (!NT_STATUS_IS_OK(error)) return error;
1303 if (vfs_unlink(conn,directory) == 0) {
1304 count++;
1306 } else {
1307 void *dirptr = NULL;
1308 const char *dname;
1310 if (check_name(directory,conn))
1311 dirptr = OpenDir(conn, directory, True);
1313 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1314 the pattern matches against the long name, otherwise the short name
1315 We don't implement this yet XXXX
1318 if (dirptr) {
1319 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1321 if (strequal(mask,"????????.???"))
1322 pstrcpy(mask,"*");
1324 while ((dname = ReadDirName(dirptr))) {
1325 pstring fname;
1326 pstrcpy(fname,dname);
1328 if(!mask_match(fname, mask, case_sensitive)) continue;
1330 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1331 error = can_delete(fname,conn,dirtype);
1332 if (!NT_STATUS_IS_OK(error)) continue;
1333 if (vfs_unlink(conn,fname) == 0) count++;
1334 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1336 CloseDir(dirptr);
1340 if (count == 0 && NT_STATUS_IS_OK(error)) {
1341 error = map_nt_error_from_unix(errno);
1344 return error;
1347 /****************************************************************************
1348 Reply to a unlink
1349 ****************************************************************************/
1351 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1352 int dum_buffsize)
1354 int outsize = 0;
1355 pstring name;
1356 int dirtype;
1357 NTSTATUS status;
1358 START_PROFILE(SMBunlink);
1360 dirtype = SVAL(inbuf,smb_vwv0);
1362 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1364 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1366 DEBUG(3,("reply_unlink : %s\n",name));
1368 status = unlink_internals(conn, dirtype, name);
1369 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1372 * Win2k needs a changenotify request response before it will
1373 * update after a rename..
1375 process_pending_change_notify_queue((time_t)0);
1377 outsize = set_message(outbuf,0,0,True);
1379 END_PROFILE(SMBunlink);
1380 return outsize;
1383 /****************************************************************************
1384 Fail for readbraw.
1385 ****************************************************************************/
1387 void fail_readraw(void)
1389 pstring errstr;
1390 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1391 strerror(errno) );
1392 exit_server(errstr);
1395 /****************************************************************************
1396 Use sendfile in readbraw.
1397 ****************************************************************************/
1399 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1400 ssize_t mincount, char *outbuf)
1402 ssize_t ret=0;
1404 #if defined(WITH_SENDFILE)
1406 * We can only use sendfile on a non-chained packet and on a file
1407 * that is exclusively oplocked. reply_readbraw has already checked the length.
1410 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1411 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1412 DATA_BLOB header;
1414 _smb_setlen(outbuf,nread);
1415 header.data = outbuf;
1416 header.length = 4;
1417 header.free = NULL;
1419 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1421 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1422 * return ENOSYS then pretend we just got a normal read.
1424 if (errno == ENOSYS)
1425 goto normal_read;
1427 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1428 fsp->fsp_name, strerror(errno) ));
1429 exit_server("send_file_readbraw sendfile failed");
1434 normal_read:
1435 #endif
1437 if (nread > 0) {
1438 ret = read_file(fsp,outbuf+4,startpos,nread);
1439 if (ret < mincount)
1440 ret = 0;
1443 _smb_setlen(outbuf,ret);
1444 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1445 fail_readraw();
1448 /****************************************************************************
1449 Reply to a readbraw (core+ protocol).
1450 ****************************************************************************/
1452 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1454 ssize_t maxcount,mincount;
1455 size_t nread = 0;
1456 SMB_OFF_T startpos;
1457 char *header = outbuf;
1458 files_struct *fsp;
1459 START_PROFILE(SMBreadbraw);
1462 * Special check if an oplock break has been issued
1463 * and the readraw request croses on the wire, we must
1464 * return a zero length response here.
1467 if(global_oplock_break) {
1468 _smb_setlen(header,0);
1469 if (write_data(smbd_server_fd(),header,4) != 4)
1470 fail_readraw();
1471 DEBUG(5,("readbraw - oplock break finished\n"));
1472 END_PROFILE(SMBreadbraw);
1473 return -1;
1476 fsp = file_fsp(inbuf,smb_vwv0);
1478 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1480 * fsp could be NULL here so use the value from the packet. JRA.
1482 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1483 _smb_setlen(header,0);
1484 if (write_data(smbd_server_fd(),header,4) != 4)
1485 fail_readraw();
1486 END_PROFILE(SMBreadbraw);
1487 return(-1);
1490 CHECK_FSP(fsp,conn);
1492 flush_write_cache(fsp, READRAW_FLUSH);
1494 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1495 if(CVAL(inbuf,smb_wct) == 10) {
1497 * This is a large offset (64 bit) read.
1499 #ifdef LARGE_SMB_OFF_T
1501 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1503 #else /* !LARGE_SMB_OFF_T */
1506 * Ensure we haven't been sent a >32 bit offset.
1509 if(IVAL(inbuf,smb_vwv8) != 0) {
1510 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1511 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1512 _smb_setlen(header,0);
1513 if (write_data(smbd_server_fd(),header,4) != 4)
1514 fail_readraw();
1515 END_PROFILE(SMBreadbraw);
1516 return(-1);
1519 #endif /* LARGE_SMB_OFF_T */
1521 if(startpos < 0) {
1522 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1523 _smb_setlen(header,0);
1524 if (write_data(smbd_server_fd(),header,4) != 4)
1525 fail_readraw();
1526 END_PROFILE(SMBreadbraw);
1527 return(-1);
1530 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1531 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1533 /* ensure we don't overrun the packet size */
1534 maxcount = MIN(65535,maxcount);
1535 maxcount = MAX(mincount,maxcount);
1537 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1538 SMB_OFF_T size = fsp->size;
1539 SMB_OFF_T sizeneeded = startpos + maxcount;
1541 if (size < sizeneeded) {
1542 SMB_STRUCT_STAT st;
1543 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1544 size = st.st_size;
1545 if (!fsp->can_write)
1546 fsp->size = size;
1549 if (startpos >= size)
1550 nread = 0;
1551 else
1552 nread = MIN(maxcount,(size - startpos));
1555 if (nread < mincount)
1556 nread = 0;
1558 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1559 (int)maxcount, (int)mincount, (int)nread ) );
1561 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1563 DEBUG(5,("readbraw finished\n"));
1564 END_PROFILE(SMBreadbraw);
1565 return -1;
1568 /****************************************************************************
1569 Reply to a lockread (core+ protocol).
1570 ****************************************************************************/
1572 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1574 ssize_t nread = -1;
1575 char *data;
1576 int outsize = 0;
1577 SMB_OFF_T startpos;
1578 size_t numtoread;
1579 NTSTATUS status;
1580 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1581 START_PROFILE(SMBlockread);
1583 CHECK_FSP(fsp,conn);
1584 CHECK_READ(fsp);
1586 release_level_2_oplocks_on_change(fsp);
1588 numtoread = SVAL(inbuf,smb_vwv1);
1589 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1591 outsize = set_message(outbuf,5,3,True);
1592 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1593 data = smb_buf(outbuf) + 3;
1596 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1597 * protocol request that predates the read/write lock concept.
1598 * Thus instead of asking for a read lock here we need to ask
1599 * for a write lock. JRA.
1602 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1603 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1605 if (NT_STATUS_V(status)) {
1606 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1608 * A blocking lock was requested. Package up
1609 * this smb into a queued request and push it
1610 * onto the blocking lock queue.
1612 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1613 (SMB_BIG_UINT)numtoread)) {
1614 END_PROFILE(SMBlockread);
1615 return -1;
1618 END_PROFILE(SMBlockread);
1619 return ERROR_NT(status);
1622 nread = read_file(fsp,data,startpos,numtoread);
1624 if (nread < 0) {
1625 END_PROFILE(SMBlockread);
1626 return(UNIXERROR(ERRDOS,ERRnoaccess));
1629 outsize += nread;
1630 SSVAL(outbuf,smb_vwv0,nread);
1631 SSVAL(outbuf,smb_vwv5,nread+3);
1632 SSVAL(smb_buf(outbuf),1,nread);
1634 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1635 fsp->fnum, (int)numtoread, (int)nread));
1637 END_PROFILE(SMBlockread);
1638 return(outsize);
1641 /****************************************************************************
1642 Reply to a read.
1643 ****************************************************************************/
1645 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1647 size_t numtoread;
1648 ssize_t nread = 0;
1649 char *data;
1650 SMB_OFF_T startpos;
1651 int outsize = 0;
1652 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1653 START_PROFILE(SMBread);
1655 CHECK_FSP(fsp,conn);
1656 CHECK_READ(fsp);
1658 numtoread = SVAL(inbuf,smb_vwv1);
1659 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1661 outsize = set_message(outbuf,5,3,True);
1662 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1663 data = smb_buf(outbuf) + 3;
1665 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1666 END_PROFILE(SMBread);
1667 return ERROR_DOS(ERRDOS,ERRlock);
1670 if (numtoread > 0)
1671 nread = read_file(fsp,data,startpos,numtoread);
1673 if (nread < 0) {
1674 END_PROFILE(SMBread);
1675 return(UNIXERROR(ERRDOS,ERRnoaccess));
1678 outsize += nread;
1679 SSVAL(outbuf,smb_vwv0,nread);
1680 SSVAL(outbuf,smb_vwv5,nread+3);
1681 SCVAL(smb_buf(outbuf),0,1);
1682 SSVAL(smb_buf(outbuf),1,nread);
1684 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1685 fsp->fnum, (int)numtoread, (int)nread ) );
1687 END_PROFILE(SMBread);
1688 return(outsize);
1691 /****************************************************************************
1692 Reply to a read and X - possibly using sendfile.
1693 ****************************************************************************/
1695 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1696 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1698 ssize_t nread = -1;
1699 char *data = smb_buf(outbuf);
1701 #if defined(WITH_SENDFILE)
1703 * We can only use sendfile on a non-chained packet and on a file
1704 * that is exclusively oplocked.
1707 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1708 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1709 SMB_STRUCT_STAT sbuf;
1710 DATA_BLOB header;
1712 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1713 return(UNIXERROR(ERRDOS,ERRnoaccess));
1715 if (startpos > sbuf.st_size)
1716 goto normal_read;
1718 if (smb_maxcnt > (sbuf.st_size - startpos))
1719 smb_maxcnt = (sbuf.st_size - startpos);
1721 if (smb_maxcnt == 0)
1722 goto normal_read;
1725 * Set up the packet header before send. We
1726 * assume here the sendfile will work (get the
1727 * correct amount of data).
1730 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1731 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1732 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1733 SCVAL(outbuf,smb_vwv0,0xFF);
1734 set_message(outbuf,12,smb_maxcnt,False);
1735 header.data = outbuf;
1736 header.length = data - outbuf;
1737 header.free = NULL;
1739 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1741 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1742 * return ENOSYS then pretend we just got a normal read.
1744 if (errno == ENOSYS)
1745 goto normal_read;
1747 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1748 fsp->fsp_name, strerror(errno) ));
1749 exit_server("send_file_readX sendfile failed");
1752 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1753 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1754 return -1;
1757 normal_read:
1759 #endif
1761 nread = read_file(fsp,data,startpos,smb_maxcnt);
1763 if (nread < 0) {
1764 END_PROFILE(SMBreadX);
1765 return(UNIXERROR(ERRDOS,ERRnoaccess));
1768 SSVAL(outbuf,smb_vwv5,nread);
1769 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1770 SSVAL(smb_buf(outbuf),-2,nread);
1772 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1773 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1775 return nread;
1778 /****************************************************************************
1779 Reply to a read and X.
1780 ****************************************************************************/
1782 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1784 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1785 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1786 ssize_t nread = -1;
1787 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1788 #if 0
1789 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1790 #endif
1792 START_PROFILE(SMBreadX);
1794 /* If it's an IPC, pass off the pipe handler. */
1795 if (IS_IPC(conn)) {
1796 END_PROFILE(SMBreadX);
1797 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1800 CHECK_FSP(fsp,conn);
1801 CHECK_READ(fsp);
1803 set_message(outbuf,12,0,True);
1805 if(CVAL(inbuf,smb_wct) == 12) {
1806 #ifdef LARGE_SMB_OFF_T
1808 * This is a large offset (64 bit) read.
1810 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1812 #else /* !LARGE_SMB_OFF_T */
1815 * Ensure we haven't been sent a >32 bit offset.
1818 if(IVAL(inbuf,smb_vwv10) != 0) {
1819 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1820 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1821 END_PROFILE(SMBreadX);
1822 return ERROR_DOS(ERRDOS,ERRbadaccess);
1825 #endif /* LARGE_SMB_OFF_T */
1829 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1830 END_PROFILE(SMBreadX);
1831 return ERROR_DOS(ERRDOS,ERRlock);
1834 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1835 if (nread != -1)
1836 nread = chain_reply(inbuf,outbuf,length,bufsize);
1838 END_PROFILE(SMBreadX);
1839 return nread;
1842 /****************************************************************************
1843 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1844 ****************************************************************************/
1846 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1848 ssize_t nwritten=0;
1849 ssize_t total_written=0;
1850 size_t numtowrite=0;
1851 size_t tcount;
1852 SMB_OFF_T startpos;
1853 char *data=NULL;
1854 BOOL write_through;
1855 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1856 int outsize = 0;
1857 START_PROFILE(SMBwritebraw);
1859 CHECK_FSP(fsp,conn);
1860 CHECK_WRITE(fsp);
1862 tcount = IVAL(inbuf,smb_vwv1);
1863 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1864 write_through = BITSETW(inbuf+smb_vwv7,0);
1866 /* We have to deal with slightly different formats depending
1867 on whether we are using the core+ or lanman1.0 protocol */
1869 if(Protocol <= PROTOCOL_COREPLUS) {
1870 numtowrite = SVAL(smb_buf(inbuf),-2);
1871 data = smb_buf(inbuf);
1872 } else {
1873 numtowrite = SVAL(inbuf,smb_vwv10);
1874 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1877 /* force the error type */
1878 SCVAL(inbuf,smb_com,SMBwritec);
1879 SCVAL(outbuf,smb_com,SMBwritec);
1881 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1882 END_PROFILE(SMBwritebraw);
1883 return(ERROR_DOS(ERRDOS,ERRlock));
1886 if (numtowrite>0)
1887 nwritten = write_file(fsp,data,startpos,numtowrite);
1889 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1890 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1892 if (nwritten < (ssize_t)numtowrite) {
1893 END_PROFILE(SMBwritebraw);
1894 return(UNIXERROR(ERRHRD,ERRdiskfull));
1897 total_written = nwritten;
1899 /* Return a message to the redirector to tell it to send more bytes */
1900 SCVAL(outbuf,smb_com,SMBwritebraw);
1901 SSVALS(outbuf,smb_vwv0,-1);
1902 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1903 if (!send_smb(smbd_server_fd(),outbuf))
1904 exit_server("reply_writebraw: send_smb failed.");
1906 /* Now read the raw data into the buffer and write it */
1907 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1908 exit_server("secondary writebraw failed");
1911 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1912 numtowrite = smb_len(inbuf);
1914 /* Set up outbuf to return the correct return */
1915 outsize = set_message(outbuf,1,0,True);
1916 SCVAL(outbuf,smb_com,SMBwritec);
1917 SSVAL(outbuf,smb_vwv0,total_written);
1919 if (numtowrite != 0) {
1921 if (numtowrite > BUFFER_SIZE) {
1922 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1923 (unsigned int)numtowrite ));
1924 exit_server("secondary writebraw failed");
1927 if (tcount > nwritten+numtowrite) {
1928 DEBUG(3,("Client overestimated the write %d %d %d\n",
1929 (int)tcount,(int)nwritten,(int)numtowrite));
1932 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1933 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1934 strerror(errno) ));
1935 exit_server("secondary writebraw failed");
1938 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1940 if (nwritten < (ssize_t)numtowrite) {
1941 SCVAL(outbuf,smb_rcls,ERRHRD);
1942 SSVAL(outbuf,smb_err,ERRdiskfull);
1945 if (nwritten > 0)
1946 total_written += nwritten;
1949 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1950 sync_file(conn,fsp);
1952 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1953 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1955 /* we won't return a status if write through is not selected - this follows what WfWg does */
1956 END_PROFILE(SMBwritebraw);
1957 if (!write_through && total_written==tcount) {
1959 #if RABBIT_PELLET_FIX
1961 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1962 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1964 if (!send_keepalive(smbd_server_fd()))
1965 exit_server("reply_writebraw: send of keepalive failed");
1966 #endif
1967 return(-1);
1970 return(outsize);
1973 /****************************************************************************
1974 Reply to a writeunlock (core+).
1975 ****************************************************************************/
1977 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1978 int size, int dum_buffsize)
1980 ssize_t nwritten = -1;
1981 size_t numtowrite;
1982 SMB_OFF_T startpos;
1983 char *data;
1984 NTSTATUS status;
1985 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1986 int outsize = 0;
1987 START_PROFILE(SMBwriteunlock);
1989 CHECK_FSP(fsp,conn);
1990 CHECK_WRITE(fsp);
1992 numtowrite = SVAL(inbuf,smb_vwv1);
1993 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1994 data = smb_buf(inbuf) + 3;
1996 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1997 WRITE_LOCK,False)) {
1998 END_PROFILE(SMBwriteunlock);
1999 return ERROR_DOS(ERRDOS,ERRlock);
2002 /* The special X/Open SMB protocol handling of
2003 zero length writes is *NOT* done for
2004 this call */
2005 if(numtowrite == 0)
2006 nwritten = 0;
2007 else
2008 nwritten = write_file(fsp,data,startpos,numtowrite);
2010 if (lp_syncalways(SNUM(conn)))
2011 sync_file(conn,fsp);
2013 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2014 END_PROFILE(SMBwriteunlock);
2015 return(UNIXERROR(ERRHRD,ERRdiskfull));
2018 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2019 (SMB_BIG_UINT)startpos);
2020 if (NT_STATUS_V(status)) {
2021 END_PROFILE(SMBwriteunlock);
2022 return ERROR_NT(status);
2025 outsize = set_message(outbuf,1,0,True);
2027 SSVAL(outbuf,smb_vwv0,nwritten);
2029 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2030 fsp->fnum, (int)numtowrite, (int)nwritten));
2032 END_PROFILE(SMBwriteunlock);
2033 return outsize;
2036 /****************************************************************************
2037 Reply to a write.
2038 ****************************************************************************/
2040 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2042 size_t numtowrite;
2043 ssize_t nwritten = -1;
2044 SMB_OFF_T startpos;
2045 char *data;
2046 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2047 int outsize = 0;
2048 START_PROFILE(SMBwrite);
2050 /* If it's an IPC, pass off the pipe handler. */
2051 if (IS_IPC(conn)) {
2052 END_PROFILE(SMBwrite);
2053 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2056 CHECK_FSP(fsp,conn);
2057 CHECK_WRITE(fsp);
2059 numtowrite = SVAL(inbuf,smb_vwv1);
2060 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2061 data = smb_buf(inbuf) + 3;
2063 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2064 END_PROFILE(SMBwrite);
2065 return ERROR_DOS(ERRDOS,ERRlock);
2069 * X/Open SMB protocol says that if smb_vwv1 is
2070 * zero then the file size should be extended or
2071 * truncated to the size given in smb_vwv[2-3].
2074 if(numtowrite == 0) {
2076 * This is actually an allocate call, and set EOF. JRA.
2078 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2079 if (nwritten < 0) {
2080 END_PROFILE(SMBwrite);
2081 return ERROR_NT(NT_STATUS_DISK_FULL);
2083 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2084 if (nwritten < 0) {
2085 END_PROFILE(SMBwrite);
2086 return ERROR_NT(NT_STATUS_DISK_FULL);
2088 } else
2089 nwritten = write_file(fsp,data,startpos,numtowrite);
2091 if (lp_syncalways(SNUM(conn)))
2092 sync_file(conn,fsp);
2094 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2095 END_PROFILE(SMBwrite);
2096 return(UNIXERROR(ERRHRD,ERRdiskfull));
2099 outsize = set_message(outbuf,1,0,True);
2101 SSVAL(outbuf,smb_vwv0,nwritten);
2103 if (nwritten < (ssize_t)numtowrite) {
2104 SCVAL(outbuf,smb_rcls,ERRHRD);
2105 SSVAL(outbuf,smb_err,ERRdiskfull);
2108 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2110 END_PROFILE(SMBwrite);
2111 return(outsize);
2114 /****************************************************************************
2115 Reply to a write and X.
2116 ****************************************************************************/
2118 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2120 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2121 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2122 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2123 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2124 ssize_t nwritten = -1;
2125 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2126 unsigned int smblen = smb_len(inbuf);
2127 char *data;
2128 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2129 START_PROFILE(SMBwriteX);
2131 /* If it's an IPC, pass off the pipe handler. */
2132 if (IS_IPC(conn)) {
2133 END_PROFILE(SMBwriteX);
2134 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2137 CHECK_FSP(fsp,conn);
2138 CHECK_WRITE(fsp);
2140 /* Deal with possible LARGE_WRITEX */
2141 if (large_writeX)
2142 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2144 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2145 END_PROFILE(SMBwriteX);
2146 return ERROR_DOS(ERRDOS,ERRbadmem);
2149 data = smb_base(inbuf) + smb_doff;
2151 if(CVAL(inbuf,smb_wct) == 14) {
2152 #ifdef LARGE_SMB_OFF_T
2154 * This is a large offset (64 bit) write.
2156 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2158 #else /* !LARGE_SMB_OFF_T */
2161 * Ensure we haven't been sent a >32 bit offset.
2164 if(IVAL(inbuf,smb_vwv12) != 0) {
2165 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2166 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2167 END_PROFILE(SMBwriteX);
2168 return ERROR_DOS(ERRDOS,ERRbadaccess);
2171 #endif /* LARGE_SMB_OFF_T */
2174 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2175 END_PROFILE(SMBwriteX);
2176 return ERROR_DOS(ERRDOS,ERRlock);
2179 /* X/Open SMB protocol says that, unlike SMBwrite
2180 if the length is zero then NO truncation is
2181 done, just a write of zero. To truncate a file,
2182 use SMBwrite. */
2184 if(numtowrite == 0)
2185 nwritten = 0;
2186 else
2187 nwritten = write_file(fsp,data,startpos,numtowrite);
2189 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2190 END_PROFILE(SMBwriteX);
2191 return(UNIXERROR(ERRHRD,ERRdiskfull));
2194 set_message(outbuf,6,0,True);
2196 SSVAL(outbuf,smb_vwv2,nwritten);
2197 if (large_writeX)
2198 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2200 if (nwritten < (ssize_t)numtowrite) {
2201 SCVAL(outbuf,smb_rcls,ERRHRD);
2202 SSVAL(outbuf,smb_err,ERRdiskfull);
2205 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2206 fsp->fnum, (int)numtowrite, (int)nwritten));
2208 if (lp_syncalways(SNUM(conn)) || write_through)
2209 sync_file(conn,fsp);
2211 END_PROFILE(SMBwriteX);
2212 return chain_reply(inbuf,outbuf,length,bufsize);
2215 /****************************************************************************
2216 Reply to a lseek.
2217 ****************************************************************************/
2219 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2221 SMB_OFF_T startpos;
2222 SMB_OFF_T res= -1;
2223 int mode,umode;
2224 int outsize = 0;
2225 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2226 START_PROFILE(SMBlseek);
2228 CHECK_FSP(fsp,conn);
2230 flush_write_cache(fsp, SEEK_FLUSH);
2232 mode = SVAL(inbuf,smb_vwv1) & 3;
2233 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2234 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2236 switch (mode) {
2237 case 0:
2238 umode = SEEK_SET;
2239 break;
2240 case 1:
2241 umode = SEEK_CUR;
2242 break;
2243 case 2:
2244 umode = SEEK_END;
2245 break;
2246 default:
2247 umode = SEEK_SET;
2248 break;
2251 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2253 * Check for the special case where a seek before the start
2254 * of the file sets the offset to zero. Added in the CIFS spec,
2255 * section 4.2.7.
2258 if(errno == EINVAL) {
2259 SMB_OFF_T current_pos = startpos;
2261 if(umode == SEEK_CUR) {
2263 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2264 END_PROFILE(SMBlseek);
2265 return(UNIXERROR(ERRDOS,ERRnoaccess));
2268 current_pos += startpos;
2270 } else if (umode == SEEK_END) {
2272 SMB_STRUCT_STAT sbuf;
2274 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2275 END_PROFILE(SMBlseek);
2276 return(UNIXERROR(ERRDOS,ERRnoaccess));
2279 current_pos += sbuf.st_size;
2282 if(current_pos < 0)
2283 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2286 if(res == -1) {
2287 END_PROFILE(SMBlseek);
2288 return(UNIXERROR(ERRDOS,ERRnoaccess));
2292 fsp->pos = res;
2294 outsize = set_message(outbuf,2,0,True);
2295 SIVAL(outbuf,smb_vwv0,res);
2297 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2298 fsp->fnum, (double)startpos, (double)res, mode));
2300 END_PROFILE(SMBlseek);
2301 return(outsize);
2304 /****************************************************************************
2305 Reply to a flush.
2306 ****************************************************************************/
2308 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2310 int outsize = set_message(outbuf,0,0,True);
2311 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2312 START_PROFILE(SMBflush);
2314 CHECK_FSP(fsp,conn);
2316 if (!fsp) {
2317 file_sync_all(conn);
2318 } else {
2319 sync_file(conn,fsp);
2322 DEBUG(3,("flush\n"));
2323 END_PROFILE(SMBflush);
2324 return(outsize);
2327 /****************************************************************************
2328 Reply to a exit.
2329 ****************************************************************************/
2331 int reply_exit(connection_struct *conn,
2332 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2334 int outsize;
2335 START_PROFILE(SMBexit);
2336 outsize = set_message(outbuf,0,0,True);
2338 DEBUG(3,("exit\n"));
2340 END_PROFILE(SMBexit);
2341 return(outsize);
2344 /****************************************************************************
2345 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2346 ****************************************************************************/
2348 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2349 int dum_buffsize)
2351 int outsize = 0;
2352 time_t mtime;
2353 int32 eclass = 0, err = 0;
2354 files_struct *fsp = NULL;
2355 START_PROFILE(SMBclose);
2357 outsize = set_message(outbuf,0,0,True);
2359 /* If it's an IPC, pass off to the pipe handler. */
2360 if (IS_IPC(conn)) {
2361 END_PROFILE(SMBclose);
2362 return reply_pipe_close(conn, inbuf,outbuf);
2365 fsp = file_fsp(inbuf,smb_vwv0);
2368 * We can only use CHECK_FSP if we know it's not a directory.
2371 if(!fsp || (fsp->conn != conn)) {
2372 END_PROFILE(SMBclose);
2373 return ERROR_DOS(ERRDOS,ERRbadfid);
2376 if(fsp->is_directory) {
2378 * Special case - close NT SMB directory handle.
2380 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2381 close_file(fsp,True);
2382 } else {
2384 * Close ordinary file.
2386 int close_err;
2387 pstring file_name;
2389 /* Save the name for time set in close. */
2390 pstrcpy( file_name, fsp->fsp_name);
2392 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2393 fsp->fd, fsp->fnum,
2394 conn->num_files_open));
2397 * close_file() returns the unix errno if an error
2398 * was detected on close - normally this is due to
2399 * a disk full error. If not then it was probably an I/O error.
2402 if((close_err = close_file(fsp,True)) != 0) {
2403 errno = close_err;
2404 END_PROFILE(SMBclose);
2405 return (UNIXERROR(ERRHRD,ERRgeneral));
2409 * Now take care of any time sent in the close.
2412 mtime = make_unix_date3(inbuf+smb_vwv1);
2414 /* try and set the date */
2415 set_filetime(conn, file_name, mtime);
2419 /* We have a cached error */
2420 if(eclass || err) {
2421 END_PROFILE(SMBclose);
2422 return ERROR_DOS(eclass,err);
2425 END_PROFILE(SMBclose);
2426 return(outsize);
2429 /****************************************************************************
2430 Reply to a writeclose (Core+ protocol).
2431 ****************************************************************************/
2433 int reply_writeclose(connection_struct *conn,
2434 char *inbuf,char *outbuf, int size, int dum_buffsize)
2436 size_t numtowrite;
2437 ssize_t nwritten = -1;
2438 int outsize = 0;
2439 int close_err = 0;
2440 SMB_OFF_T startpos;
2441 char *data;
2442 time_t mtime;
2443 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2444 START_PROFILE(SMBwriteclose);
2446 CHECK_FSP(fsp,conn);
2447 CHECK_WRITE(fsp);
2449 numtowrite = SVAL(inbuf,smb_vwv1);
2450 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2451 mtime = make_unix_date3(inbuf+smb_vwv4);
2452 data = smb_buf(inbuf) + 1;
2454 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2455 END_PROFILE(SMBwriteclose);
2456 return ERROR_DOS(ERRDOS,ERRlock);
2459 nwritten = write_file(fsp,data,startpos,numtowrite);
2461 set_filetime(conn, fsp->fsp_name,mtime);
2463 close_err = close_file(fsp,True);
2465 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2466 fsp->fnum, (int)numtowrite, (int)nwritten,
2467 conn->num_files_open));
2469 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2470 END_PROFILE(SMBwriteclose);
2471 return(UNIXERROR(ERRHRD,ERRdiskfull));
2474 if(close_err != 0) {
2475 errno = close_err;
2476 END_PROFILE(SMBwriteclose);
2477 return(UNIXERROR(ERRHRD,ERRgeneral));
2480 outsize = set_message(outbuf,1,0,True);
2482 SSVAL(outbuf,smb_vwv0,nwritten);
2483 END_PROFILE(SMBwriteclose);
2484 return(outsize);
2487 /****************************************************************************
2488 Reply to a lock.
2489 ****************************************************************************/
2491 int reply_lock(connection_struct *conn,
2492 char *inbuf,char *outbuf, int length, int dum_buffsize)
2494 int outsize = set_message(outbuf,0,0,True);
2495 SMB_BIG_UINT count,offset;
2496 NTSTATUS status;
2497 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2498 START_PROFILE(SMBlock);
2500 CHECK_FSP(fsp,conn);
2502 release_level_2_oplocks_on_change(fsp);
2504 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2505 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2507 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2508 fsp->fd, fsp->fnum, (double)offset, (double)count));
2510 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2511 if (NT_STATUS_V(status)) {
2512 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2514 * A blocking lock was requested. Package up
2515 * this smb into a queued request and push it
2516 * onto the blocking lock queue.
2518 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2519 END_PROFILE(SMBlock);
2520 return -1;
2523 END_PROFILE(SMBlock);
2524 return ERROR_NT(status);
2527 END_PROFILE(SMBlock);
2528 return(outsize);
2531 /****************************************************************************
2532 Reply to a unlock.
2533 ****************************************************************************/
2535 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2536 int dum_buffsize)
2538 int outsize = set_message(outbuf,0,0,True);
2539 SMB_BIG_UINT count,offset;
2540 NTSTATUS status;
2541 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2542 START_PROFILE(SMBunlock);
2544 CHECK_FSP(fsp,conn);
2546 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2547 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2549 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2550 if (NT_STATUS_V(status)) {
2551 END_PROFILE(SMBunlock);
2552 return ERROR_NT(status);
2555 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2556 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2558 END_PROFILE(SMBunlock);
2559 return(outsize);
2562 /****************************************************************************
2563 Reply to a tdis.
2564 ****************************************************************************/
2566 int reply_tdis(connection_struct *conn,
2567 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2569 int outsize = set_message(outbuf,0,0,True);
2570 uint16 vuid;
2571 START_PROFILE(SMBtdis);
2573 vuid = SVAL(inbuf,smb_uid);
2575 if (!conn) {
2576 DEBUG(4,("Invalid connection in tdis\n"));
2577 END_PROFILE(SMBtdis);
2578 return ERROR_DOS(ERRSRV,ERRinvnid);
2581 conn->used = False;
2583 close_cnum(conn,vuid);
2585 END_PROFILE(SMBtdis);
2586 return outsize;
2589 /****************************************************************************
2590 Reply to a echo.
2591 ****************************************************************************/
2593 int reply_echo(connection_struct *conn,
2594 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2596 int smb_reverb = SVAL(inbuf,smb_vwv0);
2597 int seq_num;
2598 unsigned int data_len = smb_buflen(inbuf);
2599 int outsize = set_message(outbuf,1,data_len,True);
2600 START_PROFILE(SMBecho);
2602 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2604 /* copy any incoming data back out */
2605 if (data_len > 0)
2606 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2608 if (smb_reverb > 100) {
2609 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2610 smb_reverb = 100;
2613 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2614 SSVAL(outbuf,smb_vwv0,seq_num);
2616 smb_setlen(outbuf,outsize - 4);
2618 if (!send_smb(smbd_server_fd(),outbuf))
2619 exit_server("reply_echo: send_smb failed.");
2622 DEBUG(3,("echo %d times\n", smb_reverb));
2624 smb_echo_count++;
2626 END_PROFILE(SMBecho);
2627 return -1;
2630 /****************************************************************************
2631 Reply to a printopen.
2632 ****************************************************************************/
2634 int reply_printopen(connection_struct *conn,
2635 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2637 int outsize = 0;
2638 files_struct *fsp;
2639 START_PROFILE(SMBsplopen);
2641 if (!CAN_PRINT(conn)) {
2642 END_PROFILE(SMBsplopen);
2643 return ERROR_DOS(ERRDOS,ERRnoaccess);
2646 /* Open for exclusive use, write only. */
2647 fsp = print_fsp_open(conn, NULL);
2649 if (!fsp) {
2650 END_PROFILE(SMBsplopen);
2651 return(UNIXERROR(ERRDOS,ERRnoaccess));
2654 outsize = set_message(outbuf,1,0,True);
2655 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2657 DEBUG(3,("openprint fd=%d fnum=%d\n",
2658 fsp->fd, fsp->fnum));
2660 END_PROFILE(SMBsplopen);
2661 return(outsize);
2664 /****************************************************************************
2665 Reply to a printclose.
2666 ****************************************************************************/
2668 int reply_printclose(connection_struct *conn,
2669 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2671 int outsize = set_message(outbuf,0,0,True);
2672 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2673 int close_err = 0;
2674 START_PROFILE(SMBsplclose);
2676 CHECK_FSP(fsp,conn);
2678 if (!CAN_PRINT(conn)) {
2679 END_PROFILE(SMBsplclose);
2680 return ERROR_DOS(ERRDOS,ERRnoaccess);
2683 DEBUG(3,("printclose fd=%d fnum=%d\n",
2684 fsp->fd,fsp->fnum));
2686 close_err = close_file(fsp,True);
2688 if(close_err != 0) {
2689 errno = close_err;
2690 END_PROFILE(SMBsplclose);
2691 return(UNIXERROR(ERRHRD,ERRgeneral));
2694 END_PROFILE(SMBsplclose);
2695 return(outsize);
2698 /****************************************************************************
2699 Reply to a printqueue.
2700 ****************************************************************************/
2702 int reply_printqueue(connection_struct *conn,
2703 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2705 int outsize = set_message(outbuf,2,3,True);
2706 int max_count = SVAL(inbuf,smb_vwv0);
2707 int start_index = SVAL(inbuf,smb_vwv1);
2708 START_PROFILE(SMBsplretq);
2710 /* we used to allow the client to get the cnum wrong, but that
2711 is really quite gross and only worked when there was only
2712 one printer - I think we should now only accept it if they
2713 get it right (tridge) */
2714 if (!CAN_PRINT(conn)) {
2715 END_PROFILE(SMBsplretq);
2716 return ERROR_DOS(ERRDOS,ERRnoaccess);
2719 SSVAL(outbuf,smb_vwv0,0);
2720 SSVAL(outbuf,smb_vwv1,0);
2721 SCVAL(smb_buf(outbuf),0,1);
2722 SSVAL(smb_buf(outbuf),1,0);
2724 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2725 start_index, max_count));
2728 print_queue_struct *queue = NULL;
2729 print_status_struct status;
2730 char *p = smb_buf(outbuf) + 3;
2731 int count = print_queue_status(SNUM(conn), &queue, &status);
2732 int num_to_get = ABS(max_count);
2733 int first = (max_count>0?start_index:start_index+max_count+1);
2734 int i;
2736 if (first >= count)
2737 num_to_get = 0;
2738 else
2739 num_to_get = MIN(num_to_get,count-first);
2742 for (i=first;i<first+num_to_get;i++) {
2743 put_dos_date2(p,0,queue[i].time);
2744 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2745 SSVAL(p,5, queue[i].job);
2746 SIVAL(p,7,queue[i].size);
2747 SCVAL(p,11,0);
2748 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2749 p += 28;
2752 if (count > 0) {
2753 outsize = set_message(outbuf,2,28*count+3,False);
2754 SSVAL(outbuf,smb_vwv0,count);
2755 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2756 SCVAL(smb_buf(outbuf),0,1);
2757 SSVAL(smb_buf(outbuf),1,28*count);
2760 SAFE_FREE(queue);
2762 DEBUG(3,("%d entries returned in queue\n",count));
2765 END_PROFILE(SMBsplretq);
2766 return(outsize);
2769 /****************************************************************************
2770 Reply to a printwrite.
2771 ****************************************************************************/
2773 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2775 int numtowrite;
2776 int outsize = set_message(outbuf,0,0,True);
2777 char *data;
2778 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2780 START_PROFILE(SMBsplwr);
2782 if (!CAN_PRINT(conn)) {
2783 END_PROFILE(SMBsplwr);
2784 return ERROR_DOS(ERRDOS,ERRnoaccess);
2787 CHECK_FSP(fsp,conn);
2788 CHECK_WRITE(fsp);
2790 numtowrite = SVAL(smb_buf(inbuf),1);
2791 data = smb_buf(inbuf) + 3;
2793 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2794 END_PROFILE(SMBsplwr);
2795 return(UNIXERROR(ERRHRD,ERRdiskfull));
2798 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2800 END_PROFILE(SMBsplwr);
2801 return(outsize);
2804 /****************************************************************************
2805 The guts of the mkdir command, split out so it may be called by the NT SMB
2806 code.
2807 ****************************************************************************/
2809 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2811 BOOL bad_path = False;
2812 SMB_STRUCT_STAT sbuf;
2813 int ret= -1;
2815 unix_convert(directory,conn,0,&bad_path,&sbuf);
2817 if (check_name(directory, conn))
2818 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2820 if (ret == -1) {
2821 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2822 if (!NT_STATUS_IS_OK(nterr))
2823 return nterr;
2824 return map_nt_error_from_unix(errno);
2827 return NT_STATUS_OK;
2830 /****************************************************************************
2831 Reply to a mkdir.
2832 ****************************************************************************/
2834 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2836 pstring directory;
2837 int outsize;
2838 NTSTATUS status;
2839 START_PROFILE(SMBmkdir);
2841 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2843 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2845 status = mkdir_internal(conn, directory);
2846 if (!NT_STATUS_IS_OK(status))
2847 return ERROR_NT(status);
2849 outsize = set_message(outbuf,0,0,True);
2851 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2853 END_PROFILE(SMBmkdir);
2854 return(outsize);
2857 /****************************************************************************
2858 Static function used by reply_rmdir to delete an entire directory
2859 tree recursively. Return False on ok, True on fail.
2860 ****************************************************************************/
2862 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2864 const char *dname = NULL;
2865 BOOL ret = False;
2866 void *dirptr = OpenDir(conn, directory, False);
2868 if(dirptr == NULL)
2869 return True;
2871 while((dname = ReadDirName(dirptr))) {
2872 pstring fullname;
2873 SMB_STRUCT_STAT st;
2875 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2876 continue;
2878 /* Construct the full name. */
2879 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2880 errno = ENOMEM;
2881 ret = True;
2882 break;
2885 pstrcpy(fullname, directory);
2886 pstrcat(fullname, "/");
2887 pstrcat(fullname, dname);
2889 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2890 ret = True;
2891 break;
2894 if(st.st_mode & S_IFDIR) {
2895 if(recursive_rmdir(conn, fullname)!=0) {
2896 ret = True;
2897 break;
2899 if(vfs_rmdir(conn,fullname) != 0) {
2900 ret = True;
2901 break;
2903 } else if(vfs_unlink(conn,fullname) != 0) {
2904 ret = True;
2905 break;
2908 CloseDir(dirptr);
2909 return ret;
2912 /****************************************************************************
2913 The internals of the rmdir code - called elsewhere.
2914 ****************************************************************************/
2916 BOOL rmdir_internals(connection_struct *conn, char *directory)
2918 BOOL ok;
2920 ok = (vfs_rmdir(conn,directory) == 0);
2921 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2923 * Check to see if the only thing in this directory are
2924 * vetoed files/directories. If so then delete them and
2925 * retry. If we fail to delete any of them (and we *don't*
2926 * do a recursive delete) then fail the rmdir.
2928 BOOL all_veto_files = True;
2929 const char *dname;
2930 void *dirptr = OpenDir(conn, directory, False);
2932 if(dirptr != NULL) {
2933 int dirpos = TellDir(dirptr);
2934 while ((dname = ReadDirName(dirptr))) {
2935 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2936 continue;
2937 if(!IS_VETO_PATH(conn, dname)) {
2938 all_veto_files = False;
2939 break;
2943 if(all_veto_files) {
2944 SeekDir(dirptr,dirpos);
2945 while ((dname = ReadDirName(dirptr))) {
2946 pstring fullname;
2947 SMB_STRUCT_STAT st;
2949 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2950 continue;
2952 /* Construct the full name. */
2953 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2954 errno = ENOMEM;
2955 break;
2958 pstrcpy(fullname, directory);
2959 pstrcat(fullname, "/");
2960 pstrcat(fullname, dname);
2962 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2963 break;
2964 if(st.st_mode & S_IFDIR) {
2965 if(lp_recursive_veto_delete(SNUM(conn))) {
2966 if(recursive_rmdir(conn, fullname) != 0)
2967 break;
2969 if(vfs_rmdir(conn,fullname) != 0)
2970 break;
2971 } else if(vfs_unlink(conn,fullname) != 0)
2972 break;
2974 CloseDir(dirptr);
2975 /* Retry the rmdir */
2976 ok = (vfs_rmdir(conn,directory) == 0);
2977 } else {
2978 CloseDir(dirptr);
2980 } else {
2981 errno = ENOTEMPTY;
2985 if (!ok)
2986 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2988 return ok;
2991 /****************************************************************************
2992 Reply to a rmdir.
2993 ****************************************************************************/
2995 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2997 pstring directory;
2998 int outsize = 0;
2999 BOOL ok = False;
3000 BOOL bad_path = False;
3001 SMB_STRUCT_STAT sbuf;
3002 START_PROFILE(SMBrmdir);
3004 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3006 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3008 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3010 if (check_name(directory,conn)) {
3011 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3012 ok = rmdir_internals(conn, directory);
3015 if (!ok) {
3016 set_bad_path_error(errno, bad_path);
3017 END_PROFILE(SMBrmdir);
3018 return(UNIXERROR(ERRDOS,ERRbadpath));
3021 outsize = set_message(outbuf,0,0,True);
3023 DEBUG( 3, ( "rmdir %s\n", directory ) );
3025 END_PROFILE(SMBrmdir);
3026 return(outsize);
3029 /*******************************************************************
3030 Resolve wildcards in a filename rename.
3031 ********************************************************************/
3033 static BOOL resolve_wildcards(char *name1,char *name2)
3035 fstring root1,root2;
3036 fstring ext1,ext2;
3037 char *p,*p2;
3039 name1 = strrchr_m(name1,'/');
3040 name2 = strrchr_m(name2,'/');
3042 if (!name1 || !name2)
3043 return(False);
3045 fstrcpy(root1,name1);
3046 fstrcpy(root2,name2);
3047 p = strrchr_m(root1,'.');
3048 if (p) {
3049 *p = 0;
3050 fstrcpy(ext1,p+1);
3051 } else {
3052 fstrcpy(ext1,"");
3054 p = strrchr_m(root2,'.');
3055 if (p) {
3056 *p = 0;
3057 fstrcpy(ext2,p+1);
3058 } else {
3059 fstrcpy(ext2,"");
3062 p = root1;
3063 p2 = root2;
3064 while (*p2) {
3065 if (*p2 == '?') {
3066 *p2 = *p;
3067 p2++;
3068 } else {
3069 p2++;
3071 if (*p)
3072 p++;
3075 p = ext1;
3076 p2 = ext2;
3077 while (*p2) {
3078 if (*p2 == '?') {
3079 *p2 = *p;
3080 p2++;
3081 } else {
3082 p2++;
3084 if (*p)
3085 p++;
3088 pstrcpy(name2,root2);
3089 if (ext2[0]) {
3090 pstrcat(name2,".");
3091 pstrcat(name2,ext2);
3094 return(True);
3097 /****************************************************************************
3098 The guts of the rename command, split out so it may be called by the NT SMB
3099 code.
3100 ****************************************************************************/
3102 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3104 pstring directory;
3105 pstring mask;
3106 pstring newname_last_component;
3107 char *p;
3108 BOOL has_wild;
3109 BOOL bad_path1 = False;
3110 BOOL bad_path2 = False;
3111 int count=0;
3112 NTSTATUS error = NT_STATUS_OK;
3113 BOOL rc = True;
3114 SMB_STRUCT_STAT sbuf1, sbuf2;
3116 *directory = *mask = 0;
3118 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3119 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3122 * Split the old name into directory and last component
3123 * strings. Note that unix_convert may have stripped off a
3124 * leading ./ from both name and newname if the rename is
3125 * at the root of the share. We need to make sure either both
3126 * name and newname contain a / character or neither of them do
3127 * as this is checked in resolve_wildcards().
3130 p = strrchr_m(name,'/');
3131 if (!p) {
3132 pstrcpy(directory,".");
3133 pstrcpy(mask,name);
3134 } else {
3135 *p = 0;
3136 pstrcpy(directory,name);
3137 pstrcpy(mask,p+1);
3138 *p = '/'; /* Replace needed for exceptional test below. */
3142 * We should only check the mangled cache
3143 * here if unix_convert failed. This means
3144 * that the path in 'mask' doesn't exist
3145 * on the file system and so we need to look
3146 * for a possible mangle. This patch from
3147 * Tine Smukavec <valentin.smukavec@hermes.si>.
3150 if (!rc && mangle_is_mangled(mask))
3151 mangle_check_cache( mask );
3153 has_wild = ms_has_wild(mask);
3155 if (!has_wild) {
3157 * No wildcards - just process the one file.
3159 BOOL is_short_name = mangle_is_8_3(name, True);
3161 /* Add a terminating '/' to the directory name. */
3162 pstrcat(directory,"/");
3163 pstrcat(directory,mask);
3165 /* Ensure newname contains a '/' also */
3166 if(strrchr_m(newname,'/') == 0) {
3167 pstring tmpstr;
3169 pstrcpy(tmpstr, "./");
3170 pstrcat(tmpstr, newname);
3171 pstrcpy(newname, tmpstr);
3174 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3175 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3176 case_sensitive, case_preserve, short_case_preserve, directory,
3177 newname, newname_last_component, is_short_name));
3180 * Check for special case with case preserving and not
3181 * case sensitive, if directory and newname are identical,
3182 * and the old last component differs from the original
3183 * last component only by case, then we should allow
3184 * the rename (user is trying to change the case of the
3185 * filename).
3187 if((case_sensitive == False) &&
3188 (((case_preserve == True) &&
3189 (is_short_name == False)) ||
3190 ((short_case_preserve == True) &&
3191 (is_short_name == True))) &&
3192 strcsequal(directory, newname)) {
3193 pstring newname_modified_last_component;
3196 * Get the last component of the modified name.
3197 * Note that we guarantee that newname contains a '/'
3198 * character above.
3200 p = strrchr_m(newname,'/');
3201 pstrcpy(newname_modified_last_component,p+1);
3203 if(strcsequal(newname_modified_last_component,
3204 newname_last_component) == False) {
3206 * Replace the modified last component with
3207 * the original.
3209 pstrcpy(p+1, newname_last_component);
3213 resolve_wildcards(directory,newname);
3216 * The source object must exist.
3219 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3220 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3221 directory,newname));
3223 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3225 * Must return different errors depending on whether the parent
3226 * directory existed or not.
3229 p = strrchr_m(directory, '/');
3230 if (!p)
3231 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3232 *p = '\0';
3233 if (vfs_object_exist(conn, directory, NULL))
3234 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3235 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3237 error = map_nt_error_from_unix(errno);
3238 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3239 nt_errstr(error), directory,newname));
3241 return error;
3244 error = can_rename(directory,conn,&sbuf1);
3246 if (!NT_STATUS_IS_OK(error)) {
3247 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3248 nt_errstr(error), directory,newname));
3249 return error;
3253 * If the src and dest names are identical - including case,
3254 * don't do the rename, just return success.
3257 if (strcsequal(directory, newname)) {
3258 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3259 return NT_STATUS_OK;
3262 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3263 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3264 directory,newname));
3265 return NT_STATUS_OBJECT_NAME_COLLISION;
3268 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3269 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3270 directory,newname));
3271 return NT_STATUS_OK;
3274 if (errno == ENOTDIR || errno == EISDIR)
3275 error = NT_STATUS_OBJECT_NAME_COLLISION;
3276 else
3277 error = map_nt_error_from_unix(errno);
3279 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3280 nt_errstr(error), directory,newname));
3282 return error;
3283 } else {
3285 * Wildcards - process each file that matches.
3287 void *dirptr = NULL;
3288 const char *dname;
3289 pstring destname;
3291 if (check_name(directory,conn))
3292 dirptr = OpenDir(conn, directory, True);
3294 if (dirptr) {
3295 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3297 if (strequal(mask,"????????.???"))
3298 pstrcpy(mask,"*");
3300 while ((dname = ReadDirName(dirptr))) {
3301 pstring fname;
3303 pstrcpy(fname,dname);
3305 if(!mask_match(fname, mask, case_sensitive))
3306 continue;
3308 error = NT_STATUS_ACCESS_DENIED;
3309 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3310 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3311 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3312 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3313 continue;
3315 error = can_rename(fname,conn,&sbuf1);
3316 if (!NT_STATUS_IS_OK(error)) {
3317 DEBUG(6,("rename %s refused\n", fname));
3318 continue;
3320 pstrcpy(destname,newname);
3322 if (!resolve_wildcards(fname,destname)) {
3323 DEBUG(6,("resolve_wildcards %s %s failed\n",
3324 fname, destname));
3325 continue;
3328 if (!replace_if_exists &&
3329 vfs_file_exist(conn,destname, NULL)) {
3330 DEBUG(6,("file_exist %s\n", destname));
3331 error = NT_STATUS_OBJECT_NAME_COLLISION;
3332 continue;
3335 if (!conn->vfs_ops.rename(conn,fname,destname))
3336 count++;
3337 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3339 CloseDir(dirptr);
3343 if (count == 0 && NT_STATUS_IS_OK(error)) {
3344 error = map_nt_error_from_unix(errno);
3347 return error;
3350 /****************************************************************************
3351 Reply to a mv.
3352 ****************************************************************************/
3354 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3355 int dum_buffsize)
3357 int outsize = 0;
3358 pstring name;
3359 pstring newname;
3360 char *p;
3361 NTSTATUS status;
3363 START_PROFILE(SMBmv);
3365 p = smb_buf(inbuf) + 1;
3366 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3367 p++;
3368 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3370 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3371 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3373 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3375 status = rename_internals(conn, name, newname, False);
3376 if (!NT_STATUS_IS_OK(status)) {
3377 return ERROR_NT(status);
3381 * Win2k needs a changenotify request response before it will
3382 * update after a rename..
3384 process_pending_change_notify_queue((time_t)0);
3385 outsize = set_message(outbuf,0,0,True);
3387 END_PROFILE(SMBmv);
3388 return(outsize);
3391 /*******************************************************************
3392 Copy a file as part of a reply_copy.
3393 ******************************************************************/
3395 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3396 int count,BOOL target_is_directory, int *err_ret)
3398 int Access,action;
3399 SMB_STRUCT_STAT src_sbuf, sbuf2;
3400 SMB_OFF_T ret=-1;
3401 files_struct *fsp1,*fsp2;
3402 pstring dest;
3404 *err_ret = 0;
3406 pstrcpy(dest,dest1);
3407 if (target_is_directory) {
3408 char *p = strrchr_m(src,'/');
3409 if (p)
3410 p++;
3411 else
3412 p = src;
3413 pstrcat(dest,"/");
3414 pstrcat(dest,p);
3417 if (!vfs_file_exist(conn,src,&src_sbuf))
3418 return(False);
3420 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3421 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3423 if (!fsp1)
3424 return(False);
3426 if (!target_is_directory && count)
3427 ofun = FILE_EXISTS_OPEN;
3429 if (vfs_stat(conn,dest,&sbuf2) == -1)
3430 ZERO_STRUCTP(&sbuf2);
3432 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3433 ofun,src_sbuf.st_mode,0,&Access,&action);
3435 if (!fsp2) {
3436 close_file(fsp1,False);
3437 return(False);
3440 if ((ofun&3) == 1) {
3441 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3442 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3444 * Stop the copy from occurring.
3446 ret = -1;
3447 src_sbuf.st_size = 0;
3451 if (src_sbuf.st_size)
3452 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3454 close_file(fsp1,False);
3456 /* Ensure the modtime is set correctly on the destination file. */
3457 fsp2->pending_modtime = src_sbuf.st_mtime;
3460 * As we are opening fsp1 read-only we only expect
3461 * an error on close on fsp2 if we are out of space.
3462 * Thus we don't look at the error return from the
3463 * close of fsp1.
3465 *err_ret = close_file(fsp2,False);
3467 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3470 /****************************************************************************
3471 Reply to a file copy.
3472 ****************************************************************************/
3474 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3476 int outsize = 0;
3477 pstring name;
3478 pstring directory;
3479 pstring mask,newname;
3480 char *p;
3481 int count=0;
3482 int error = ERRnoaccess;
3483 int err = 0;
3484 BOOL has_wild;
3485 BOOL exists=False;
3486 int tid2 = SVAL(inbuf,smb_vwv0);
3487 int ofun = SVAL(inbuf,smb_vwv1);
3488 int flags = SVAL(inbuf,smb_vwv2);
3489 BOOL target_is_directory=False;
3490 BOOL bad_path1 = False;
3491 BOOL bad_path2 = False;
3492 BOOL rc = True;
3493 SMB_STRUCT_STAT sbuf1, sbuf2;
3495 START_PROFILE(SMBcopy);
3497 *directory = *mask = 0;
3499 p = smb_buf(inbuf);
3500 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3501 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3503 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3505 if (tid2 != conn->cnum) {
3506 /* can't currently handle inter share copies XXXX */
3507 DEBUG(3,("Rejecting inter-share copy\n"));
3508 END_PROFILE(SMBcopy);
3509 return ERROR_DOS(ERRSRV,ERRinvdevice);
3512 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3513 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3515 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3516 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3518 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3520 if ((flags&1) && target_is_directory) {
3521 END_PROFILE(SMBcopy);
3522 return ERROR_DOS(ERRDOS,ERRbadfile);
3525 if ((flags&2) && !target_is_directory) {
3526 END_PROFILE(SMBcopy);
3527 return ERROR_DOS(ERRDOS,ERRbadpath);
3530 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3531 /* wants a tree copy! XXXX */
3532 DEBUG(3,("Rejecting tree copy\n"));
3533 END_PROFILE(SMBcopy);
3534 return ERROR_DOS(ERRSRV,ERRerror);
3537 p = strrchr_m(name,'/');
3538 if (!p) {
3539 pstrcpy(directory,"./");
3540 pstrcpy(mask,name);
3541 } else {
3542 *p = 0;
3543 pstrcpy(directory,name);
3544 pstrcpy(mask,p+1);
3548 * We should only check the mangled cache
3549 * here if unix_convert failed. This means
3550 * that the path in 'mask' doesn't exist
3551 * on the file system and so we need to look
3552 * for a possible mangle. This patch from
3553 * Tine Smukavec <valentin.smukavec@hermes.si>.
3556 if (!rc && mangle_is_mangled(mask))
3557 mangle_check_cache( mask );
3559 has_wild = ms_has_wild(mask);
3561 if (!has_wild) {
3562 pstrcat(directory,"/");
3563 pstrcat(directory,mask);
3564 if (resolve_wildcards(directory,newname) &&
3565 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3566 count++;
3567 if(!count && err) {
3568 errno = err;
3569 END_PROFILE(SMBcopy);
3570 return(UNIXERROR(ERRHRD,ERRgeneral));
3572 if (!count) {
3573 exists = vfs_file_exist(conn,directory,NULL);
3575 } else {
3576 void *dirptr = NULL;
3577 const char *dname;
3578 pstring destname;
3580 if (check_name(directory,conn))
3581 dirptr = OpenDir(conn, directory, True);
3583 if (dirptr) {
3584 error = ERRbadfile;
3586 if (strequal(mask,"????????.???"))
3587 pstrcpy(mask,"*");
3589 while ((dname = ReadDirName(dirptr))) {
3590 pstring fname;
3591 pstrcpy(fname,dname);
3593 if(!mask_match(fname, mask, case_sensitive))
3594 continue;
3596 error = ERRnoaccess;
3597 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3598 pstrcpy(destname,newname);
3599 if (resolve_wildcards(fname,destname) &&
3600 copy_file(fname,destname,conn,ofun,
3601 count,target_is_directory,&err))
3602 count++;
3603 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3605 CloseDir(dirptr);
3609 if (count == 0) {
3610 if(err) {
3611 /* Error on close... */
3612 errno = err;
3613 END_PROFILE(SMBcopy);
3614 return(UNIXERROR(ERRHRD,ERRgeneral));
3617 if (exists) {
3618 END_PROFILE(SMBcopy);
3619 return ERROR_DOS(ERRDOS,error);
3620 } else {
3621 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3622 unix_ERR_class = ERRDOS;
3623 unix_ERR_code = ERRbadpath;
3625 END_PROFILE(SMBcopy);
3626 return(UNIXERROR(ERRDOS,error));
3630 outsize = set_message(outbuf,1,0,True);
3631 SSVAL(outbuf,smb_vwv0,count);
3633 END_PROFILE(SMBcopy);
3634 return(outsize);
3637 /****************************************************************************
3638 Reply to a setdir.
3639 ****************************************************************************/
3641 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3643 int snum;
3644 int outsize = 0;
3645 BOOL ok = False;
3646 pstring newdir;
3648 START_PROFILE(pathworks_setdir);
3650 snum = SNUM(conn);
3651 if (!CAN_SETDIR(snum)) {
3652 END_PROFILE(pathworks_setdir);
3653 return ERROR_DOS(ERRDOS,ERRnoaccess);
3656 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3658 if (strlen(newdir) == 0) {
3659 ok = True;
3660 } else {
3661 ok = vfs_directory_exist(conn,newdir,NULL);
3662 if (ok)
3663 string_set(&conn->connectpath,newdir);
3666 if (!ok) {
3667 END_PROFILE(pathworks_setdir);
3668 return ERROR_DOS(ERRDOS,ERRbadpath);
3671 outsize = set_message(outbuf,0,0,True);
3672 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3674 DEBUG(3,("setdir %s\n", newdir));
3676 END_PROFILE(pathworks_setdir);
3677 return(outsize);
3680 /****************************************************************************
3681 Get a lock pid, dealing with large count requests.
3682 ****************************************************************************/
3684 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3686 if(!large_file_format)
3687 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3688 else
3689 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3692 /****************************************************************************
3693 Get a lock count, dealing with large count requests.
3694 ****************************************************************************/
3696 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3698 SMB_BIG_UINT count = 0;
3700 if(!large_file_format) {
3701 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3702 } else {
3704 #if defined(HAVE_LONGLONG)
3705 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3706 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3707 #else /* HAVE_LONGLONG */
3710 * NT4.x seems to be broken in that it sends large file (64 bit)
3711 * lockingX calls even if the CAP_LARGE_FILES was *not*
3712 * negotiated. For boxes without large unsigned ints truncate the
3713 * lock count by dropping the top 32 bits.
3716 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3717 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3718 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3719 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3720 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3723 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3724 #endif /* HAVE_LONGLONG */
3727 return count;
3730 #if !defined(HAVE_LONGLONG)
3731 /****************************************************************************
3732 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3733 ****************************************************************************/
3735 static uint32 map_lock_offset(uint32 high, uint32 low)
3737 unsigned int i;
3738 uint32 mask = 0;
3739 uint32 highcopy = high;
3742 * Try and find out how many significant bits there are in high.
3745 for(i = 0; highcopy; i++)
3746 highcopy >>= 1;
3749 * We use 31 bits not 32 here as POSIX
3750 * lock offsets may not be negative.
3753 mask = (~0) << (31 - i);
3755 if(low & mask)
3756 return 0; /* Fail. */
3758 high <<= (31 - i);
3760 return (high|low);
3762 #endif /* !defined(HAVE_LONGLONG) */
3764 /****************************************************************************
3765 Get a lock offset, dealing with large offset requests.
3766 ****************************************************************************/
3768 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3770 SMB_BIG_UINT offset = 0;
3772 *err = False;
3774 if(!large_file_format) {
3775 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3776 } else {
3778 #if defined(HAVE_LONGLONG)
3779 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3780 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3781 #else /* HAVE_LONGLONG */
3784 * NT4.x seems to be broken in that it sends large file (64 bit)
3785 * lockingX calls even if the CAP_LARGE_FILES was *not*
3786 * negotiated. For boxes without large unsigned ints mangle the
3787 * lock offset by mapping the top 32 bits onto the lower 32.
3790 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3791 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3792 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3793 uint32 new_low = 0;
3795 if((new_low = map_lock_offset(high, low)) == 0) {
3796 *err = True;
3797 return (SMB_BIG_UINT)-1;
3800 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3801 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3802 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3803 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3806 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3807 #endif /* HAVE_LONGLONG */
3810 return offset;
3813 /****************************************************************************
3814 Reply to a lockingX request.
3815 ****************************************************************************/
3817 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3819 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3820 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3821 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3822 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3823 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3824 SMB_BIG_UINT count = 0, offset = 0;
3825 uint16 lock_pid;
3826 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3827 int i;
3828 char *data;
3829 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3830 BOOL err;
3831 NTSTATUS status;
3833 START_PROFILE(SMBlockingX);
3835 CHECK_FSP(fsp,conn);
3837 data = smb_buf(inbuf);
3839 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3840 /* we don't support these - and CANCEL_LOCK makes w2k
3841 and XP reboot so I don't really want to be
3842 compatible! (tridge) */
3843 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3846 /* Check if this is an oplock break on a file
3847 we have granted an oplock on.
3849 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3850 /* Client can insist on breaking to none. */
3851 BOOL break_to_none = (oplocklevel == 0);
3853 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3854 (unsigned int)oplocklevel, fsp->fnum ));
3857 * Make sure we have granted an exclusive or batch oplock on this file.
3860 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3861 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3862 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3864 /* if this is a pure oplock break request then don't send a reply */
3865 if (num_locks == 0 && num_ulocks == 0) {
3866 END_PROFILE(SMBlockingX);
3867 return -1;
3868 } else {
3869 END_PROFILE(SMBlockingX);
3870 return ERROR_DOS(ERRDOS,ERRlock);
3874 if (remove_oplock(fsp, break_to_none) == False) {
3875 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3876 fsp->fsp_name ));
3879 /* if this is a pure oplock break request then don't send a reply */
3880 if (num_locks == 0 && num_ulocks == 0) {
3881 /* Sanity check - ensure a pure oplock break is not a
3882 chained request. */
3883 if(CVAL(inbuf,smb_vwv0) != 0xff)
3884 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3885 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3886 END_PROFILE(SMBlockingX);
3887 return -1;
3892 * We do this check *after* we have checked this is not a oplock break
3893 * response message. JRA.
3896 release_level_2_oplocks_on_change(fsp);
3898 /* Data now points at the beginning of the list
3899 of smb_unlkrng structs */
3900 for(i = 0; i < (int)num_ulocks; i++) {
3901 lock_pid = get_lock_pid( data, i, large_file_format);
3902 count = get_lock_count( data, i, large_file_format);
3903 offset = get_lock_offset( data, i, large_file_format, &err);
3906 * There is no error code marked "stupid client bug".... :-).
3908 if(err) {
3909 END_PROFILE(SMBlockingX);
3910 return ERROR_DOS(ERRDOS,ERRnoaccess);
3913 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3914 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3916 status = do_unlock(fsp,conn,lock_pid,count,offset);
3917 if (NT_STATUS_V(status)) {
3918 END_PROFILE(SMBlockingX);
3919 return ERROR_NT(status);
3923 /* Setup the timeout in seconds. */
3925 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3927 /* Now do any requested locks */
3928 data += ((large_file_format ? 20 : 10)*num_ulocks);
3930 /* Data now points at the beginning of the list
3931 of smb_lkrng structs */
3933 for(i = 0; i < (int)num_locks; i++) {
3934 lock_pid = get_lock_pid( data, i, large_file_format);
3935 count = get_lock_count( data, i, large_file_format);
3936 offset = get_lock_offset( data, i, large_file_format, &err);
3939 * There is no error code marked "stupid client bug".... :-).
3941 if(err) {
3942 END_PROFILE(SMBlockingX);
3943 return ERROR_DOS(ERRDOS,ERRnoaccess);
3946 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3947 (double)offset, (double)count, (unsigned int)lock_pid,
3948 fsp->fsp_name, (int)lock_timeout ));
3950 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3951 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3952 if (NT_STATUS_V(status)) {
3953 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3955 * A blocking lock was requested. Package up
3956 * this smb into a queued request and push it
3957 * onto the blocking lock queue.
3959 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3960 END_PROFILE(SMBlockingX);
3961 return -1;
3964 break;
3968 /* If any of the above locks failed, then we must unlock
3969 all of the previous locks (X/Open spec). */
3970 if (i != num_locks && num_locks != 0) {
3972 * Ensure we don't do a remove on the lock that just failed,
3973 * as under POSIX rules, if we have a lock already there, we
3974 * will delete it (and we shouldn't) .....
3976 for(i--; i >= 0; i--) {
3977 lock_pid = get_lock_pid( data, i, large_file_format);
3978 count = get_lock_count( data, i, large_file_format);
3979 offset = get_lock_offset( data, i, large_file_format, &err);
3982 * There is no error code marked "stupid client bug".... :-).
3984 if(err) {
3985 END_PROFILE(SMBlockingX);
3986 return ERROR_DOS(ERRDOS,ERRnoaccess);
3989 do_unlock(fsp,conn,lock_pid,count,offset);
3991 END_PROFILE(SMBlockingX);
3992 return ERROR_NT(status);
3995 set_message(outbuf,2,0,True);
3997 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3998 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4000 END_PROFILE(SMBlockingX);
4001 return chain_reply(inbuf,outbuf,length,bufsize);
4004 /****************************************************************************
4005 Reply to a SMBreadbmpx (read block multiplex) request.
4006 ****************************************************************************/
4008 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4010 ssize_t nread = -1;
4011 ssize_t total_read;
4012 char *data;
4013 SMB_OFF_T startpos;
4014 int outsize;
4015 size_t maxcount;
4016 int max_per_packet;
4017 size_t tcount;
4018 int pad;
4019 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4020 START_PROFILE(SMBreadBmpx);
4022 /* this function doesn't seem to work - disable by default */
4023 if (!lp_readbmpx()) {
4024 END_PROFILE(SMBreadBmpx);
4025 return ERROR_DOS(ERRSRV,ERRuseSTD);
4028 outsize = set_message(outbuf,8,0,True);
4030 CHECK_FSP(fsp,conn);
4031 CHECK_READ(fsp);
4033 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4034 maxcount = SVAL(inbuf,smb_vwv3);
4036 data = smb_buf(outbuf);
4037 pad = ((long)data)%4;
4038 if (pad)
4039 pad = 4 - pad;
4040 data += pad;
4042 max_per_packet = bufsize-(outsize+pad);
4043 tcount = maxcount;
4044 total_read = 0;
4046 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4047 END_PROFILE(SMBreadBmpx);
4048 return ERROR_DOS(ERRDOS,ERRlock);
4051 do {
4052 size_t N = MIN(max_per_packet,tcount-total_read);
4054 nread = read_file(fsp,data,startpos,N);
4056 if (nread <= 0)
4057 nread = 0;
4059 if (nread < (ssize_t)N)
4060 tcount = total_read + nread;
4062 set_message(outbuf,8,nread,False);
4063 SIVAL(outbuf,smb_vwv0,startpos);
4064 SSVAL(outbuf,smb_vwv2,tcount);
4065 SSVAL(outbuf,smb_vwv6,nread);
4066 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4068 if (!send_smb(smbd_server_fd(),outbuf))
4069 exit_server("reply_readbmpx: send_smb failed.");
4071 total_read += nread;
4072 startpos += nread;
4073 } while (total_read < (ssize_t)tcount);
4075 END_PROFILE(SMBreadBmpx);
4076 return(-1);
4079 /****************************************************************************
4080 Reply to a SMBsetattrE.
4081 ****************************************************************************/
4083 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4085 struct utimbuf unix_times;
4086 int outsize = 0;
4087 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4088 START_PROFILE(SMBsetattrE);
4090 outsize = set_message(outbuf,0,0,True);
4092 if(!fsp || (fsp->conn != conn)) {
4093 END_PROFILE(SMBgetattrE);
4094 return ERROR_DOS(ERRDOS,ERRbadfid);
4098 * Convert the DOS times into unix times. Ignore create
4099 * time as UNIX can't set this.
4102 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4103 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4106 * Patch from Ray Frush <frush@engr.colostate.edu>
4107 * Sometimes times are sent as zero - ignore them.
4110 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4111 /* Ignore request */
4112 if( DEBUGLVL( 3 ) ) {
4113 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4114 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4116 END_PROFILE(SMBsetattrE);
4117 return(outsize);
4118 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4119 /* set modify time = to access time if modify time was 0 */
4120 unix_times.modtime = unix_times.actime;
4123 /* Set the date on this file */
4124 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4125 END_PROFILE(SMBsetattrE);
4126 return ERROR_DOS(ERRDOS,ERRnoaccess);
4129 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4130 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4132 END_PROFILE(SMBsetattrE);
4133 return(outsize);
4137 /* Back from the dead for OS/2..... JRA. */
4139 /****************************************************************************
4140 Reply to a SMBwritebmpx (write block multiplex primary) request.
4141 ****************************************************************************/
4143 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4145 size_t numtowrite;
4146 ssize_t nwritten = -1;
4147 int outsize = 0;
4148 SMB_OFF_T startpos;
4149 size_t tcount;
4150 BOOL write_through;
4151 int smb_doff;
4152 char *data;
4153 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4154 START_PROFILE(SMBwriteBmpx);
4156 CHECK_FSP(fsp,conn);
4157 CHECK_WRITE(fsp);
4158 CHECK_ERROR(fsp);
4160 tcount = SVAL(inbuf,smb_vwv1);
4161 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4162 write_through = BITSETW(inbuf+smb_vwv7,0);
4163 numtowrite = SVAL(inbuf,smb_vwv10);
4164 smb_doff = SVAL(inbuf,smb_vwv11);
4166 data = smb_base(inbuf) + smb_doff;
4168 /* If this fails we need to send an SMBwriteC response,
4169 not an SMBwritebmpx - set this up now so we don't forget */
4170 SCVAL(outbuf,smb_com,SMBwritec);
4172 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4173 END_PROFILE(SMBwriteBmpx);
4174 return(ERROR_DOS(ERRDOS,ERRlock));
4177 nwritten = write_file(fsp,data,startpos,numtowrite);
4179 if(lp_syncalways(SNUM(conn)) || write_through)
4180 sync_file(conn,fsp);
4182 if(nwritten < (ssize_t)numtowrite) {
4183 END_PROFILE(SMBwriteBmpx);
4184 return(UNIXERROR(ERRHRD,ERRdiskfull));
4187 /* If the maximum to be written to this file
4188 is greater than what we just wrote then set
4189 up a secondary struct to be attached to this
4190 fd, we will use this to cache error messages etc. */
4192 if((ssize_t)tcount > nwritten) {
4193 write_bmpx_struct *wbms;
4194 if(fsp->wbmpx_ptr != NULL)
4195 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4196 else
4197 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4198 if(!wbms) {
4199 DEBUG(0,("Out of memory in reply_readmpx\n"));
4200 END_PROFILE(SMBwriteBmpx);
4201 return(ERROR_DOS(ERRSRV,ERRnoresource));
4203 wbms->wr_mode = write_through;
4204 wbms->wr_discard = False; /* No errors yet */
4205 wbms->wr_total_written = nwritten;
4206 wbms->wr_errclass = 0;
4207 wbms->wr_error = 0;
4208 fsp->wbmpx_ptr = wbms;
4211 /* We are returning successfully, set the message type back to
4212 SMBwritebmpx */
4213 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4215 outsize = set_message(outbuf,1,0,True);
4217 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4219 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4220 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4222 if (write_through && tcount==nwritten) {
4223 /* We need to send both a primary and a secondary response */
4224 smb_setlen(outbuf,outsize - 4);
4225 if (!send_smb(smbd_server_fd(),outbuf))
4226 exit_server("reply_writebmpx: send_smb failed.");
4228 /* Now the secondary */
4229 outsize = set_message(outbuf,1,0,True);
4230 SCVAL(outbuf,smb_com,SMBwritec);
4231 SSVAL(outbuf,smb_vwv0,nwritten);
4234 END_PROFILE(SMBwriteBmpx);
4235 return(outsize);
4238 /****************************************************************************
4239 Reply to a SMBwritebs (write block multiplex secondary) request.
4240 ****************************************************************************/
4242 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4244 size_t numtowrite;
4245 ssize_t nwritten = -1;
4246 int outsize = 0;
4247 SMB_OFF_T startpos;
4248 size_t tcount;
4249 BOOL write_through;
4250 int smb_doff;
4251 char *data;
4252 write_bmpx_struct *wbms;
4253 BOOL send_response = False;
4254 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4255 START_PROFILE(SMBwriteBs);
4257 CHECK_FSP(fsp,conn);
4258 CHECK_WRITE(fsp);
4260 tcount = SVAL(inbuf,smb_vwv1);
4261 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4262 numtowrite = SVAL(inbuf,smb_vwv6);
4263 smb_doff = SVAL(inbuf,smb_vwv7);
4265 data = smb_base(inbuf) + smb_doff;
4267 /* We need to send an SMBwriteC response, not an SMBwritebs */
4268 SCVAL(outbuf,smb_com,SMBwritec);
4270 /* This fd should have an auxiliary struct attached,
4271 check that it does */
4272 wbms = fsp->wbmpx_ptr;
4273 if(!wbms) {
4274 END_PROFILE(SMBwriteBs);
4275 return(-1);
4278 /* If write through is set we can return errors, else we must cache them */
4279 write_through = wbms->wr_mode;
4281 /* Check for an earlier error */
4282 if(wbms->wr_discard) {
4283 END_PROFILE(SMBwriteBs);
4284 return -1; /* Just discard the packet */
4287 nwritten = write_file(fsp,data,startpos,numtowrite);
4289 if(lp_syncalways(SNUM(conn)) || write_through)
4290 sync_file(conn,fsp);
4292 if (nwritten < (ssize_t)numtowrite) {
4293 if(write_through) {
4294 /* We are returning an error - we can delete the aux struct */
4295 if (wbms)
4296 free((char *)wbms);
4297 fsp->wbmpx_ptr = NULL;
4298 END_PROFILE(SMBwriteBs);
4299 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4301 END_PROFILE(SMBwriteBs);
4302 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4305 /* Increment the total written, if this matches tcount
4306 we can discard the auxiliary struct (hurrah !) and return a writeC */
4307 wbms->wr_total_written += nwritten;
4308 if(wbms->wr_total_written >= tcount) {
4309 if (write_through) {
4310 outsize = set_message(outbuf,1,0,True);
4311 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4312 send_response = True;
4315 free((char *)wbms);
4316 fsp->wbmpx_ptr = NULL;
4319 if(send_response) {
4320 END_PROFILE(SMBwriteBs);
4321 return(outsize);
4324 END_PROFILE(SMBwriteBs);
4325 return(-1);
4328 /****************************************************************************
4329 Reply to a SMBgetattrE.
4330 ****************************************************************************/
4332 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4334 SMB_STRUCT_STAT sbuf;
4335 int outsize = 0;
4336 int mode;
4337 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4338 START_PROFILE(SMBgetattrE);
4340 outsize = set_message(outbuf,11,0,True);
4342 if(!fsp || (fsp->conn != conn)) {
4343 END_PROFILE(SMBgetattrE);
4344 return ERROR_DOS(ERRDOS,ERRbadfid);
4347 /* Do an fstat on this file */
4348 if(fsp_stat(fsp, &sbuf)) {
4349 END_PROFILE(SMBgetattrE);
4350 return(UNIXERROR(ERRDOS,ERRnoaccess));
4353 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4356 * Convert the times into dos times. Set create
4357 * date to be last modify date as UNIX doesn't save
4358 * this.
4361 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4362 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4363 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4365 if (mode & aDIR) {
4366 SIVAL(outbuf,smb_vwv6,0);
4367 SIVAL(outbuf,smb_vwv8,0);
4368 } else {
4369 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4370 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4372 SSVAL(outbuf,smb_vwv10, mode);
4374 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4376 END_PROFILE(SMBgetattrE);
4377 return(outsize);