00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "includes.h"
00028
00029
00030 extern enum protocol_types Protocol;
00031 extern int max_send;
00032 extern int max_recv;
00033 unsigned int smb_echo_count = 0;
00034 extern uint32 global_client_caps;
00035
00036 extern struct current_user current_user;
00037 extern BOOL global_encrypted_passwords_negotiated;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
00049
00050 NTSTATUS check_path_syntax_internal(pstring destname,
00051 const pstring srcname,
00052 BOOL posix_path,
00053 BOOL *p_last_component_contains_wcard)
00054 {
00055 char *d = destname;
00056 const char *s = srcname;
00057 NTSTATUS ret = NT_STATUS_OK;
00058 BOOL start_of_name_component = True;
00059
00060 *p_last_component_contains_wcard = False;
00061
00062 while (*s) {
00063 if (IS_PATH_SEP(*s,posix_path)) {
00064
00065
00066
00067
00068 while (IS_PATH_SEP(*s,posix_path)) {
00069 s++;
00070 }
00071 if ((d != destname) && (*s != '\0')) {
00072
00073 *d++ = '/';
00074 }
00075
00076 start_of_name_component = True;
00077
00078 *p_last_component_contains_wcard = False;
00079 continue;
00080 }
00081
00082 if (start_of_name_component) {
00083 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
00084
00085
00086
00087
00088
00089
00090
00091 if ((d > destname) && (*(d-1) == '/')) {
00092 *(d-1) = '\0';
00093 d--;
00094 }
00095
00096
00097 if (d <= destname) {
00098 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
00099 break;
00100 }
00101
00102
00103
00104
00105 for (d--; d > destname; d--) {
00106 if (*d == '/')
00107 break;
00108 }
00109 s += 2;
00110
00111 continue;
00112
00113 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
00114 if (posix_path) {
00115
00116 s++;
00117 continue;
00118 }
00119 }
00120
00121 }
00122
00123 if (!(*s & 0x80)) {
00124 if (!posix_path) {
00125 if (*s <= 0x1f) {
00126 return NT_STATUS_OBJECT_NAME_INVALID;
00127 }
00128 switch (*s) {
00129 case '*':
00130 case '?':
00131 case '<':
00132 case '>':
00133 case '"':
00134 *p_last_component_contains_wcard = True;
00135 break;
00136 default:
00137 break;
00138 }
00139 }
00140 *d++ = *s++;
00141 } else {
00142 size_t siz;
00143
00144 next_codepoint(s,&siz);
00145 switch(siz) {
00146 case 5:
00147 *d++ = *s++;
00148
00149 case 4:
00150 *d++ = *s++;
00151
00152 case 3:
00153 *d++ = *s++;
00154
00155 case 2:
00156 *d++ = *s++;
00157
00158 case 1:
00159 *d++ = *s++;
00160 break;
00161 default:
00162 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
00163 *d = '\0';
00164 return NT_STATUS_INVALID_PARAMETER;
00165 }
00166 }
00167 start_of_name_component = False;
00168 }
00169
00170 *d = '\0';
00171 return ret;
00172 }
00173
00174
00175
00176
00177
00178
00179 NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
00180 {
00181 BOOL ignore;
00182 return check_path_syntax_internal(destname, srcname, False, &ignore);
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
00192 {
00193 return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
00203 {
00204 BOOL ignore;
00205 return check_path_syntax_internal(destname, srcname, True, &ignore);
00206 }
00207
00208
00209
00210
00211
00212 size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
00213 NTSTATUS *err, BOOL *contains_wcard)
00214 {
00215 pstring tmppath;
00216 char *tmppath_ptr = tmppath;
00217 size_t ret;
00218 #ifdef DEVELOPER
00219 SMB_ASSERT(dest_len == sizeof(pstring));
00220 #endif
00221
00222 if (src_len == 0) {
00223 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
00224 } else {
00225 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
00226 }
00227
00228 *contains_wcard = False;
00229
00230 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
00231
00232
00233
00234
00235 pstrcpy(dest, tmppath);
00236 *err = NT_STATUS_OK;
00237 return ret;
00238 }
00239
00240 if (lp_posix_pathnames()) {
00241 *err = check_path_syntax_posix(dest, tmppath);
00242 } else {
00243 *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
00244 }
00245
00246 return ret;
00247 }
00248
00249
00250
00251
00252
00253 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
00254 {
00255 pstring tmppath;
00256 char *tmppath_ptr = tmppath;
00257 size_t ret;
00258 #ifdef DEVELOPER
00259 SMB_ASSERT(dest_len == sizeof(pstring));
00260 #endif
00261
00262 if (src_len == 0) {
00263 ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
00264 } else {
00265 ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
00266 }
00267
00268 if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
00269
00270
00271
00272
00273 pstrcpy(dest, tmppath);
00274 *err = NT_STATUS_OK;
00275 return ret;
00276 }
00277
00278 if (lp_posix_pathnames()) {
00279 *err = check_path_syntax_posix(dest, tmppath);
00280 } else {
00281 *err = check_path_syntax(dest, tmppath);
00282 }
00283
00284 return ret;
00285 }
00286
00287
00288
00289
00290
00291 int reply_special(char *inbuf,char *outbuf)
00292 {
00293 int outsize = 4;
00294 int msg_type = CVAL(inbuf,0);
00295 int msg_flags = CVAL(inbuf,1);
00296 fstring name1,name2;
00297 char name_type = 0;
00298
00299 static BOOL already_got_session = False;
00300
00301 *name1 = *name2 = 0;
00302
00303 memset(outbuf,'\0',smb_size);
00304
00305 smb_setlen(outbuf,0);
00306
00307 switch (msg_type) {
00308 case 0x81:
00309
00310 if (already_got_session) {
00311 exit_server_cleanly("multiple session request not permitted");
00312 }
00313
00314 SCVAL(outbuf,0,0x82);
00315 SCVAL(outbuf,3,0);
00316 if (name_len(inbuf+4) > 50 ||
00317 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
00318 DEBUG(0,("Invalid name length in session request\n"));
00319 return(0);
00320 }
00321 name_extract(inbuf,4,name1);
00322 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
00323 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
00324 name1,name2));
00325
00326 set_local_machine_name(name1, True);
00327 set_remote_machine_name(name2, True);
00328
00329 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
00330 get_local_machine_name(), get_remote_machine_name(),
00331 name_type));
00332
00333 if (name_type == 'R') {
00334
00335
00336 SCVAL(outbuf, 0,0x83);
00337 break;
00338 }
00339
00340
00341
00342
00343 if (lp_security() == SEC_SHARE) {
00344 add_session_user(get_remote_machine_name());
00345 }
00346
00347 reload_services(True);
00348 reopen_logs();
00349
00350 already_got_session = True;
00351 break;
00352
00353 case 0x89:
00354
00355 SCVAL(outbuf,0,SMBkeepalive);
00356 SCVAL(outbuf,3,0);
00357 break;
00358
00359 case 0x82:
00360 case 0x83:
00361 case 0x84:
00362 DEBUG(0,("Unexpected session response\n"));
00363 break;
00364
00365 case SMBkeepalive:
00366 default:
00367 return(0);
00368 }
00369
00370 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
00371 msg_type, msg_flags));
00372
00373 return(outsize);
00374 }
00375
00376
00377
00378
00379
00380
00381 int reply_tcon(connection_struct *conn,
00382 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00383 {
00384 const char *service;
00385 pstring service_buf;
00386 pstring password;
00387 pstring dev;
00388 int outsize = 0;
00389 uint16 vuid = SVAL(inbuf,smb_uid);
00390 int pwlen=0;
00391 NTSTATUS nt_status;
00392 char *p;
00393 DATA_BLOB password_blob;
00394
00395 START_PROFILE(SMBtcon);
00396
00397 *service_buf = *password = *dev = 0;
00398
00399 p = smb_buf(inbuf)+1;
00400 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
00401 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
00402 p += pwlen;
00403 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
00404
00405 p = strrchr_m(service_buf,'\\');
00406 if (p) {
00407 service = p+1;
00408 } else {
00409 service = service_buf;
00410 }
00411
00412 password_blob = data_blob(password, pwlen+1);
00413
00414 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
00415
00416 data_blob_clear_free(&password_blob);
00417
00418 if (!conn) {
00419 END_PROFILE(SMBtcon);
00420 return ERROR_NT(nt_status);
00421 }
00422
00423 outsize = set_message(outbuf,2,0,True);
00424 SSVAL(outbuf,smb_vwv0,max_recv);
00425 SSVAL(outbuf,smb_vwv1,conn->cnum);
00426 SSVAL(outbuf,smb_tid,conn->cnum);
00427
00428 DEBUG(3,("tcon service=%s cnum=%d\n",
00429 service, conn->cnum));
00430
00431 END_PROFILE(SMBtcon);
00432 return(outsize);
00433 }
00434
00435
00436
00437
00438
00439
00440 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
00441 {
00442 fstring service;
00443 DATA_BLOB password;
00444
00445
00446 fstring client_devicetype;
00447
00448 const char *server_devicetype;
00449 NTSTATUS nt_status;
00450 uint16 vuid = SVAL(inbuf,smb_uid);
00451 int passlen = SVAL(inbuf,smb_vwv3);
00452 pstring path;
00453 char *p, *q;
00454 uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
00455
00456 START_PROFILE(SMBtconX);
00457
00458 *service = *client_devicetype = 0;
00459
00460
00461 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
00462 close_cnum(conn,vuid);
00463 }
00464
00465 if (passlen > MAX_PASS_LEN) {
00466 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
00467 }
00468
00469 if (global_encrypted_passwords_negotiated) {
00470 password = data_blob(smb_buf(inbuf),passlen);
00471 if (lp_security() == SEC_SHARE) {
00472
00473
00474
00475
00476 p = smb_buf(inbuf) + passlen + 1;
00477 } else {
00478 p = smb_buf(inbuf) + passlen;
00479 }
00480 } else {
00481 password = data_blob(smb_buf(inbuf),passlen+1);
00482
00483 password.data[passlen]=0;
00484 p = smb_buf(inbuf) + passlen + 1;
00485 }
00486
00487 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
00488
00489
00490
00491
00492
00493 if (*path=='\\') {
00494 q = strchr_m(path+2,'\\');
00495 if (!q) {
00496 END_PROFILE(SMBtconX);
00497 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
00498 }
00499 fstrcpy(service,q+1);
00500 }
00501 else
00502 fstrcpy(service,path);
00503
00504 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
00505
00506 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
00507
00508 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
00509
00510 data_blob_clear_free(&password);
00511
00512 if (!conn) {
00513 END_PROFILE(SMBtconX);
00514 return ERROR_NT(nt_status);
00515 }
00516
00517 if ( IS_IPC(conn) )
00518 server_devicetype = "IPC";
00519 else if ( IS_PRINT(conn) )
00520 server_devicetype = "LPT1:";
00521 else
00522 server_devicetype = "A:";
00523
00524 if (Protocol < PROTOCOL_NT1) {
00525 set_message(outbuf,2,0,True);
00526 p = smb_buf(outbuf);
00527 p += srvstr_push(outbuf, p, server_devicetype, BUFFER_SIZE - (p - outbuf),
00528 STR_TERMINATE|STR_ASCII);
00529 set_message_end(outbuf,p);
00530 } else {
00531
00532 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
00533
00534 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
00535
00536 uint32 perm1 = 0;
00537 uint32 perm2 = 0;
00538
00539 set_message(outbuf,7,0,True);
00540
00541 if (IS_IPC(conn)) {
00542 perm1 = FILE_ALL_ACCESS;
00543 perm2 = FILE_ALL_ACCESS;
00544 } else {
00545 perm1 = CAN_WRITE(conn) ?
00546 SHARE_ALL_ACCESS :
00547 SHARE_READ_ONLY;
00548 }
00549
00550 SIVAL(outbuf, smb_vwv3, perm1);
00551 SIVAL(outbuf, smb_vwv5, perm2);
00552 } else {
00553 set_message(outbuf,3,0,True);
00554 }
00555
00556 p = smb_buf(outbuf);
00557 p += srvstr_push(outbuf, p, server_devicetype, BUFFER_SIZE - (p - outbuf),
00558 STR_TERMINATE|STR_ASCII);
00559 p += srvstr_push(outbuf, p, fstype, BUFFER_SIZE - (p - outbuf),
00560 STR_TERMINATE);
00561
00562 set_message_end(outbuf,p);
00563
00564
00565
00566 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
00567 (lp_csc_policy(SNUM(conn)) << 2));
00568
00569 init_dfsroot(conn, inbuf, outbuf);
00570 }
00571
00572
00573 DEBUG(3,("tconX service=%s \n",
00574 service));
00575
00576
00577 SSVAL(inbuf,smb_tid,conn->cnum);
00578 SSVAL(outbuf,smb_tid,conn->cnum);
00579
00580 END_PROFILE(SMBtconX);
00581 return chain_reply(inbuf,outbuf,length,bufsize);
00582 }
00583
00584
00585
00586
00587
00588 int reply_unknown(char *inbuf,char *outbuf)
00589 {
00590 int type;
00591 type = CVAL(inbuf,smb_com);
00592
00593 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
00594 smb_fn_name(type), type, type));
00595
00596 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
00597 }
00598
00599
00600
00601
00602
00603
00604 int reply_ioctl(connection_struct *conn,
00605 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00606 {
00607 uint16 device = SVAL(inbuf,smb_vwv1);
00608 uint16 function = SVAL(inbuf,smb_vwv2);
00609 uint32 ioctl_code = (device << 16) + function;
00610 int replysize, outsize;
00611 char *p;
00612 START_PROFILE(SMBioctl);
00613
00614 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
00615
00616 switch (ioctl_code) {
00617 case IOCTL_QUERY_JOB_INFO:
00618 replysize = 32;
00619 break;
00620 default:
00621 END_PROFILE(SMBioctl);
00622 return(ERROR_DOS(ERRSRV,ERRnosupport));
00623 }
00624
00625 outsize = set_message(outbuf,8,replysize+1,True);
00626 SSVAL(outbuf,smb_vwv1,replysize);
00627 SSVAL(outbuf,smb_vwv5,replysize);
00628 SSVAL(outbuf,smb_vwv6,52);
00629 p = smb_buf(outbuf) + 1;
00630
00631 switch (ioctl_code) {
00632 case IOCTL_QUERY_JOB_INFO:
00633 {
00634 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
00635 if (!fsp) {
00636 END_PROFILE(SMBioctl);
00637 return(UNIXERROR(ERRDOS,ERRbadfid));
00638 }
00639 SSVAL(p,0,fsp->rap_print_jobid);
00640 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
00641 if (conn) {
00642 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
00643 }
00644 break;
00645 }
00646 }
00647
00648 END_PROFILE(SMBioctl);
00649 return outsize;
00650 }
00651
00652
00653
00654
00655
00656 static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
00657 {
00658
00659 if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
00660 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
00661
00662 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
00663 }
00664 }
00665 return status;
00666 }
00667
00668
00669
00670
00671
00672 int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00673 {
00674 int outsize = 0;
00675 pstring name;
00676 SMB_STRUCT_STAT sbuf;
00677 NTSTATUS status;
00678
00679 START_PROFILE(SMBcheckpath);
00680
00681 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
00682 if (!NT_STATUS_IS_OK(status)) {
00683 END_PROFILE(SMBcheckpath);
00684 status = map_checkpath_error(inbuf, status);
00685 return ERROR_NT(status);
00686 }
00687
00688 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
00689 if (!NT_STATUS_IS_OK(status)) {
00690 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
00691 END_PROFILE(SMBcheckpath);
00692 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
00693 }
00694 goto path_err;
00695 }
00696
00697 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
00698
00699 status = unix_convert(conn, name, False, NULL, &sbuf);
00700 if (!NT_STATUS_IS_OK(status)) {
00701 goto path_err;
00702 }
00703
00704 status = check_name(conn, name);
00705 if (!NT_STATUS_IS_OK(status)) {
00706 DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
00707 goto path_err;
00708 }
00709
00710 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
00711 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
00712 status = map_nt_error_from_unix(errno);
00713 goto path_err;
00714 }
00715
00716 if (!S_ISDIR(sbuf.st_mode)) {
00717 END_PROFILE(SMBcheckpath);
00718 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
00719 }
00720
00721 outsize = set_message(outbuf,0,0,False);
00722
00723 END_PROFILE(SMBcheckpath);
00724 return outsize;
00725
00726 path_err:
00727
00728 END_PROFILE(SMBcheckpath);
00729
00730
00731
00732
00733
00734
00735 status = map_checkpath_error(inbuf, status);
00736 if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
00737
00738
00739
00740
00741
00742
00743
00744 return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
00745 }
00746
00747 return ERROR_NT(status);
00748 }
00749
00750
00751
00752
00753
00754 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00755 {
00756 pstring fname;
00757 int outsize = 0;
00758 SMB_STRUCT_STAT sbuf;
00759 int mode=0;
00760 SMB_OFF_T size=0;
00761 time_t mtime=0;
00762 char *p;
00763 NTSTATUS status;
00764
00765 START_PROFILE(SMBgetatr);
00766
00767 p = smb_buf(inbuf) + 1;
00768 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
00769 if (!NT_STATUS_IS_OK(status)) {
00770 END_PROFILE(SMBgetatr);
00771 return ERROR_NT(status);
00772 }
00773
00774 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
00775 if (!NT_STATUS_IS_OK(status)) {
00776 END_PROFILE(SMBgetatr);
00777 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
00778 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
00779 }
00780 return ERROR_NT(status);
00781 }
00782
00783
00784
00785 if (*fname == '\0') {
00786 mode = aHIDDEN | aDIR;
00787 if (!CAN_WRITE(conn)) {
00788 mode |= aRONLY;
00789 }
00790 size = 0;
00791 mtime = 0;
00792 } else {
00793 status = unix_convert(conn, fname, False, NULL,&sbuf);
00794 if (!NT_STATUS_IS_OK(status)) {
00795 END_PROFILE(SMBgetatr);
00796 return ERROR_NT(status);
00797 }
00798 status = check_name(conn, fname);
00799 if (!NT_STATUS_IS_OK(status)) {
00800 DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
00801 END_PROFILE(SMBgetatr);
00802 return ERROR_NT(status);
00803 }
00804 if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
00805 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
00806 return UNIXERROR(ERRDOS,ERRbadfile);
00807 }
00808
00809 mode = dos_mode(conn,fname,&sbuf);
00810 size = sbuf.st_size;
00811 mtime = sbuf.st_mtime;
00812 if (mode & aDIR) {
00813 size = 0;
00814 }
00815 }
00816
00817 outsize = set_message(outbuf,10,0,True);
00818
00819 SSVAL(outbuf,smb_vwv0,mode);
00820 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
00821 srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
00822 } else {
00823 srv_put_dos_date3(outbuf,smb_vwv1,mtime);
00824 }
00825 SIVAL(outbuf,smb_vwv3,(uint32)size);
00826
00827 if (Protocol >= PROTOCOL_NT1) {
00828 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
00829 }
00830
00831 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
00832
00833 END_PROFILE(SMBgetatr);
00834 return(outsize);
00835 }
00836
00837
00838
00839
00840
00841 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00842 {
00843 pstring fname;
00844 int outsize = 0;
00845 int mode;
00846 time_t mtime;
00847 SMB_STRUCT_STAT sbuf;
00848 char *p;
00849 NTSTATUS status;
00850
00851 START_PROFILE(SMBsetatr);
00852
00853 p = smb_buf(inbuf) + 1;
00854 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
00855 if (!NT_STATUS_IS_OK(status)) {
00856 END_PROFILE(SMBsetatr);
00857 return ERROR_NT(status);
00858 }
00859
00860 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
00861 if (!NT_STATUS_IS_OK(status)) {
00862 END_PROFILE(SMBsetatr);
00863 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
00864 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
00865 }
00866 return ERROR_NT(status);
00867 }
00868
00869 status = unix_convert(conn, fname, False, NULL, &sbuf);
00870 if (!NT_STATUS_IS_OK(status)) {
00871 END_PROFILE(SMBsetatr);
00872 return ERROR_NT(status);
00873 }
00874
00875 status = check_name(conn, fname);
00876 if (!NT_STATUS_IS_OK(status)) {
00877 END_PROFILE(SMBsetatr);
00878 return ERROR_NT(status);
00879 }
00880
00881 if (fname[0] == '.' && fname[1] == '\0') {
00882
00883
00884
00885
00886 END_PROFILE(SMBsetatr);
00887 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
00888 }
00889
00890 mode = SVAL(inbuf,smb_vwv0);
00891 mtime = srv_make_unix_date3(inbuf+smb_vwv1);
00892
00893 if (mode != FILE_ATTRIBUTE_NORMAL) {
00894 if (VALID_STAT_OF_DIR(sbuf))
00895 mode |= aDIR;
00896 else
00897 mode &= ~aDIR;
00898
00899 if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
00900 END_PROFILE(SMBsetatr);
00901 return UNIXERROR(ERRDOS, ERRnoaccess);
00902 }
00903 }
00904
00905 if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
00906 END_PROFILE(SMBsetatr);
00907 return UNIXERROR(ERRDOS, ERRnoaccess);
00908 }
00909
00910 outsize = set_message(outbuf,0,0,False);
00911
00912 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
00913
00914 END_PROFILE(SMBsetatr);
00915 return(outsize);
00916 }
00917
00918
00919
00920
00921
00922 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00923 {
00924 int outsize = 0;
00925 SMB_BIG_UINT dfree,dsize,bsize;
00926 START_PROFILE(SMBdskattr);
00927
00928 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
00929 END_PROFILE(SMBdskattr);
00930 return(UNIXERROR(ERRHRD,ERRgeneral));
00931 }
00932
00933 outsize = set_message(outbuf,5,0,True);
00934
00935 if (Protocol <= PROTOCOL_LANMAN2) {
00936 double total_space, free_space;
00937
00938
00939
00940
00941
00942
00943 total_space = dsize * (double)bsize;
00944 free_space = dfree * (double)bsize;
00945
00946 dsize = (total_space+63*512) / (64*512);
00947 dfree = (free_space+63*512) / (64*512);
00948
00949 if (dsize > 0xFFFF) dsize = 0xFFFF;
00950 if (dfree > 0xFFFF) dfree = 0xFFFF;
00951
00952 SSVAL(outbuf,smb_vwv0,dsize);
00953 SSVAL(outbuf,smb_vwv1,64);
00954 SSVAL(outbuf,smb_vwv2,512);
00955 SSVAL(outbuf,smb_vwv3,dfree);
00956 } else {
00957 SSVAL(outbuf,smb_vwv0,dsize);
00958 SSVAL(outbuf,smb_vwv1,bsize/512);
00959 SSVAL(outbuf,smb_vwv2,512);
00960 SSVAL(outbuf,smb_vwv3,dfree);
00961 }
00962
00963 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
00964
00965 END_PROFILE(SMBdskattr);
00966 return(outsize);
00967 }
00968
00969
00970
00971
00972
00973
00974 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
00975 {
00976 pstring mask;
00977 pstring directory;
00978 pstring fname;
00979 SMB_OFF_T size;
00980 uint32 mode;
00981 time_t date;
00982 uint32 dirtype;
00983 int outsize = 0;
00984 unsigned int numentries = 0;
00985 unsigned int maxentries = 0;
00986 BOOL finished = False;
00987 char *p;
00988 int status_len;
00989 pstring path;
00990 char status[21];
00991 int dptr_num= -1;
00992 BOOL check_descend = False;
00993 BOOL expect_close = False;
00994 NTSTATUS nt_status;
00995 BOOL mask_contains_wcard = False;
00996 BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
00997
00998 START_PROFILE(SMBsearch);
00999
01000 if (lp_posix_pathnames()) {
01001 END_PROFILE(SMBsearch);
01002 return reply_unknown(inbuf, outbuf);
01003 }
01004
01005 *mask = *directory = *fname = 0;
01006
01007
01008 if(CVAL(inbuf,smb_com) == SMBffirst) {
01009 expect_close = True;
01010 }
01011
01012 outsize = set_message(outbuf,1,3,True);
01013 maxentries = SVAL(inbuf,smb_vwv0);
01014 dirtype = SVAL(inbuf,smb_vwv1);
01015 p = smb_buf(inbuf) + 1;
01016 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
01017 if (!NT_STATUS_IS_OK(nt_status)) {
01018 END_PROFILE(SMBsearch);
01019 return ERROR_NT(nt_status);
01020 }
01021
01022 nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
01023 if (!NT_STATUS_IS_OK(nt_status)) {
01024 END_PROFILE(SMBsearch);
01025 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
01026 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01027 }
01028 return ERROR_NT(nt_status);
01029 }
01030
01031 p++;
01032 status_len = SVAL(p, 0);
01033 p += 2;
01034
01035
01036
01037 if (status_len == 0) {
01038 SMB_STRUCT_STAT sbuf;
01039
01040 pstrcpy(directory,path);
01041 nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
01042 if (!NT_STATUS_IS_OK(nt_status)) {
01043 END_PROFILE(SMBsearch);
01044 return ERROR_NT(nt_status);
01045 }
01046
01047 nt_status = check_name(conn, directory);
01048 if (!NT_STATUS_IS_OK(nt_status)) {
01049 END_PROFILE(SMBsearch);
01050 return ERROR_NT(nt_status);
01051 }
01052
01053 p = strrchr_m(directory,'/');
01054 if (!p) {
01055 pstrcpy(mask,directory);
01056 pstrcpy(directory,".");
01057 } else {
01058 *p = 0;
01059 pstrcpy(mask,p+1);
01060 }
01061
01062 if (*directory == '\0') {
01063 pstrcpy(directory,".");
01064 }
01065 memset((char *)status,'\0',21);
01066 SCVAL(status,0,(dirtype & 0x1F));
01067 } else {
01068 int status_dirtype;
01069
01070 memcpy(status,p,21);
01071 status_dirtype = CVAL(status,0) & 0x1F;
01072 if (status_dirtype != (dirtype & 0x1F)) {
01073 dirtype = status_dirtype;
01074 }
01075
01076 conn->dirptr = dptr_fetch(status+12,&dptr_num);
01077 if (!conn->dirptr) {
01078 goto SearchEmpty;
01079 }
01080 string_set(&conn->dirpath,dptr_path(dptr_num));
01081 pstrcpy(mask, dptr_wcard(dptr_num));
01082
01083
01084
01085
01086 mask_contains_wcard = ms_has_wild(mask);
01087 }
01088
01089 p = smb_buf(outbuf) + 3;
01090
01091 if (status_len == 0) {
01092 nt_status = dptr_create(conn,
01093 directory,
01094 True,
01095 expect_close,
01096 SVAL(inbuf,smb_pid),
01097 mask,
01098 mask_contains_wcard,
01099 dirtype,
01100 &conn->dirptr);
01101 if (!NT_STATUS_IS_OK(nt_status)) {
01102 return ERROR_NT(nt_status);
01103 }
01104 dptr_num = dptr_dnum(conn->dirptr);
01105 } else {
01106 dirtype = dptr_attr(dptr_num);
01107 }
01108
01109 DEBUG(4,("dptr_num is %d\n",dptr_num));
01110
01111 if ((dirtype&0x1F) == aVOLID) {
01112 memcpy(p,status,21);
01113 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
01114 0,aVOLID,0,!allow_long_path_components);
01115 dptr_fill(p+12,dptr_num);
01116 if (dptr_zero(p+12) && (status_len==0)) {
01117 numentries = 1;
01118 } else {
01119 numentries = 0;
01120 }
01121 p += DIR_STRUCT_SIZE;
01122 } else {
01123 unsigned int i;
01124 maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
01125
01126 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
01127 conn->dirpath,lp_dontdescend(SNUM(conn))));
01128 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
01129 check_descend = True;
01130 }
01131
01132 for (i=numentries;(i<maxentries) && !finished;i++) {
01133 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
01134 if (!finished) {
01135 memcpy(p,status,21);
01136 make_dir_struct(p,mask,fname,size, mode,date,
01137 !allow_long_path_components);
01138 if (!dptr_fill(p+12,dptr_num)) {
01139 break;
01140 }
01141 numentries++;
01142 p += DIR_STRUCT_SIZE;
01143 }
01144 }
01145 }
01146
01147 SearchEmpty:
01148
01149
01150
01151
01152
01153 if (numentries == 0) {
01154 dptr_close(&dptr_num);
01155 } else if(expect_close && status_len == 0) {
01156
01157 dptr_close(&dptr_num);
01158 }
01159
01160
01161 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
01162 dptr_close(&dptr_num);
01163 }
01164
01165 if ((numentries == 0) && !mask_contains_wcard) {
01166 return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
01167 }
01168
01169 SSVAL(outbuf,smb_vwv0,numentries);
01170 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
01171 SCVAL(smb_buf(outbuf),0,5);
01172 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
01173
01174
01175 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
01176 if (!allow_long_path_components) {
01177 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
01178 }
01179
01180
01181 SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
01182
01183 outsize += DIR_STRUCT_SIZE*numentries;
01184 smb_setlen(outbuf,outsize - 4);
01185
01186 if ((! *directory) && dptr_path(dptr_num))
01187 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
01188
01189 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
01190 smb_fn_name(CVAL(inbuf,smb_com)),
01191 mask, directory, dirtype, numentries, maxentries ) );
01192
01193 END_PROFILE(SMBsearch);
01194 return(outsize);
01195 }
01196
01197
01198
01199
01200
01201 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
01202 {
01203 int outsize = 0;
01204 int status_len;
01205 pstring path;
01206 char status[21];
01207 int dptr_num= -2;
01208 char *p;
01209 NTSTATUS err;
01210 BOOL path_contains_wcard = False;
01211
01212 START_PROFILE(SMBfclose);
01213
01214 if (lp_posix_pathnames()) {
01215 END_PROFILE(SMBfclose);
01216 return reply_unknown(inbuf, outbuf);
01217 }
01218
01219 outsize = set_message(outbuf,1,0,True);
01220 p = smb_buf(inbuf) + 1;
01221 p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
01222 if (!NT_STATUS_IS_OK(err)) {
01223 END_PROFILE(SMBfclose);
01224 return ERROR_NT(err);
01225 }
01226 p++;
01227 status_len = SVAL(p,0);
01228 p += 2;
01229
01230 if (status_len == 0) {
01231 END_PROFILE(SMBfclose);
01232 return ERROR_DOS(ERRSRV,ERRsrverror);
01233 }
01234
01235 memcpy(status,p,21);
01236
01237 if(dptr_fetch(status+12,&dptr_num)) {
01238
01239 dptr_close(&dptr_num);
01240 }
01241
01242 SSVAL(outbuf,smb_vwv0,0);
01243
01244 DEBUG(3,("search close\n"));
01245
01246 END_PROFILE(SMBfclose);
01247 return(outsize);
01248 }
01249
01250
01251
01252
01253
01254 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
01255 {
01256 pstring fname;
01257 int outsize = 0;
01258 uint32 fattr=0;
01259 SMB_OFF_T size = 0;
01260 time_t mtime=0;
01261 int info;
01262 SMB_STRUCT_STAT sbuf;
01263 files_struct *fsp;
01264 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
01265 int deny_mode;
01266 uint32 dos_attr = SVAL(inbuf,smb_vwv1);
01267 uint32 access_mask;
01268 uint32 share_mode;
01269 uint32 create_disposition;
01270 uint32 create_options = 0;
01271 NTSTATUS status;
01272 START_PROFILE(SMBopen);
01273
01274 deny_mode = SVAL(inbuf,smb_vwv0);
01275
01276 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
01277 if (!NT_STATUS_IS_OK(status)) {
01278 END_PROFILE(SMBopen);
01279 return ERROR_NT(status);
01280 }
01281
01282 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
01283 if (!NT_STATUS_IS_OK(status)) {
01284 END_PROFILE(SMBopen);
01285 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01286 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01287 }
01288 return ERROR_NT(status);
01289 }
01290
01291 status = unix_convert(conn, fname, False, NULL, &sbuf);
01292 if (!NT_STATUS_IS_OK(status)) {
01293 END_PROFILE(SMBopen);
01294 return ERROR_NT(status);
01295 }
01296
01297 status = check_name(conn, fname);
01298 if (!NT_STATUS_IS_OK(status)) {
01299 END_PROFILE(SMBopen);
01300 return ERROR_NT(status);
01301 }
01302
01303 if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
01304 &access_mask, &share_mode, &create_disposition, &create_options)) {
01305 END_PROFILE(SMBopen);
01306 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
01307 }
01308
01309 status = open_file_ntcreate(conn,fname,&sbuf,
01310 access_mask,
01311 share_mode,
01312 create_disposition,
01313 create_options,
01314 dos_attr,
01315 oplock_request,
01316 &info, &fsp);
01317
01318 if (!NT_STATUS_IS_OK(status)) {
01319 END_PROFILE(SMBopen);
01320 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01321
01322 return -1;
01323 }
01324 return ERROR_OPEN(status);
01325 }
01326
01327 size = sbuf.st_size;
01328 fattr = dos_mode(conn,fname,&sbuf);
01329 mtime = sbuf.st_mtime;
01330
01331 if (fattr & aDIR) {
01332 DEBUG(3,("attempt to open a directory %s\n",fname));
01333 close_file(fsp,ERROR_CLOSE);
01334 END_PROFILE(SMBopen);
01335 return ERROR_DOS(ERRDOS,ERRnoaccess);
01336 }
01337
01338 outsize = set_message(outbuf,7,0,True);
01339 SSVAL(outbuf,smb_vwv0,fsp->fnum);
01340 SSVAL(outbuf,smb_vwv1,fattr);
01341 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
01342 srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
01343 } else {
01344 srv_put_dos_date3(outbuf,smb_vwv2,mtime);
01345 }
01346 SIVAL(outbuf,smb_vwv4,(uint32)size);
01347 SSVAL(outbuf,smb_vwv6,deny_mode);
01348
01349 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
01350 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01351 }
01352
01353 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01354 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01355 }
01356 END_PROFILE(SMBopen);
01357 return(outsize);
01358 }
01359
01360
01361
01362
01363
01364 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
01365 {
01366 pstring fname;
01367 uint16 open_flags = SVAL(inbuf,smb_vwv2);
01368 int deny_mode = SVAL(inbuf,smb_vwv3);
01369 uint32 smb_attr = SVAL(inbuf,smb_vwv5);
01370
01371
01372 int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
01373 int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
01374 int oplock_request = ex_oplock_request | core_oplock_request;
01375 #if 0
01376 int smb_sattr = SVAL(inbuf,smb_vwv4);
01377 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
01378 #endif
01379 int smb_ofun = SVAL(inbuf,smb_vwv8);
01380 uint32 fattr=0;
01381 int mtime=0;
01382 SMB_STRUCT_STAT sbuf;
01383 int smb_action = 0;
01384 files_struct *fsp;
01385 NTSTATUS status;
01386 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
01387 ssize_t retval = -1;
01388 uint32 access_mask;
01389 uint32 share_mode;
01390 uint32 create_disposition;
01391 uint32 create_options = 0;
01392
01393 START_PROFILE(SMBopenX);
01394
01395
01396 if (IS_IPC(conn)) {
01397 if (lp_nt_pipe_support()) {
01398 END_PROFILE(SMBopenX);
01399 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
01400 } else {
01401 END_PROFILE(SMBopenX);
01402 return ERROR_DOS(ERRSRV,ERRaccess);
01403 }
01404 }
01405
01406
01407 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
01408 if (!NT_STATUS_IS_OK(status)) {
01409 END_PROFILE(SMBopenX);
01410 return ERROR_NT(status);
01411 }
01412
01413 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
01414 if (!NT_STATUS_IS_OK(status)) {
01415 END_PROFILE(SMBopenX);
01416 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01417 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01418 }
01419 return ERROR_NT(status);
01420 }
01421
01422 status = unix_convert(conn, fname, False, NULL, &sbuf);
01423 if (!NT_STATUS_IS_OK(status)) {
01424 END_PROFILE(SMBopenX);
01425 return ERROR_NT(status);
01426 }
01427
01428 status = check_name(conn, fname);
01429 if (!NT_STATUS_IS_OK(status)) {
01430 END_PROFILE(SMBopenX);
01431 return ERROR_NT(status);
01432 }
01433
01434 if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
01435 &access_mask,
01436 &share_mode,
01437 &create_disposition,
01438 &create_options)) {
01439 END_PROFILE(SMBopenX);
01440 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
01441 }
01442
01443 status = open_file_ntcreate(conn,fname,&sbuf,
01444 access_mask,
01445 share_mode,
01446 create_disposition,
01447 create_options,
01448 smb_attr,
01449 oplock_request,
01450 &smb_action, &fsp);
01451
01452 if (!NT_STATUS_IS_OK(status)) {
01453 END_PROFILE(SMBopenX);
01454 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01455
01456 return -1;
01457 }
01458 return ERROR_OPEN(status);
01459 }
01460
01461
01462
01463 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
01464 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
01465 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
01466 close_file(fsp,ERROR_CLOSE);
01467 END_PROFILE(SMBopenX);
01468 return ERROR_NT(NT_STATUS_DISK_FULL);
01469 }
01470 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
01471 if (retval < 0) {
01472 close_file(fsp,ERROR_CLOSE);
01473 END_PROFILE(SMBopenX);
01474 return ERROR_NT(NT_STATUS_DISK_FULL);
01475 }
01476 sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
01477 }
01478
01479 fattr = dos_mode(conn,fname,&sbuf);
01480 mtime = sbuf.st_mtime;
01481 if (fattr & aDIR) {
01482 close_file(fsp,ERROR_CLOSE);
01483 END_PROFILE(SMBopenX);
01484 return ERROR_DOS(ERRDOS,ERRnoaccess);
01485 }
01486
01487
01488
01489
01490
01491
01492 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
01493 smb_action |= EXTENDED_OPLOCK_GRANTED;
01494 }
01495
01496 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01497 smb_action |= EXTENDED_OPLOCK_GRANTED;
01498 }
01499
01500
01501
01502
01503
01504
01505 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
01506 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01507 }
01508
01509 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01510 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01511 }
01512
01513 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
01514 set_message(outbuf,19,0,True);
01515 } else {
01516 set_message(outbuf,15,0,True);
01517 }
01518 SSVAL(outbuf,smb_vwv2,fsp->fnum);
01519 SSVAL(outbuf,smb_vwv3,fattr);
01520 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
01521 srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
01522 } else {
01523 srv_put_dos_date3(outbuf,smb_vwv4,mtime);
01524 }
01525 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
01526 SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
01527 SSVAL(outbuf,smb_vwv11,smb_action);
01528
01529 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
01530 SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
01531 }
01532
01533 END_PROFILE(SMBopenX);
01534 return chain_reply(inbuf,outbuf,length,bufsize);
01535 }
01536
01537
01538
01539
01540
01541
01542 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
01543 {
01544 uint16 vuid = SVAL(inbuf,smb_uid);
01545 user_struct *vuser = get_valid_user_struct(vuid);
01546 START_PROFILE(SMBulogoffX);
01547
01548 if(vuser == 0)
01549 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
01550
01551
01552
01553 if ((vuser != 0) && (lp_security() != SEC_SHARE))
01554 file_close_user(vuid);
01555
01556 invalidate_vuid(vuid);
01557
01558 set_message(outbuf,2,0,True);
01559
01560 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
01561
01562 END_PROFILE(SMBulogoffX);
01563 return chain_reply(inbuf,outbuf,length,bufsize);
01564 }
01565
01566
01567
01568
01569
01570 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
01571 {
01572 pstring fname;
01573 int com;
01574 int outsize = 0;
01575 uint32 fattr = SVAL(inbuf,smb_vwv0);
01576 struct timespec ts[2];
01577 files_struct *fsp;
01578 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
01579 SMB_STRUCT_STAT sbuf;
01580 NTSTATUS status;
01581 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
01582 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
01583 uint32 create_disposition;
01584 uint32 create_options = 0;
01585
01586 START_PROFILE(SMBcreate);
01587
01588 com = SVAL(inbuf,smb_com);
01589
01590 ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1));
01591
01592 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
01593 if (!NT_STATUS_IS_OK(status)) {
01594 END_PROFILE(SMBcreate);
01595 return ERROR_NT(status);
01596 }
01597
01598 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
01599 if (!NT_STATUS_IS_OK(status)) {
01600 END_PROFILE(SMBcreate);
01601 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01602 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01603 }
01604 return ERROR_NT(status);
01605 }
01606
01607 status = unix_convert(conn, fname, False, NULL, &sbuf);
01608 if (!NT_STATUS_IS_OK(status)) {
01609 END_PROFILE(SMBcreate);
01610 return ERROR_NT(status);
01611 }
01612
01613 status = check_name(conn, fname);
01614 if (!NT_STATUS_IS_OK(status)) {
01615 END_PROFILE(SMBcreate);
01616 return ERROR_NT(status);
01617 }
01618
01619 if (fattr & aVOLID) {
01620 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
01621 }
01622
01623 if(com == SMBmknew) {
01624
01625 create_disposition = FILE_CREATE;
01626 } else {
01627
01628 create_disposition = FILE_OVERWRITE_IF;
01629 }
01630
01631
01632 status = open_file_ntcreate(conn,fname,&sbuf,
01633 access_mask,
01634 share_mode,
01635 create_disposition,
01636 create_options,
01637 fattr,
01638 oplock_request,
01639 NULL, &fsp);
01640
01641 if (!NT_STATUS_IS_OK(status)) {
01642 END_PROFILE(SMBcreate);
01643 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01644
01645 return -1;
01646 }
01647 return ERROR_OPEN(status);
01648 }
01649
01650 ts[0] = get_atimespec(&sbuf);
01651 file_ntimes(conn, fname, ts);
01652
01653 outsize = set_message(outbuf,1,0,True);
01654 SSVAL(outbuf,smb_vwv0,fsp->fnum);
01655
01656 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
01657 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01658 }
01659
01660 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01661 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01662 }
01663
01664 DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
01665 DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
01666
01667 END_PROFILE(SMBcreate);
01668 return(outsize);
01669 }
01670
01671
01672
01673
01674
01675 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
01676 {
01677 pstring fname;
01678 int outsize = 0;
01679 uint32 fattr = SVAL(inbuf,smb_vwv0);
01680 files_struct *fsp;
01681 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
01682 int tmpfd;
01683 SMB_STRUCT_STAT sbuf;
01684 char *p, *s;
01685 NTSTATUS status;
01686 unsigned int namelen;
01687
01688 START_PROFILE(SMBctemp);
01689
01690 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
01691 if (!NT_STATUS_IS_OK(status)) {
01692 END_PROFILE(SMBctemp);
01693 return ERROR_NT(status);
01694 }
01695 if (*fname) {
01696 pstrcat(fname,"/TMXXXXXX");
01697 } else {
01698 pstrcat(fname,"TMXXXXXX");
01699 }
01700
01701 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
01702 if (!NT_STATUS_IS_OK(status)) {
01703 END_PROFILE(SMBctemp);
01704 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01705 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01706 }
01707 return ERROR_NT(status);
01708 }
01709
01710 status = unix_convert(conn, fname, False, NULL, &sbuf);
01711 if (!NT_STATUS_IS_OK(status)) {
01712 END_PROFILE(SMBctemp);
01713 return ERROR_NT(status);
01714 }
01715
01716 status = check_name(conn, fname);
01717 if (!NT_STATUS_IS_OK(status)) {
01718 END_PROFILE(SMBctemp);
01719 return ERROR_NT(status);
01720 }
01721
01722 tmpfd = smb_mkstemp(fname);
01723 if (tmpfd == -1) {
01724 END_PROFILE(SMBctemp);
01725 return(UNIXERROR(ERRDOS,ERRnoaccess));
01726 }
01727
01728 SMB_VFS_STAT(conn,fname,&sbuf);
01729
01730
01731 status = open_file_ntcreate(conn,fname,&sbuf,
01732 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
01733 FILE_SHARE_READ|FILE_SHARE_WRITE,
01734 FILE_OPEN,
01735 0,
01736 fattr,
01737 oplock_request,
01738 NULL, &fsp);
01739
01740
01741 close(tmpfd);
01742
01743 if (!NT_STATUS_IS_OK(status)) {
01744 END_PROFILE(SMBctemp);
01745 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01746
01747 return -1;
01748 }
01749 return ERROR_OPEN(status);
01750 }
01751
01752 outsize = set_message(outbuf,1,0,True);
01753 SSVAL(outbuf,smb_vwv0,fsp->fnum);
01754
01755
01756 s = strrchr_m(fname, '/');
01757 if (!s) {
01758 s = fname;
01759 } else {
01760 s++;
01761 }
01762
01763 p = smb_buf(outbuf);
01764 #if 0
01765
01766
01767 SSVALS(p, 0, -1);
01768 #endif
01769 namelen = srvstr_push(outbuf, p, s, BUFFER_SIZE - (p - outbuf), STR_ASCII|STR_TERMINATE);
01770 p += namelen;
01771 outsize = set_message_end(outbuf, p);
01772
01773 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
01774 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01775 }
01776
01777 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01778 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
01779 }
01780
01781 DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
01782 DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
01783 (unsigned int)sbuf.st_mode ) );
01784
01785 END_PROFILE(SMBctemp);
01786 return(outsize);
01787 }
01788
01789
01790
01791
01792
01793 static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
01794 {
01795 files_struct *fsp;
01796 uint32 fmode;
01797 NTSTATUS status;
01798
01799 if (!CAN_WRITE(conn)) {
01800 return NT_STATUS_MEDIA_WRITE_PROTECTED;
01801 }
01802
01803 fmode = dos_mode(conn,fname,pst);
01804 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
01805 return NT_STATUS_NO_SUCH_FILE;
01806 }
01807
01808 if (S_ISDIR(pst->st_mode)) {
01809 return NT_STATUS_OK;
01810 }
01811
01812 status = open_file_ntcreate(conn, fname, pst,
01813 DELETE_ACCESS,
01814
01815 self_open ?
01816 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
01817 FILE_SHARE_READ|FILE_SHARE_WRITE,
01818 FILE_OPEN,
01819 0,
01820 FILE_ATTRIBUTE_NORMAL,
01821 0,
01822 NULL, &fsp);
01823
01824 if (!NT_STATUS_IS_OK(status)) {
01825 return status;
01826 }
01827 close_file(fsp,NORMAL_CLOSE);
01828 return NT_STATUS_OK;
01829 }
01830
01831
01832
01833
01834
01835 static NTSTATUS can_delete(connection_struct *conn, char *fname,
01836 uint32 dirtype, BOOL can_defer)
01837 {
01838 SMB_STRUCT_STAT sbuf;
01839 uint32 fattr;
01840 files_struct *fsp;
01841 uint32 dirtype_orig = dirtype;
01842 NTSTATUS status;
01843
01844 DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
01845
01846 if (!CAN_WRITE(conn)) {
01847 return NT_STATUS_MEDIA_WRITE_PROTECTED;
01848 }
01849
01850 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
01851 return map_nt_error_from_unix(errno);
01852 }
01853
01854 fattr = dos_mode(conn,fname,&sbuf);
01855
01856 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
01857 dirtype = aDIR|aARCH|aRONLY;
01858 }
01859
01860 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
01861 if (!dirtype) {
01862 return NT_STATUS_NO_SUCH_FILE;
01863 }
01864
01865 if (!dir_check_ftype(conn, fattr, dirtype)) {
01866 if (fattr & aDIR) {
01867 return NT_STATUS_FILE_IS_A_DIRECTORY;
01868 }
01869 return NT_STATUS_NO_SUCH_FILE;
01870 }
01871
01872 if (dirtype_orig & 0x8000) {
01873
01874 return NT_STATUS_NO_SUCH_FILE;
01875 }
01876
01877 #if 0
01878 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
01879 return NT_STATUS_FILE_IS_A_DIRECTORY;
01880 }
01881
01882 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
01883 return NT_STATUS_NO_SUCH_FILE;
01884 }
01885
01886 if (dirtype & 0xFF00) {
01887
01888 return NT_STATUS_NO_SUCH_FILE;
01889 }
01890
01891 dirtype &= 0xFF;
01892 if (!dirtype) {
01893 return NT_STATUS_NO_SUCH_FILE;
01894 }
01895
01896
01897 if (fattr & aDIR) {
01898 return NT_STATUS_FILE_IS_A_DIRECTORY;
01899 }
01900 #endif
01901
01902 #if 0
01903 else if (dirtype & aDIR)
01904 return NT_STATUS_OBJECT_NAME_INVALID;
01905 #endif
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919 if (!lp_delete_readonly(SNUM(conn))) {
01920 if (fattr & aRONLY) {
01921 return NT_STATUS_CANNOT_DELETE;
01922 }
01923 }
01924
01925
01926
01927
01928 status = open_file_ntcreate(conn, fname, &sbuf,
01929 DELETE_ACCESS,
01930 FILE_SHARE_NONE,
01931 FILE_OPEN,
01932 0,
01933 FILE_ATTRIBUTE_NORMAL,
01934 can_defer ? 0 : INTERNAL_OPEN_ONLY,
01935 NULL, &fsp);
01936
01937 if (NT_STATUS_IS_OK(status)) {
01938 close_file(fsp,NORMAL_CLOSE);
01939 }
01940 return status;
01941 }
01942
01943
01944
01945
01946
01947
01948 NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
01949 char *name, BOOL has_wild, BOOL can_defer)
01950 {
01951 pstring directory;
01952 pstring mask;
01953 char *p;
01954 int count=0;
01955 NTSTATUS status = NT_STATUS_OK;
01956 SMB_STRUCT_STAT sbuf;
01957
01958 *directory = *mask = 0;
01959
01960 status = unix_convert(conn, name, has_wild, NULL, &sbuf);
01961 if (!NT_STATUS_IS_OK(status)) {
01962 return status;
01963 }
01964
01965 p = strrchr_m(name,'/');
01966 if (!p) {
01967 pstrcpy(directory,".");
01968 pstrcpy(mask,name);
01969 } else {
01970 *p = 0;
01971 pstrcpy(directory,name);
01972 pstrcpy(mask,p+1);
01973 }
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984 if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
01985 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
01986
01987 if (!has_wild) {
01988 pstrcat(directory,"/");
01989 pstrcat(directory,mask);
01990 if (dirtype == 0) {
01991 dirtype = FILE_ATTRIBUTE_NORMAL;
01992 }
01993
01994 status = check_name(conn, directory);
01995 if (!NT_STATUS_IS_OK(status)) {
01996 return status;
01997 }
01998
01999 status = can_delete(conn,directory,dirtype,can_defer);
02000 if (!NT_STATUS_IS_OK(status)) {
02001 return status;
02002 }
02003
02004 if (SMB_VFS_UNLINK(conn,directory) == 0) {
02005 count++;
02006 notify_fname(conn, NOTIFY_ACTION_REMOVED,
02007 FILE_NOTIFY_CHANGE_FILE_NAME,
02008 directory);
02009 }
02010 } else {
02011 struct smb_Dir *dir_hnd = NULL;
02012 long offset = 0;
02013 const char *dname;
02014
02015 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
02016 return NT_STATUS_OBJECT_NAME_INVALID;
02017 }
02018
02019 if (strequal(mask,"????????.???")) {
02020 pstrcpy(mask,"*");
02021 }
02022
02023 status = check_name(conn, directory);
02024 if (!NT_STATUS_IS_OK(status)) {
02025 return status;
02026 }
02027
02028 dir_hnd = OpenDir(conn, directory, mask, dirtype);
02029 if (dir_hnd == NULL) {
02030 return map_nt_error_from_unix(errno);
02031 }
02032
02033
02034
02035
02036
02037
02038 status = NT_STATUS_NO_SUCH_FILE;
02039
02040 while ((dname = ReadDirName(dir_hnd, &offset))) {
02041 SMB_STRUCT_STAT st;
02042 pstring fname;
02043 pstrcpy(fname,dname);
02044
02045 if (!is_visible_file(conn, directory, dname, &st, True)) {
02046 continue;
02047 }
02048
02049
02050 if (fname[0] == '.') {
02051 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
02052 continue;
02053 }
02054 }
02055
02056 if(!mask_match(fname, mask, conn->case_sensitive)) {
02057 continue;
02058 }
02059
02060 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
02061
02062 status = check_name(conn, fname);
02063 if (!NT_STATUS_IS_OK(status)) {
02064 CloseDir(dir_hnd);
02065 return status;
02066 }
02067
02068 status = can_delete(conn, fname, dirtype, can_defer);
02069 if (!NT_STATUS_IS_OK(status)) {
02070 continue;
02071 }
02072 if (SMB_VFS_UNLINK(conn,fname) == 0) {
02073 count++;
02074 DEBUG(3,("unlink_internals: successful unlink "
02075 "[%s]\n",fname));
02076 notify_fname(conn, NOTIFY_ACTION_REMOVED,
02077 FILE_NOTIFY_CHANGE_FILE_NAME,
02078 fname);
02079 }
02080
02081 }
02082 CloseDir(dir_hnd);
02083 }
02084
02085 if (count == 0 && NT_STATUS_IS_OK(status)) {
02086 status = map_nt_error_from_unix(errno);
02087 }
02088
02089 return status;
02090 }
02091
02092
02093
02094
02095
02096 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
02097 int dum_buffsize)
02098 {
02099 int outsize = 0;
02100 pstring name;
02101 uint32 dirtype;
02102 NTSTATUS status;
02103 BOOL path_contains_wcard = False;
02104
02105 START_PROFILE(SMBunlink);
02106
02107 dirtype = SVAL(inbuf,smb_vwv0);
02108
02109 srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
02110 if (!NT_STATUS_IS_OK(status)) {
02111 END_PROFILE(SMBunlink);
02112 return ERROR_NT(status);
02113 }
02114
02115 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
02116 if (!NT_STATUS_IS_OK(status)) {
02117 END_PROFILE(SMBunlink);
02118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
02119 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
02120 }
02121 return ERROR_NT(status);
02122 }
02123
02124 DEBUG(3,("reply_unlink : %s\n",name));
02125
02126 status = unlink_internals(conn, dirtype, name, path_contains_wcard,
02127 True);
02128 if (!NT_STATUS_IS_OK(status)) {
02129 END_PROFILE(SMBunlink);
02130 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
02131
02132 return -1;
02133 }
02134 return ERROR_NT(status);
02135 }
02136
02137 outsize = set_message(outbuf,0,0,False);
02138
02139 END_PROFILE(SMBunlink);
02140 return outsize;
02141 }
02142
02143
02144
02145
02146
02147 static void fail_readraw(void)
02148 {
02149 pstring errstr;
02150 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
02151 strerror(errno) );
02152 exit_server_cleanly(errstr);
02153 }
02154
02155 #if defined(WITH_SENDFILE)
02156
02157
02158
02159
02160 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
02161 {
02162 ssize_t ret=0;
02163
02164
02165 if (nread > bufsize) {
02166 fail_readraw();
02167 }
02168
02169 if (nread > 0) {
02170 ret = read_file(fsp,buf,startpos,nread);
02171 if (ret == -1) {
02172 return -1;
02173 }
02174 }
02175
02176
02177 if (ret < nread) {
02178 memset(buf, '\0', nread - ret);
02179 }
02180
02181 if (write_data(smbd_server_fd(),buf,nread) != nread) {
02182 return -1;
02183 }
02184
02185 return (ssize_t)nread;
02186 }
02187 #endif
02188
02189
02190
02191
02192
02193 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
02194 ssize_t mincount, char *outbuf, int out_buffsize)
02195 {
02196 ssize_t ret=0;
02197
02198 #if defined(WITH_SENDFILE)
02199
02200
02201
02202
02203
02204
02205
02206 if ( (chain_size == 0) && (nread > 0) &&
02207 (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
02208 DATA_BLOB header;
02209
02210 _smb_setlen(outbuf,nread);
02211 header.data = (uint8 *)outbuf;
02212 header.length = 4;
02213 header.free = NULL;
02214
02215 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
02216
02217 if (errno == ENOSYS) {
02218 goto normal_readbraw;
02219 }
02220
02221
02222
02223
02224
02225
02226 if (errno == EINTR) {
02227
02228 set_use_sendfile(SNUM(conn), False);
02229 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
02230
02231 if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
02232 DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
02233 fsp->fsp_name, strerror(errno) ));
02234 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
02235 }
02236 return;
02237 }
02238
02239 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
02240 fsp->fsp_name, strerror(errno) ));
02241 exit_server_cleanly("send_file_readbraw sendfile failed");
02242 }
02243
02244 return;
02245 }
02246
02247 normal_readbraw:
02248
02249 #endif
02250
02251 if (nread > 0) {
02252 ret = read_file(fsp,outbuf+4,startpos,nread);
02253 #if 0
02254 if (ret < mincount)
02255 ret = 0;
02256 #else
02257 if (ret < nread)
02258 ret = 0;
02259 #endif
02260 }
02261
02262 _smb_setlen(outbuf,ret);
02263 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
02264 fail_readraw();
02265 }
02266
02267
02268
02269
02270
02271 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
02272 {
02273 ssize_t maxcount,mincount;
02274 size_t nread = 0;
02275 SMB_OFF_T startpos;
02276 char *header = outbuf;
02277 files_struct *fsp;
02278 START_PROFILE(SMBreadbraw);
02279
02280 if (srv_is_signing_active()) {
02281 exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
02282 }
02283
02284
02285
02286
02287
02288
02289
02290 fsp = file_fsp(inbuf,smb_vwv0);
02291
02292 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
02293
02294
02295
02296 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
02297 _smb_setlen(header,0);
02298 if (write_data(smbd_server_fd(),header,4) != 4)
02299 fail_readraw();
02300 END_PROFILE(SMBreadbraw);
02301 return(-1);
02302 }
02303
02304 CHECK_FSP(fsp,conn);
02305
02306 flush_write_cache(fsp, READRAW_FLUSH);
02307
02308 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
02309 if(CVAL(inbuf,smb_wct) == 10) {
02310
02311
02312
02313 #ifdef LARGE_SMB_OFF_T
02314
02315 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
02316
02317 #else
02318
02319
02320
02321
02322
02323 if(IVAL(inbuf,smb_vwv8) != 0) {
02324 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
02325 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
02326 _smb_setlen(header,0);
02327 if (write_data(smbd_server_fd(),header,4) != 4)
02328 fail_readraw();
02329 END_PROFILE(SMBreadbraw);
02330 return(-1);
02331 }
02332
02333 #endif
02334
02335 if(startpos < 0) {
02336 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
02337 _smb_setlen(header,0);
02338 if (write_data(smbd_server_fd(),header,4) != 4)
02339 fail_readraw();
02340 END_PROFILE(SMBreadbraw);
02341 return(-1);
02342 }
02343 }
02344 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
02345 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
02346
02347
02348 maxcount = MIN(65535,maxcount);
02349
02350 if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
02351 SMB_STRUCT_STAT st;
02352 SMB_OFF_T size = 0;
02353
02354 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
02355 size = st.st_size;
02356 }
02357
02358 if (startpos >= size) {
02359 nread = 0;
02360 } else {
02361 nread = MIN(maxcount,(size - startpos));
02362 }
02363 }
02364
02365 #if 0
02366 if (nread < mincount)
02367 nread = 0;
02368 #endif
02369
02370 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
02371 (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
02372
02373 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
02374
02375 DEBUG(5,("readbraw finished\n"));
02376 END_PROFILE(SMBreadbraw);
02377 return -1;
02378 }
02379
02380 #undef DBGC_CLASS
02381 #define DBGC_CLASS DBGC_LOCKING
02382
02383
02384
02385
02386
02387 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
02388 {
02389 ssize_t nread = -1;
02390 char *data;
02391 int outsize = 0;
02392 SMB_OFF_T startpos;
02393 size_t numtoread;
02394 NTSTATUS status;
02395 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
02396 struct byte_range_lock *br_lck = NULL;
02397 START_PROFILE(SMBlockread);
02398
02399 CHECK_FSP(fsp,conn);
02400 if (!CHECK_READ(fsp,inbuf)) {
02401 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02402 }
02403
02404 release_level_2_oplocks_on_change(fsp);
02405
02406 numtoread = SVAL(inbuf,smb_vwv1);
02407 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
02408
02409 outsize = set_message(outbuf,5,3,True);
02410 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
02411 data = smb_buf(outbuf) + 3;
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421 br_lck = do_lock(fsp,
02422 (uint32)SVAL(inbuf,smb_pid),
02423 (SMB_BIG_UINT)numtoread,
02424 (SMB_BIG_UINT)startpos,
02425 WRITE_LOCK,
02426 WINDOWS_LOCK,
02427 False,
02428 &status,
02429 NULL);
02430 TALLOC_FREE(br_lck);
02431
02432 if (NT_STATUS_V(status)) {
02433 END_PROFILE(SMBlockread);
02434 return ERROR_NT(status);
02435 }
02436
02437
02438
02439
02440
02441 if (numtoread > max_recv) {
02442 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
02443 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
02444 (unsigned int)numtoread, (unsigned int)max_recv ));
02445 numtoread = MIN(numtoread,max_recv);
02446 }
02447 nread = read_file(fsp,data,startpos,numtoread);
02448
02449 if (nread < 0) {
02450 END_PROFILE(SMBlockread);
02451 return(UNIXERROR(ERRDOS,ERRnoaccess));
02452 }
02453
02454 outsize += nread;
02455 SSVAL(outbuf,smb_vwv0,nread);
02456 SSVAL(outbuf,smb_vwv5,nread+3);
02457 SSVAL(smb_buf(outbuf),1,nread);
02458
02459 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
02460 fsp->fnum, (int)numtoread, (int)nread));
02461
02462 END_PROFILE(SMBlockread);
02463 return(outsize);
02464 }
02465
02466 #undef DBGC_CLASS
02467 #define DBGC_CLASS DBGC_ALL
02468
02469
02470
02471
02472
02473 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
02474 {
02475 size_t numtoread;
02476 ssize_t nread = 0;
02477 char *data;
02478 SMB_OFF_T startpos;
02479 int outsize = 0;
02480 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
02481 START_PROFILE(SMBread);
02482
02483 CHECK_FSP(fsp,conn);
02484 if (!CHECK_READ(fsp,inbuf)) {
02485 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02486 }
02487
02488 numtoread = SVAL(inbuf,smb_vwv1);
02489 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
02490
02491 outsize = set_message(outbuf,5,3,True);
02492 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
02493
02494
02495
02496 if (numtoread > max_recv) {
02497 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
02498 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
02499 (unsigned int)numtoread, (unsigned int)max_recv ));
02500 numtoread = MIN(numtoread,max_recv);
02501 }
02502
02503 data = smb_buf(outbuf) + 3;
02504
02505 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
02506 END_PROFILE(SMBread);
02507 return ERROR_DOS(ERRDOS,ERRlock);
02508 }
02509
02510 if (numtoread > 0)
02511 nread = read_file(fsp,data,startpos,numtoread);
02512
02513 if (nread < 0) {
02514 END_PROFILE(SMBread);
02515 return(UNIXERROR(ERRDOS,ERRnoaccess));
02516 }
02517
02518 outsize += nread;
02519 SSVAL(outbuf,smb_vwv0,nread);
02520 SSVAL(outbuf,smb_vwv5,nread+3);
02521 SCVAL(smb_buf(outbuf),0,1);
02522 SSVAL(smb_buf(outbuf),1,nread);
02523
02524 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
02525 fsp->fnum, (int)numtoread, (int)nread ) );
02526
02527 END_PROFILE(SMBread);
02528 return(outsize);
02529 }
02530
02531
02532
02533
02534
02535 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
02536 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
02537 {
02538 int outsize = 0;
02539 ssize_t nread = -1;
02540 char *data = smb_buf(outbuf);
02541
02542 #if defined(WITH_SENDFILE)
02543
02544
02545
02546
02547
02548
02549 if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
02550 lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
02551 SMB_STRUCT_STAT sbuf;
02552 DATA_BLOB header;
02553
02554 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
02555 return(UNIXERROR(ERRDOS,ERRnoaccess));
02556
02557 if (startpos > sbuf.st_size)
02558 goto normal_read;
02559
02560 if (smb_maxcnt > (sbuf.st_size - startpos))
02561 smb_maxcnt = (sbuf.st_size - startpos);
02562
02563 if (smb_maxcnt == 0)
02564 goto normal_read;
02565
02566
02567
02568
02569
02570
02571
02572 SSVAL(outbuf,smb_vwv2,0xFFFF);
02573 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
02574 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
02575 SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
02576 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
02577 SCVAL(outbuf,smb_vwv0,0xFF);
02578 set_message(outbuf,12,smb_maxcnt,False);
02579 header.data = (uint8 *)outbuf;
02580 header.length = data - outbuf;
02581 header.free = NULL;
02582
02583 if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
02584
02585 if (errno == ENOSYS) {
02586 goto normal_read;
02587 }
02588
02589
02590
02591
02592
02593
02594
02595 if (errno == EINTR) {
02596
02597 set_use_sendfile(SNUM(conn), False);
02598 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
02599
02600 if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
02601 len_outbuf - (data-outbuf))) == -1) {
02602 DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
02603 fsp->fsp_name, strerror(errno) ));
02604 exit_server_cleanly("send_file_readX: fake_sendfile failed");
02605 }
02606 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
02607 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
02608
02609 return -1;
02610 }
02611
02612 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
02613 fsp->fsp_name, strerror(errno) ));
02614 exit_server_cleanly("send_file_readX sendfile failed");
02615 }
02616
02617 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
02618 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
02619
02620 return -1;
02621 }
02622
02623 normal_read:
02624
02625 #endif
02626
02627 nread = read_file(fsp,data,startpos,smb_maxcnt);
02628
02629 if (nread < 0) {
02630 return(UNIXERROR(ERRDOS,ERRnoaccess));
02631 }
02632
02633 outsize = set_message(outbuf,12,nread,False);
02634 SSVAL(outbuf,smb_vwv2,0xFFFF);
02635 SSVAL(outbuf,smb_vwv5,nread);
02636 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
02637 SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
02638 SSVAL(smb_buf(outbuf),-2,nread);
02639
02640 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
02641 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
02642
02643
02644 return outsize;
02645 }
02646
02647
02648
02649
02650
02651 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
02652 {
02653 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
02654 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
02655 ssize_t nread = -1;
02656 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
02657 #if 0
02658 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
02659 #endif
02660
02661 START_PROFILE(SMBreadX);
02662
02663
02664 if (IS_IPC(conn)) {
02665 END_PROFILE(SMBreadX);
02666 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
02667 }
02668
02669 CHECK_FSP(fsp,conn);
02670 if (!CHECK_READ(fsp,inbuf)) {
02671 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02672 }
02673
02674 set_message(outbuf,12,0,True);
02675
02676 if (global_client_caps & CAP_LARGE_READX) {
02677 if (SVAL(inbuf,smb_vwv7) == 1) {
02678 smb_maxcnt |= (1<<16);
02679 }
02680 if (smb_maxcnt > BUFFER_SIZE) {
02681 DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
02682 (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
02683 END_PROFILE(SMBreadX);
02684 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02685 }
02686 }
02687
02688 if(CVAL(inbuf,smb_wct) == 12) {
02689 #ifdef LARGE_SMB_OFF_T
02690
02691
02692
02693 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
02694
02695 #else
02696
02697
02698
02699
02700
02701 if(IVAL(inbuf,smb_vwv10) != 0) {
02702 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
02703 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
02704 END_PROFILE(SMBreadX);
02705 return ERROR_DOS(ERRDOS,ERRbadaccess);
02706 }
02707
02708 #endif
02709
02710 }
02711
02712 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
02713 END_PROFILE(SMBreadX);
02714 return ERROR_DOS(ERRDOS,ERRlock);
02715 }
02716
02717 if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
02718 END_PROFILE(SMBreadX);
02719 return -1;
02720 }
02721
02722 nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
02723
02724 if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
02725 nread = chain_reply(inbuf,outbuf,length,bufsize);
02726 }
02727
02728 END_PROFILE(SMBreadX);
02729 return nread;
02730 }
02731
02732
02733
02734
02735
02736 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
02737 {
02738 ssize_t nwritten=0;
02739 ssize_t total_written=0;
02740 size_t numtowrite=0;
02741 size_t tcount;
02742 SMB_OFF_T startpos;
02743 char *data=NULL;
02744 BOOL write_through;
02745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
02746 int outsize = 0;
02747 NTSTATUS status;
02748 START_PROFILE(SMBwritebraw);
02749
02750 if (srv_is_signing_active()) {
02751 exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
02752 }
02753
02754 CHECK_FSP(fsp,conn);
02755 if (!CHECK_WRITE(fsp)) {
02756 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02757 }
02758
02759 tcount = IVAL(inbuf,smb_vwv1);
02760 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
02761 write_through = BITSETW(inbuf+smb_vwv7,0);
02762
02763
02764
02765
02766 if(Protocol <= PROTOCOL_COREPLUS) {
02767 numtowrite = SVAL(smb_buf(inbuf),-2);
02768 data = smb_buf(inbuf);
02769 } else {
02770 numtowrite = SVAL(inbuf,smb_vwv10);
02771 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
02772 }
02773
02774
02775 SCVAL(inbuf,smb_com,SMBwritec);
02776 SCVAL(outbuf,smb_com,SMBwritec);
02777
02778 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
02779 END_PROFILE(SMBwritebraw);
02780 return(ERROR_DOS(ERRDOS,ERRlock));
02781 }
02782
02783 if (numtowrite>0)
02784 nwritten = write_file(fsp,data,startpos,numtowrite);
02785
02786 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
02787 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
02788
02789 if (nwritten < (ssize_t)numtowrite) {
02790 END_PROFILE(SMBwritebraw);
02791 return(UNIXERROR(ERRHRD,ERRdiskfull));
02792 }
02793
02794 total_written = nwritten;
02795
02796
02797 SCVAL(outbuf,smb_com,SMBwritebraw);
02798 SSVALS(outbuf,smb_vwv0,-1);
02799 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
02800 show_msg(outbuf);
02801 if (!send_smb(smbd_server_fd(),outbuf))
02802 exit_server_cleanly("reply_writebraw: send_smb failed.");
02803
02804
02805 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
02806 exit_server_cleanly("secondary writebraw failed");
02807 }
02808
02809
02810 numtowrite = smb_len(inbuf);
02811
02812
02813 outsize = set_message(outbuf,1,0,True);
02814 SCVAL(outbuf,smb_com,SMBwritec);
02815
02816 if (numtowrite != 0) {
02817
02818 if (numtowrite > BUFFER_SIZE) {
02819 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
02820 (unsigned int)numtowrite ));
02821 exit_server_cleanly("secondary writebraw failed");
02822 }
02823
02824 if (tcount > nwritten+numtowrite) {
02825 DEBUG(3,("Client overestimated the write %d %d %d\n",
02826 (int)tcount,(int)nwritten,(int)numtowrite));
02827 }
02828
02829 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
02830 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
02831 strerror(errno) ));
02832 exit_server_cleanly("secondary writebraw failed");
02833 }
02834
02835 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
02836 if (nwritten == -1) {
02837 END_PROFILE(SMBwritebraw);
02838 return(UNIXERROR(ERRHRD,ERRdiskfull));
02839 }
02840
02841 if (nwritten < (ssize_t)numtowrite) {
02842 SCVAL(outbuf,smb_rcls,ERRHRD);
02843 SSVAL(outbuf,smb_err,ERRdiskfull);
02844 }
02845
02846 if (nwritten > 0)
02847 total_written += nwritten;
02848 }
02849
02850 SSVAL(outbuf,smb_vwv0,total_written);
02851
02852 status = sync_file(conn, fsp, write_through);
02853 if (!NT_STATUS_IS_OK(status)) {
02854 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
02855 fsp->fsp_name, nt_errstr(status) ));
02856 END_PROFILE(SMBwritebraw);
02857 return ERROR_NT(status);
02858 }
02859
02860 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
02861 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
02862
02863
02864 END_PROFILE(SMBwritebraw);
02865 if (!write_through && total_written==tcount) {
02866
02867 #if RABBIT_PELLET_FIX
02868
02869
02870
02871
02872 if (!send_keepalive(smbd_server_fd()))
02873 exit_server_cleanly("reply_writebraw: send of keepalive failed");
02874 #endif
02875 return(-1);
02876 }
02877
02878 return(outsize);
02879 }
02880
02881 #undef DBGC_CLASS
02882 #define DBGC_CLASS DBGC_LOCKING
02883
02884
02885
02886
02887
02888 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
02889 int size, int dum_buffsize)
02890 {
02891 ssize_t nwritten = -1;
02892 size_t numtowrite;
02893 SMB_OFF_T startpos;
02894 char *data;
02895 NTSTATUS status = NT_STATUS_OK;
02896 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
02897 int outsize = 0;
02898 START_PROFILE(SMBwriteunlock);
02899
02900 CHECK_FSP(fsp,conn);
02901 if (!CHECK_WRITE(fsp)) {
02902 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02903 }
02904
02905 numtowrite = SVAL(inbuf,smb_vwv1);
02906 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
02907 data = smb_buf(inbuf) + 3;
02908
02909 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
02910 END_PROFILE(SMBwriteunlock);
02911 return ERROR_DOS(ERRDOS,ERRlock);
02912 }
02913
02914
02915
02916
02917 if(numtowrite == 0) {
02918 nwritten = 0;
02919 } else {
02920 nwritten = write_file(fsp,data,startpos,numtowrite);
02921 }
02922
02923 status = sync_file(conn, fsp, False );
02924 if (!NT_STATUS_IS_OK(status)) {
02925 END_PROFILE(SMBwriteunlock);
02926 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
02927 fsp->fsp_name, nt_errstr(status) ));
02928 return ERROR_NT(status);
02929 }
02930
02931 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
02932 END_PROFILE(SMBwriteunlock);
02933 return(UNIXERROR(ERRHRD,ERRdiskfull));
02934 }
02935
02936 if (numtowrite) {
02937 status = do_unlock(fsp,
02938 (uint32)SVAL(inbuf,smb_pid),
02939 (SMB_BIG_UINT)numtowrite,
02940 (SMB_BIG_UINT)startpos,
02941 WINDOWS_LOCK);
02942
02943 if (NT_STATUS_V(status)) {
02944 END_PROFILE(SMBwriteunlock);
02945 return ERROR_NT(status);
02946 }
02947 }
02948
02949 outsize = set_message(outbuf,1,0,True);
02950
02951 SSVAL(outbuf,smb_vwv0,nwritten);
02952
02953 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
02954 fsp->fnum, (int)numtowrite, (int)nwritten));
02955
02956 END_PROFILE(SMBwriteunlock);
02957 return outsize;
02958 }
02959
02960 #undef DBGC_CLASS
02961 #define DBGC_CLASS DBGC_ALL
02962
02963
02964
02965
02966
02967 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
02968 {
02969 size_t numtowrite;
02970 ssize_t nwritten = -1;
02971 SMB_OFF_T startpos;
02972 char *data;
02973 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
02974 int outsize = 0;
02975 NTSTATUS status;
02976 START_PROFILE(SMBwrite);
02977
02978
02979 if (IS_IPC(conn)) {
02980 END_PROFILE(SMBwrite);
02981 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
02982 }
02983
02984 CHECK_FSP(fsp,conn);
02985 if (!CHECK_WRITE(fsp)) {
02986 END_PROFILE(SMBwrite);
02987 return(ERROR_DOS(ERRDOS,ERRbadaccess));
02988 }
02989
02990 numtowrite = SVAL(inbuf,smb_vwv1);
02991 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
02992 data = smb_buf(inbuf) + 3;
02993
02994 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
02995 END_PROFILE(SMBwrite);
02996 return ERROR_DOS(ERRDOS,ERRlock);
02997 }
02998
02999
03000
03001
03002
03003
03004
03005 if(numtowrite == 0) {
03006
03007
03008
03009 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
03010 if (nwritten < 0) {
03011 END_PROFILE(SMBwrite);
03012 return ERROR_NT(NT_STATUS_DISK_FULL);
03013 }
03014 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
03015 if (nwritten < 0) {
03016 END_PROFILE(SMBwrite);
03017 return ERROR_NT(NT_STATUS_DISK_FULL);
03018 }
03019 } else
03020 nwritten = write_file(fsp,data,startpos,numtowrite);
03021
03022 status = sync_file(conn, fsp, False);
03023 if (!NT_STATUS_IS_OK(status)) {
03024 END_PROFILE(SMBwrite);
03025 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
03026 fsp->fsp_name, nt_errstr(status) ));
03027 return ERROR_NT(status);
03028 }
03029
03030 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
03031 END_PROFILE(SMBwrite);
03032 return(UNIXERROR(ERRHRD,ERRdiskfull));
03033 }
03034
03035 outsize = set_message(outbuf,1,0,True);
03036
03037 SSVAL(outbuf,smb_vwv0,nwritten);
03038
03039 if (nwritten < (ssize_t)numtowrite) {
03040 SCVAL(outbuf,smb_rcls,ERRHRD);
03041 SSVAL(outbuf,smb_err,ERRdiskfull);
03042 }
03043
03044 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
03045
03046 END_PROFILE(SMBwrite);
03047 return(outsize);
03048 }
03049
03050
03051
03052
03053
03054 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
03055 {
03056 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
03057 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
03058 size_t numtowrite = SVAL(inbuf,smb_vwv10);
03059 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
03060 ssize_t nwritten = -1;
03061 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
03062 unsigned int smblen = smb_len(inbuf);
03063 char *data;
03064 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
03065 NTSTATUS status;
03066 START_PROFILE(SMBwriteX);
03067
03068
03069 if (IS_IPC(conn)) {
03070 END_PROFILE(SMBwriteX);
03071 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
03072 }
03073
03074 CHECK_FSP(fsp,conn);
03075 if (!CHECK_WRITE(fsp)) {
03076 return(ERROR_DOS(ERRDOS,ERRbadaccess));
03077 }
03078
03079 set_message(outbuf,6,0,True);
03080
03081
03082 if (large_writeX) {
03083 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
03084 }
03085
03086 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
03087 END_PROFILE(SMBwriteX);
03088 return ERROR_DOS(ERRDOS,ERRbadmem);
03089 }
03090
03091 data = smb_base(inbuf) + smb_doff;
03092
03093 if(CVAL(inbuf,smb_wct) == 14) {
03094 #ifdef LARGE_SMB_OFF_T
03095
03096
03097
03098 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
03099
03100 #else
03101
03102
03103
03104
03105
03106 if(IVAL(inbuf,smb_vwv12) != 0) {
03107 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
03108 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
03109 END_PROFILE(SMBwriteX);
03110 return ERROR_DOS(ERRDOS,ERRbadaccess);
03111 }
03112
03113 #endif
03114 }
03115
03116 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
03117 END_PROFILE(SMBwriteX);
03118 return ERROR_DOS(ERRDOS,ERRlock);
03119 }
03120
03121
03122
03123
03124
03125
03126 if(numtowrite == 0) {
03127 nwritten = 0;
03128 } else {
03129
03130 if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
03131 fsp,data,startpos,numtowrite)) {
03132 END_PROFILE(SMBwriteX);
03133 return -1;
03134 }
03135
03136 nwritten = write_file(fsp,data,startpos,numtowrite);
03137 }
03138
03139 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
03140 END_PROFILE(SMBwriteX);
03141 return(UNIXERROR(ERRHRD,ERRdiskfull));
03142 }
03143
03144 SSVAL(outbuf,smb_vwv2,nwritten);
03145 if (large_writeX)
03146 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
03147
03148 if (nwritten < (ssize_t)numtowrite) {
03149 SCVAL(outbuf,smb_rcls,ERRHRD);
03150 SSVAL(outbuf,smb_err,ERRdiskfull);
03151 }
03152
03153 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
03154 fsp->fnum, (int)numtowrite, (int)nwritten));
03155
03156 status = sync_file(conn, fsp, write_through);
03157 if (!NT_STATUS_IS_OK(status)) {
03158 END_PROFILE(SMBwriteX);
03159 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
03160 fsp->fsp_name, nt_errstr(status) ));
03161 return ERROR_NT(status);
03162 }
03163
03164 END_PROFILE(SMBwriteX);
03165 return chain_reply(inbuf,outbuf,length,bufsize);
03166 }
03167
03168
03169
03170
03171
03172 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
03173 {
03174 SMB_OFF_T startpos;
03175 SMB_OFF_T res= -1;
03176 int mode,umode;
03177 int outsize = 0;
03178 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03179 START_PROFILE(SMBlseek);
03180
03181 CHECK_FSP(fsp,conn);
03182
03183 flush_write_cache(fsp, SEEK_FLUSH);
03184
03185 mode = SVAL(inbuf,smb_vwv1) & 3;
03186
03187 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
03188
03189 switch (mode) {
03190 case 0:
03191 umode = SEEK_SET;
03192 res = startpos;
03193 break;
03194 case 1:
03195 umode = SEEK_CUR;
03196 res = fsp->fh->pos + startpos;
03197 break;
03198 case 2:
03199 umode = SEEK_END;
03200 break;
03201 default:
03202 umode = SEEK_SET;
03203 res = startpos;
03204 break;
03205 }
03206
03207 if (umode == SEEK_END) {
03208 if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
03209 if(errno == EINVAL) {
03210 SMB_OFF_T current_pos = startpos;
03211 SMB_STRUCT_STAT sbuf;
03212
03213 if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
03214 END_PROFILE(SMBlseek);
03215 return(UNIXERROR(ERRDOS,ERRnoaccess));
03216 }
03217
03218 current_pos += sbuf.st_size;
03219 if(current_pos < 0)
03220 res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
03221 }
03222 }
03223
03224 if(res == -1) {
03225 END_PROFILE(SMBlseek);
03226 return(UNIXERROR(ERRDOS,ERRnoaccess));
03227 }
03228 }
03229
03230 fsp->fh->pos = res;
03231
03232 outsize = set_message(outbuf,2,0,True);
03233 SIVAL(outbuf,smb_vwv0,res);
03234
03235 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
03236 fsp->fnum, (double)startpos, (double)res, mode));
03237
03238 END_PROFILE(SMBlseek);
03239 return(outsize);
03240 }
03241
03242
03243
03244
03245
03246 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
03247 {
03248 int outsize = set_message(outbuf,0,0,False);
03249 uint16 fnum = SVAL(inbuf,smb_vwv0);
03250 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03251 START_PROFILE(SMBflush);
03252
03253 if (fnum != 0xFFFF)
03254 CHECK_FSP(fsp,conn);
03255
03256 if (!fsp) {
03257 file_sync_all(conn);
03258 } else {
03259 NTSTATUS status = sync_file(conn, fsp, True);
03260 if (!NT_STATUS_IS_OK(status)) {
03261 END_PROFILE(SMBflush);
03262 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
03263 fsp->fsp_name, nt_errstr(status) ));
03264 return ERROR_NT(status);
03265 }
03266 }
03267
03268 DEBUG(3,("flush\n"));
03269 END_PROFILE(SMBflush);
03270 return(outsize);
03271 }
03272
03273
03274
03275
03276
03277
03278 int reply_exit(connection_struct *conn,
03279 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03280 {
03281 int outsize;
03282 START_PROFILE(SMBexit);
03283
03284 file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
03285
03286 outsize = set_message(outbuf,0,0,False);
03287
03288 DEBUG(3,("exit\n"));
03289
03290 END_PROFILE(SMBexit);
03291 return(outsize);
03292 }
03293
03294
03295
03296
03297
03298 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
03299 int dum_buffsize)
03300 {
03301 NTSTATUS status = NT_STATUS_OK;
03302 int outsize = 0;
03303 files_struct *fsp = NULL;
03304 START_PROFILE(SMBclose);
03305
03306 outsize = set_message(outbuf,0,0,False);
03307
03308
03309 if (IS_IPC(conn)) {
03310 END_PROFILE(SMBclose);
03311 return reply_pipe_close(conn, inbuf,outbuf);
03312 }
03313
03314 fsp = file_fsp(inbuf,smb_vwv0);
03315
03316
03317
03318
03319
03320 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
03321 END_PROFILE(SMBclose);
03322 return ERROR_DOS(ERRDOS,ERRbadfid);
03323 }
03324
03325 if(fsp->is_directory) {
03326
03327
03328
03329 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
03330 status = close_file(fsp,NORMAL_CLOSE);
03331 } else {
03332
03333
03334
03335
03336 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
03337 fsp->fh->fd, fsp->fnum,
03338 conn->num_files_open));
03339
03340
03341
03342
03343
03344 fsp_set_pending_modtime(fsp,
03345 convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
03346
03347
03348
03349
03350
03351
03352
03353 status = close_file(fsp,NORMAL_CLOSE);
03354 }
03355
03356 if(!NT_STATUS_IS_OK(status)) {
03357 END_PROFILE(SMBclose);
03358 return ERROR_NT(status);
03359 }
03360
03361 END_PROFILE(SMBclose);
03362 return(outsize);
03363 }
03364
03365
03366
03367
03368
03369 int reply_writeclose(connection_struct *conn,
03370 char *inbuf,char *outbuf, int size, int dum_buffsize)
03371 {
03372 size_t numtowrite;
03373 ssize_t nwritten = -1;
03374 int outsize = 0;
03375 NTSTATUS close_status = NT_STATUS_OK;
03376 SMB_OFF_T startpos;
03377 char *data;
03378 struct timespec mtime;
03379 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03380 START_PROFILE(SMBwriteclose);
03381
03382 CHECK_FSP(fsp,conn);
03383 if (!CHECK_WRITE(fsp)) {
03384 return(ERROR_DOS(ERRDOS,ERRbadaccess));
03385 }
03386
03387 numtowrite = SVAL(inbuf,smb_vwv1);
03388 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
03389 mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
03390 data = smb_buf(inbuf) + 1;
03391
03392 if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
03393 END_PROFILE(SMBwriteclose);
03394 return ERROR_DOS(ERRDOS,ERRlock);
03395 }
03396
03397 nwritten = write_file(fsp,data,startpos,numtowrite);
03398
03399 set_filetime(conn, fsp->fsp_name, mtime);
03400
03401
03402
03403
03404
03405
03406 if (numtowrite) {
03407 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
03408 fsp->fsp_name ));
03409 close_status = close_file(fsp,NORMAL_CLOSE);
03410 }
03411
03412 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
03413 fsp->fnum, (int)numtowrite, (int)nwritten,
03414 conn->num_files_open));
03415
03416 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
03417 END_PROFILE(SMBwriteclose);
03418 return(UNIXERROR(ERRHRD,ERRdiskfull));
03419 }
03420
03421 if(!NT_STATUS_IS_OK(close_status)) {
03422 END_PROFILE(SMBwriteclose);
03423 return ERROR_NT(close_status);
03424 }
03425
03426 outsize = set_message(outbuf,1,0,True);
03427
03428 SSVAL(outbuf,smb_vwv0,nwritten);
03429 END_PROFILE(SMBwriteclose);
03430 return(outsize);
03431 }
03432
03433 #undef DBGC_CLASS
03434 #define DBGC_CLASS DBGC_LOCKING
03435
03436
03437
03438
03439
03440 int reply_lock(connection_struct *conn,
03441 char *inbuf,char *outbuf, int length, int dum_buffsize)
03442 {
03443 int outsize = set_message(outbuf,0,0,False);
03444 SMB_BIG_UINT count,offset;
03445 NTSTATUS status;
03446 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03447 struct byte_range_lock *br_lck = NULL;
03448
03449 START_PROFILE(SMBlock);
03450
03451 CHECK_FSP(fsp,conn);
03452
03453 release_level_2_oplocks_on_change(fsp);
03454
03455 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
03456 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
03457
03458 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
03459 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
03460
03461 br_lck = do_lock(fsp,
03462 (uint32)SVAL(inbuf,smb_pid),
03463 count,
03464 offset,
03465 WRITE_LOCK,
03466 WINDOWS_LOCK,
03467 False,
03468 &status,
03469 NULL);
03470
03471 TALLOC_FREE(br_lck);
03472
03473 if (NT_STATUS_V(status)) {
03474 END_PROFILE(SMBlock);
03475 return ERROR_NT(status);
03476 }
03477
03478 END_PROFILE(SMBlock);
03479 return(outsize);
03480 }
03481
03482
03483
03484
03485
03486 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
03487 int dum_buffsize)
03488 {
03489 int outsize = set_message(outbuf,0,0,False);
03490 SMB_BIG_UINT count,offset;
03491 NTSTATUS status;
03492 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03493 START_PROFILE(SMBunlock);
03494
03495 CHECK_FSP(fsp,conn);
03496
03497 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
03498 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
03499
03500 status = do_unlock(fsp,
03501 (uint32)SVAL(inbuf,smb_pid),
03502 count,
03503 offset,
03504 WINDOWS_LOCK);
03505
03506 if (NT_STATUS_V(status)) {
03507 END_PROFILE(SMBunlock);
03508 return ERROR_NT(status);
03509 }
03510
03511 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
03512 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
03513
03514 END_PROFILE(SMBunlock);
03515 return(outsize);
03516 }
03517
03518 #undef DBGC_CLASS
03519 #define DBGC_CLASS DBGC_ALL
03520
03521
03522
03523
03524
03525
03526 int reply_tdis(connection_struct *conn,
03527 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03528 {
03529 int outsize = set_message(outbuf,0,0,False);
03530 uint16 vuid;
03531 START_PROFILE(SMBtdis);
03532
03533 vuid = SVAL(inbuf,smb_uid);
03534
03535 if (!conn) {
03536 DEBUG(4,("Invalid connection in tdis\n"));
03537 END_PROFILE(SMBtdis);
03538 return ERROR_DOS(ERRSRV,ERRinvnid);
03539 }
03540
03541 conn->used = False;
03542
03543 close_cnum(conn,vuid);
03544
03545 END_PROFILE(SMBtdis);
03546 return outsize;
03547 }
03548
03549
03550
03551
03552
03553
03554 int reply_echo(connection_struct *conn,
03555 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03556 {
03557 int smb_reverb = SVAL(inbuf,smb_vwv0);
03558 int seq_num;
03559 unsigned int data_len = smb_buflen(inbuf);
03560 int outsize = set_message(outbuf,1,data_len,True);
03561 START_PROFILE(SMBecho);
03562
03563 if (data_len > BUFFER_SIZE) {
03564 DEBUG(0,("reply_echo: data_len too large.\n"));
03565 END_PROFILE(SMBecho);
03566 return -1;
03567 }
03568
03569
03570 if (data_len > 0)
03571 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
03572
03573 if (smb_reverb > 100) {
03574 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
03575 smb_reverb = 100;
03576 }
03577
03578 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
03579 SSVAL(outbuf,smb_vwv0,seq_num);
03580
03581 smb_setlen(outbuf,outsize - 4);
03582
03583 show_msg(outbuf);
03584 if (!send_smb(smbd_server_fd(),outbuf))
03585 exit_server_cleanly("reply_echo: send_smb failed.");
03586 }
03587
03588 DEBUG(3,("echo %d times\n", smb_reverb));
03589
03590 smb_echo_count++;
03591
03592 END_PROFILE(SMBecho);
03593 return -1;
03594 }
03595
03596
03597
03598
03599
03600 int reply_printopen(connection_struct *conn,
03601 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03602 {
03603 int outsize = 0;
03604 files_struct *fsp;
03605 NTSTATUS status;
03606
03607 START_PROFILE(SMBsplopen);
03608
03609 if (!CAN_PRINT(conn)) {
03610 END_PROFILE(SMBsplopen);
03611 return ERROR_DOS(ERRDOS,ERRnoaccess);
03612 }
03613
03614
03615 status = print_fsp_open(conn, NULL, &fsp);
03616
03617 if (!NT_STATUS_IS_OK(status)) {
03618 END_PROFILE(SMBsplopen);
03619 return(ERROR_NT(status));
03620 }
03621
03622 outsize = set_message(outbuf,1,0,True);
03623 SSVAL(outbuf,smb_vwv0,fsp->fnum);
03624
03625 DEBUG(3,("openprint fd=%d fnum=%d\n",
03626 fsp->fh->fd, fsp->fnum));
03627
03628 END_PROFILE(SMBsplopen);
03629 return(outsize);
03630 }
03631
03632
03633
03634
03635
03636 int reply_printclose(connection_struct *conn,
03637 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03638 {
03639 int outsize = set_message(outbuf,0,0,False);
03640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03641 NTSTATUS status;
03642 START_PROFILE(SMBsplclose);
03643
03644 CHECK_FSP(fsp,conn);
03645
03646 if (!CAN_PRINT(conn)) {
03647 END_PROFILE(SMBsplclose);
03648 return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
03649 }
03650
03651 DEBUG(3,("printclose fd=%d fnum=%d\n",
03652 fsp->fh->fd,fsp->fnum));
03653
03654 status = close_file(fsp,NORMAL_CLOSE);
03655
03656 if(!NT_STATUS_IS_OK(status)) {
03657 END_PROFILE(SMBsplclose);
03658 return ERROR_NT(status);
03659 }
03660
03661 END_PROFILE(SMBsplclose);
03662 return(outsize);
03663 }
03664
03665
03666
03667
03668
03669 int reply_printqueue(connection_struct *conn,
03670 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03671 {
03672 int outsize = set_message(outbuf,2,3,True);
03673 int max_count = SVAL(inbuf,smb_vwv0);
03674 int start_index = SVAL(inbuf,smb_vwv1);
03675 START_PROFILE(SMBsplretq);
03676
03677
03678
03679
03680
03681 if (!CAN_PRINT(conn)) {
03682 END_PROFILE(SMBsplretq);
03683 return ERROR_DOS(ERRDOS,ERRnoaccess);
03684 }
03685
03686 SSVAL(outbuf,smb_vwv0,0);
03687 SSVAL(outbuf,smb_vwv1,0);
03688 SCVAL(smb_buf(outbuf),0,1);
03689 SSVAL(smb_buf(outbuf),1,0);
03690
03691 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
03692 start_index, max_count));
03693
03694 {
03695 print_queue_struct *queue = NULL;
03696 print_status_struct status;
03697 char *p = smb_buf(outbuf) + 3;
03698 int count = print_queue_status(SNUM(conn), &queue, &status);
03699 int num_to_get = ABS(max_count);
03700 int first = (max_count>0?start_index:start_index+max_count+1);
03701 int i;
03702
03703 if (first >= count)
03704 num_to_get = 0;
03705 else
03706 num_to_get = MIN(num_to_get,count-first);
03707
03708
03709 for (i=first;i<first+num_to_get;i++) {
03710 srv_put_dos_date2(p,0,queue[i].time);
03711 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
03712 SSVAL(p,5, queue[i].job);
03713 SIVAL(p,7,queue[i].size);
03714 SCVAL(p,11,0);
03715 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
03716 p += 28;
03717 }
03718
03719 if (count > 0) {
03720 outsize = set_message(outbuf,2,28*count+3,False);
03721 SSVAL(outbuf,smb_vwv0,count);
03722 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
03723 SCVAL(smb_buf(outbuf),0,1);
03724 SSVAL(smb_buf(outbuf),1,28*count);
03725 }
03726
03727 SAFE_FREE(queue);
03728
03729 DEBUG(3,("%d entries returned in queue\n",count));
03730 }
03731
03732 END_PROFILE(SMBsplretq);
03733 return(outsize);
03734 }
03735
03736
03737
03738
03739
03740 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03741 {
03742 int numtowrite;
03743 int outsize = set_message(outbuf,0,0,False);
03744 char *data;
03745 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
03746
03747 START_PROFILE(SMBsplwr);
03748
03749 if (!CAN_PRINT(conn)) {
03750 END_PROFILE(SMBsplwr);
03751 return ERROR_DOS(ERRDOS,ERRnoaccess);
03752 }
03753
03754 CHECK_FSP(fsp,conn);
03755 if (!CHECK_WRITE(fsp)) {
03756 return(ERROR_DOS(ERRDOS,ERRbadaccess));
03757 }
03758
03759 numtowrite = SVAL(smb_buf(inbuf),1);
03760 data = smb_buf(inbuf) + 3;
03761
03762 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
03763 END_PROFILE(SMBsplwr);
03764 return(UNIXERROR(ERRHRD,ERRdiskfull));
03765 }
03766
03767 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
03768
03769 END_PROFILE(SMBsplwr);
03770 return(outsize);
03771 }
03772
03773
03774
03775
03776
03777 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
03778 {
03779 pstring directory;
03780 int outsize;
03781 NTSTATUS status;
03782 SMB_STRUCT_STAT sbuf;
03783
03784 START_PROFILE(SMBmkdir);
03785
03786 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
03787 if (!NT_STATUS_IS_OK(status)) {
03788 END_PROFILE(SMBmkdir);
03789 return ERROR_NT(status);
03790 }
03791
03792 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
03793 if (!NT_STATUS_IS_OK(status)) {
03794 END_PROFILE(SMBmkdir);
03795 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
03796 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
03797 }
03798 return ERROR_NT(status);
03799 }
03800
03801 status = unix_convert(conn, directory, False, NULL, &sbuf);
03802 if (!NT_STATUS_IS_OK(status)) {
03803 END_PROFILE(SMBmkdir);
03804 return ERROR_NT(status);
03805 }
03806
03807 status = check_name(conn, directory);
03808 if (!NT_STATUS_IS_OK(status)) {
03809 END_PROFILE(SMBmkdir);
03810 return ERROR_NT(status);
03811 }
03812
03813 status = create_directory(conn, directory);
03814
03815 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
03816
03817 if (!NT_STATUS_IS_OK(status)) {
03818
03819 if (!use_nt_status()
03820 && NT_STATUS_EQUAL(status,
03821 NT_STATUS_OBJECT_NAME_COLLISION)) {
03822
03823
03824
03825
03826
03827 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
03828 }
03829
03830 END_PROFILE(SMBmkdir);
03831 return ERROR_NT(status);
03832 }
03833
03834 outsize = set_message(outbuf,0,0,False);
03835
03836 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
03837
03838 END_PROFILE(SMBmkdir);
03839 return(outsize);
03840 }
03841
03842
03843
03844
03845
03846
03847 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
03848 {
03849 const char *dname = NULL;
03850 BOOL ret = True;
03851 long offset = 0;
03852 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
03853
03854 if(dir_hnd == NULL)
03855 return False;
03856
03857 while((dname = ReadDirName(dir_hnd, &offset))) {
03858 pstring fullname;
03859 SMB_STRUCT_STAT st;
03860
03861 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
03862 continue;
03863
03864 if (!is_visible_file(conn, directory, dname, &st, False))
03865 continue;
03866
03867
03868 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
03869 errno = ENOMEM;
03870 ret = False;
03871 break;
03872 }
03873
03874 pstrcpy(fullname, directory);
03875 pstrcat(fullname, "/");
03876 pstrcat(fullname, dname);
03877
03878 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
03879 ret = False;
03880 break;
03881 }
03882
03883 if(st.st_mode & S_IFDIR) {
03884 if(!recursive_rmdir(conn, fullname)) {
03885 ret = False;
03886 break;
03887 }
03888 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
03889 ret = False;
03890 break;
03891 }
03892 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
03893 ret = False;
03894 break;
03895 }
03896 }
03897 CloseDir(dir_hnd);
03898 return ret;
03899 }
03900
03901
03902
03903
03904
03905 NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
03906 {
03907 int ret;
03908 SMB_STRUCT_STAT st;
03909
03910
03911 if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
03912 return map_nt_error_from_unix(errno);
03913 }
03914
03915 if (S_ISLNK(st.st_mode)) {
03916
03917 if(SMB_VFS_STAT(conn, directory, &st) != 0) {
03918 return map_nt_error_from_unix(errno);
03919 }
03920 if (!(S_ISDIR(st.st_mode))) {
03921 return NT_STATUS_NOT_A_DIRECTORY;
03922 }
03923 ret = SMB_VFS_UNLINK(conn,directory);
03924 } else {
03925 ret = SMB_VFS_RMDIR(conn,directory);
03926 }
03927 if (ret == 0) {
03928 notify_fname(conn, NOTIFY_ACTION_REMOVED,
03929 FILE_NOTIFY_CHANGE_DIR_NAME,
03930 directory);
03931 return NT_STATUS_OK;
03932 }
03933
03934 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
03935
03936
03937
03938
03939
03940
03941 const char *dname;
03942 long dirpos = 0;
03943 struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
03944
03945 if(dir_hnd == NULL) {
03946 errno = ENOTEMPTY;
03947 goto err;
03948 }
03949
03950 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
03951 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
03952 continue;
03953 if (!is_visible_file(conn, directory, dname, &st, False))
03954 continue;
03955 if(!IS_VETO_PATH(conn, dname)) {
03956 CloseDir(dir_hnd);
03957 errno = ENOTEMPTY;
03958 goto err;
03959 }
03960 }
03961
03962
03963
03964 RewindDir(dir_hnd,&dirpos);
03965 while ((dname = ReadDirName(dir_hnd,&dirpos))) {
03966 pstring fullname;
03967
03968 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
03969 continue;
03970 if (!is_visible_file(conn, directory, dname, &st, False))
03971 continue;
03972
03973
03974 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
03975 errno = ENOMEM;
03976 break;
03977 }
03978
03979 pstrcpy(fullname, directory);
03980 pstrcat(fullname, "/");
03981 pstrcat(fullname, dname);
03982
03983 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
03984 break;
03985 if(st.st_mode & S_IFDIR) {
03986 if(lp_recursive_veto_delete(SNUM(conn))) {
03987 if(!recursive_rmdir(conn, fullname))
03988 break;
03989 }
03990 if(SMB_VFS_RMDIR(conn,fullname) != 0)
03991 break;
03992 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
03993 break;
03994 }
03995 CloseDir(dir_hnd);
03996
03997 ret = SMB_VFS_RMDIR(conn,directory);
03998 }
03999
04000 err:
04001
04002 if (ret != 0) {
04003 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
04004 "%s\n", directory,strerror(errno)));
04005 return map_nt_error_from_unix(errno);
04006 }
04007
04008 notify_fname(conn, NOTIFY_ACTION_REMOVED,
04009 FILE_NOTIFY_CHANGE_DIR_NAME,
04010 directory);
04011
04012 return NT_STATUS_OK;
04013 }
04014
04015
04016
04017
04018
04019 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
04020 {
04021 pstring directory;
04022 int outsize = 0;
04023 SMB_STRUCT_STAT sbuf;
04024 NTSTATUS status;
04025 START_PROFILE(SMBrmdir);
04026
04027 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
04028 if (!NT_STATUS_IS_OK(status)) {
04029 END_PROFILE(SMBrmdir);
04030 return ERROR_NT(status);
04031 }
04032
04033 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
04034 if (!NT_STATUS_IS_OK(status)) {
04035 END_PROFILE(SMBrmdir);
04036 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
04037 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
04038 }
04039 return ERROR_NT(status);
04040 }
04041
04042 status = unix_convert(conn, directory, False, NULL, &sbuf);
04043 if (!NT_STATUS_IS_OK(status)) {
04044 END_PROFILE(SMBrmdir);
04045 return ERROR_NT(status);
04046 }
04047
04048 status = check_name(conn, directory);
04049 if (!NT_STATUS_IS_OK(status)) {
04050 END_PROFILE(SMBrmdir);
04051 return ERROR_NT(status);
04052 }
04053
04054 dptr_closepath(directory,SVAL(inbuf,smb_pid));
04055 status = rmdir_internals(conn, directory);
04056 if (!NT_STATUS_IS_OK(status)) {
04057 END_PROFILE(SMBrmdir);
04058 return ERROR_NT(status);
04059 }
04060
04061 outsize = set_message(outbuf,0,0,False);
04062
04063 DEBUG( 3, ( "rmdir %s\n", directory ) );
04064
04065 END_PROFILE(SMBrmdir);
04066 return(outsize);
04067 }
04068
04069
04070
04071
04072
04073
04074
04075
04076
04077 static BOOL resolve_wildcards(const char *name1, char *name2)
04078 {
04079 pstring root1,root2;
04080 pstring ext1,ext2;
04081 char *p,*p2, *pname1, *pname2;
04082 int available_space, actual_space;
04083
04084 pname1 = strrchr_m(name1,'/');
04085 pname2 = strrchr_m(name2,'/');
04086
04087 if (!pname1 || !pname2)
04088 return(False);
04089
04090 pstrcpy(root1,pname1);
04091 pstrcpy(root2,pname2);
04092 p = strrchr_m(root1,'.');
04093 if (p) {
04094 *p = 0;
04095 pstrcpy(ext1,p+1);
04096 } else {
04097 pstrcpy(ext1,"");
04098 }
04099 p = strrchr_m(root2,'.');
04100 if (p) {
04101 *p = 0;
04102 pstrcpy(ext2,p+1);
04103 } else {
04104 pstrcpy(ext2,"");
04105 }
04106
04107 p = root1;
04108 p2 = root2;
04109 while (*p2) {
04110 if (*p2 == '?') {
04111 *p2 = *p;
04112 p2++;
04113 } else if (*p2 == '*') {
04114 pstrcpy(p2, p);
04115 break;
04116 } else {
04117 p2++;
04118 }
04119 if (*p)
04120 p++;
04121 }
04122
04123 p = ext1;
04124 p2 = ext2;
04125 while (*p2) {
04126 if (*p2 == '?') {
04127 *p2 = *p;
04128 p2++;
04129 } else if (*p2 == '*') {
04130 pstrcpy(p2, p);
04131 break;
04132 } else {
04133 p2++;
04134 }
04135 if (*p)
04136 p++;
04137 }
04138
04139 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
04140
04141 if (ext2[0]) {
04142 actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
04143 if (actual_space >= available_space - 1) {
04144 DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
04145 actual_space - available_space));
04146 }
04147 } else {
04148 pstrcpy_base(pname2, root2, name2);
04149 }
04150
04151 return(True);
04152 }
04153
04154
04155
04156
04157
04158
04159 static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
04160 SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
04161 {
04162 files_struct *fsp;
04163 BOOL did_rename = False;
04164
04165 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
04166
04167
04168
04169
04170 if (fsp->conn != conn) {
04171 continue;
04172 }
04173 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
04174 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
04175 fsp->fsp_name, newname ));
04176 string_set(&fsp->fsp_name, newname);
04177 did_rename = True;
04178 }
04179
04180 if (!did_rename) {
04181 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
04182 (unsigned int)dev, (double)inode, newname ));
04183 }
04184
04185
04186 rename_share_filename(lck, conn->connectpath, newname);
04187 }
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200 static BOOL rename_path_prefix_equal(const char *src, const char *dest)
04201 {
04202 const char *psrc = src;
04203 const char *pdst = dest;
04204 size_t slen;
04205
04206 if (psrc[0] == '.' && psrc[1] == '/') {
04207 psrc += 2;
04208 }
04209 if (pdst[0] == '.' && pdst[1] == '/') {
04210 pdst += 2;
04211 }
04212 if ((slen = strlen(psrc)) > strlen(pdst)) {
04213 return False;
04214 }
04215 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
04216 }
04217
04218
04219
04220
04221
04222 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
04223 {
04224 SMB_STRUCT_STAT sbuf;
04225 pstring newname_last_component;
04226 NTSTATUS status = NT_STATUS_OK;
04227 BOOL dest_exists;
04228 struct share_mode_lock *lck = NULL;
04229
04230 ZERO_STRUCT(sbuf);
04231
04232 status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
04233
04234
04235
04236 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
04237 return status;
04238 }
04239
04240 status = check_name(conn, newname);
04241 if (!NT_STATUS_IS_OK(status)) {
04242 return status;
04243 }
04244
04245
04246 if(strrchr_m(newname,'/') == 0) {
04247 pstring tmpstr;
04248
04249 pstrcpy(tmpstr, "./");
04250 pstrcat(tmpstr, newname);
04251 pstrcpy(newname, tmpstr);
04252 }
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
04263 strequal(newname, fsp->fsp_name)) {
04264 char *p;
04265 pstring newname_modified_last_component;
04266
04267
04268
04269
04270
04271
04272 p = strrchr_m(newname,'/');
04273 pstrcpy(newname_modified_last_component,p+1);
04274
04275 if(strcsequal(newname_modified_last_component,
04276 newname_last_component) == False) {
04277
04278
04279
04280
04281 pstrcpy(p+1, newname_last_component);
04282 }
04283 }
04284
04285
04286
04287
04288
04289
04290 if (strcsequal(fsp->fsp_name, newname)) {
04291 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
04292 newname));
04293 return NT_STATUS_OK;
04294 }
04295
04296 dest_exists = vfs_object_exist(conn,newname,NULL);
04297
04298 if(!replace_if_exists && dest_exists) {
04299 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
04300 fsp->fsp_name,newname));
04301 return NT_STATUS_OBJECT_NAME_COLLISION;
04302 }
04303
04304
04305 if (fsp->fh->fd != -1) {
04306 if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
04307 return map_nt_error_from_unix(errno);
04308 }
04309 } else {
04310 if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
04311 return map_nt_error_from_unix(errno);
04312 }
04313 }
04314
04315 status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
04316
04317 if (!NT_STATUS_IS_OK(status)) {
04318 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
04319 nt_errstr(status), fsp->fsp_name,newname));
04320 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
04321 status = NT_STATUS_ACCESS_DENIED;
04322 return status;
04323 }
04324
04325 if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
04326 return NT_STATUS_ACCESS_DENIED;
04327 }
04328
04329 lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
04330
04331 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
04332 uint32 create_options = fsp->fh->private_options;
04333
04334 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
04335 fsp->fsp_name,newname));
04336
04337 rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348 set_allow_initial_delete_on_close(lck, fsp, True);
04349
04350 if (create_options & FILE_DELETE_ON_CLOSE) {
04351 status = can_set_delete_on_close(fsp, True, 0);
04352
04353 if (NT_STATUS_IS_OK(status)) {
04354
04355
04356 fsp->initial_delete_on_close = True;
04357 }
04358 }
04359 TALLOC_FREE(lck);
04360 return NT_STATUS_OK;
04361 }
04362
04363 TALLOC_FREE(lck);
04364
04365 if (errno == ENOTDIR || errno == EISDIR) {
04366 status = NT_STATUS_OBJECT_NAME_COLLISION;
04367 } else {
04368 status = map_nt_error_from_unix(errno);
04369 }
04370
04371 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
04372 nt_errstr(status), fsp->fsp_name,newname));
04373
04374 return status;
04375 }
04376
04377
04378
04379
04380
04381 static void notify_rename(connection_struct *conn, BOOL is_dir,
04382 const char *oldpath, const char *newpath)
04383 {
04384 char *olddir, *newdir;
04385 const char *oldname, *newname;
04386 uint32 mask;
04387
04388 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
04389 : FILE_NOTIFY_CHANGE_FILE_NAME;
04390
04391 if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
04392 || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
04393 TALLOC_FREE(olddir);
04394 return;
04395 }
04396
04397 if (strcmp(olddir, newdir) == 0) {
04398 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
04399 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
04400 }
04401 else {
04402 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
04403 notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
04404 }
04405 TALLOC_FREE(olddir);
04406 TALLOC_FREE(newdir);
04407
04408
04409
04410
04411 if (!is_dir) {
04412 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
04413 FILE_NOTIFY_CHANGE_ATTRIBUTES
04414 |FILE_NOTIFY_CHANGE_CREATION,
04415 newpath);
04416 }
04417 }
04418
04419
04420
04421
04422
04423
04424 NTSTATUS rename_internals(connection_struct *conn,
04425 pstring name,
04426 pstring newname,
04427 uint32 attrs,
04428 BOOL replace_if_exists,
04429 BOOL src_has_wild,
04430 BOOL dest_has_wild)
04431 {
04432 pstring directory;
04433 pstring mask;
04434 pstring last_component_src;
04435 pstring last_component_dest;
04436 char *p;
04437 int count=0;
04438 NTSTATUS status = NT_STATUS_OK;
04439 SMB_STRUCT_STAT sbuf1, sbuf2;
04440 struct share_mode_lock *lck = NULL;
04441 struct smb_Dir *dir_hnd = NULL;
04442 const char *dname;
04443 long offset = 0;
04444 pstring destname;
04445
04446 *directory = *mask = 0;
04447
04448 ZERO_STRUCT(sbuf1);
04449 ZERO_STRUCT(sbuf2);
04450
04451 status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
04452 if (!NT_STATUS_IS_OK(status)) {
04453 return status;
04454 }
04455
04456 status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
04457 if (!NT_STATUS_IS_OK(status)) {
04458 return status;
04459 }
04460
04461
04462
04463
04464
04465
04466
04467
04468
04469
04470 p = strrchr_m(name,'/');
04471 if (!p) {
04472 pstrcpy(directory,".");
04473 pstrcpy(mask,name);
04474 } else {
04475 *p = 0;
04476 pstrcpy(directory,name);
04477 pstrcpy(mask,p+1);
04478 *p = '/';
04479 }
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
04491 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
04492 }
04493
04494 if (!src_has_wild) {
04495
04496
04497
04498 BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
04499
04500
04501 pstrcat(directory,"/");
04502 pstrcat(directory,mask);
04503
04504
04505 if(strrchr_m(newname,'/') == 0) {
04506 pstring tmpstr;
04507
04508 pstrcpy(tmpstr, "./");
04509 pstrcat(tmpstr, newname);
04510 pstrcpy(newname, tmpstr);
04511 }
04512
04513 DEBUG(3, ("rename_internals: case_sensitive = %d, "
04514 "case_preserve = %d, short case preserve = %d, "
04515 "directory = %s, newname = %s, "
04516 "last_component_dest = %s, is_8_3 = %d\n",
04517 conn->case_sensitive, conn->case_preserve,
04518 conn->short_case_preserve, directory,
04519 newname, last_component_dest, is_short_name));
04520
04521
04522 status = check_name(conn, directory);
04523 if (!NT_STATUS_IS_OK(status)) {
04524 return status;
04525 }
04526
04527
04528 if (dest_has_wild) {
04529 if (!resolve_wildcards(directory,newname)) {
04530 DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
04531 directory,newname));
04532 return NT_STATUS_NO_MEMORY;
04533 }
04534 }
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544 if((conn->case_sensitive == False) &&
04545 (((conn->case_preserve == True) &&
04546 (is_short_name == False)) ||
04547 ((conn->short_case_preserve == True) &&
04548 (is_short_name == True))) &&
04549 strcsequal(directory, newname)) {
04550 pstring modified_last_component;
04551
04552
04553
04554
04555
04556
04557 p = strrchr_m(newname,'/');
04558 pstrcpy(modified_last_component,p+1);
04559
04560 if(strcsequal(modified_last_component,
04561 last_component_dest) == False) {
04562
04563
04564
04565
04566 pstrcpy(p+1, last_component_dest);
04567 }
04568 }
04569
04570
04571 status = check_name(conn, newname);
04572 if (!NT_STATUS_IS_OK(status)) {
04573 return status;
04574 }
04575
04576
04577
04578
04579
04580 if (!vfs_object_exist(conn, directory, &sbuf1)) {
04581 DEBUG(3, ("rename_internals: source doesn't exist "
04582 "doing rename %s -> %s\n",
04583 directory,newname));
04584
04585 if (errno == ENOTDIR || errno == EISDIR
04586 || errno == ENOENT) {
04587
04588
04589
04590
04591
04592
04593 p = strrchr_m(directory, '/');
04594 if (!p)
04595 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04596 *p = '\0';
04597 if (vfs_object_exist(conn, directory, NULL))
04598 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04599 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
04600 }
04601 status = map_nt_error_from_unix(errno);
04602 DEBUG(3, ("rename_internals: Error %s rename %s -> "
04603 "%s\n", nt_errstr(status), directory,
04604 newname));
04605
04606 return status;
04607 }
04608
04609 status = can_rename(conn,directory,attrs,&sbuf1,False);
04610
04611 if (!NT_STATUS_IS_OK(status)) {
04612 DEBUG(3,("rename_internals: Error %s rename %s -> "
04613 "%s\n", nt_errstr(status), directory,
04614 newname));
04615 return status;
04616 }
04617
04618
04619
04620
04621
04622
04623 if (strcsequal(directory, newname)) {
04624 DEBUG(3, ("rename_internals: identical names in "
04625 "rename %s - returning success\n",
04626 directory));
04627 return NT_STATUS_OK;
04628 }
04629
04630 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
04631 DEBUG(3,("rename_internals: dest exists doing "
04632 "rename %s -> %s\n", directory, newname));
04633 return NT_STATUS_OBJECT_NAME_COLLISION;
04634 }
04635
04636 if (rename_path_prefix_equal(directory, newname)) {
04637 return NT_STATUS_SHARING_VIOLATION;
04638 }
04639
04640 lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
04641 NULL, NULL);
04642
04643 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
04644 DEBUG(3,("rename_internals: succeeded doing rename "
04645 "on %s -> %s\n", directory, newname));
04646 rename_open_files(conn, lck, sbuf1.st_dev,
04647 sbuf1.st_ino, newname);
04648 TALLOC_FREE(lck);
04649 notify_rename(conn, S_ISDIR(sbuf1.st_mode),
04650 directory, newname);
04651 return NT_STATUS_OK;
04652 }
04653
04654 TALLOC_FREE(lck);
04655 if (errno == ENOTDIR || errno == EISDIR) {
04656 status = NT_STATUS_OBJECT_NAME_COLLISION;
04657 } else {
04658 status = map_nt_error_from_unix(errno);
04659 }
04660
04661 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
04662 nt_errstr(status), directory,newname));
04663
04664 return status;
04665 }
04666
04667
04668
04669
04670 if (strequal(mask,"????????.???")) {
04671 pstrcpy(mask,"*");
04672 }
04673
04674 status = check_name(conn, directory);
04675 if (!NT_STATUS_IS_OK(status)) {
04676 return status;
04677 }
04678
04679 dir_hnd = OpenDir(conn, directory, mask, attrs);
04680 if (dir_hnd == NULL) {
04681 return map_nt_error_from_unix(errno);
04682 }
04683
04684 status = NT_STATUS_NO_SUCH_FILE;
04685
04686
04687
04688
04689
04690 while ((dname = ReadDirName(dir_hnd, &offset))) {
04691 pstring fname;
04692 BOOL sysdir_entry = False;
04693
04694 pstrcpy(fname,dname);
04695
04696
04697 if (fname[0] == '.') {
04698 if (!fname[1] || (fname[1] == '.' && !fname[2])) {
04699 if (attrs & aDIR) {
04700 sysdir_entry = True;
04701 } else {
04702 continue;
04703 }
04704 }
04705 }
04706
04707 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
04708 continue;
04709 }
04710
04711 if(!mask_match(fname, mask, conn->case_sensitive)) {
04712 continue;
04713 }
04714
04715 if (sysdir_entry) {
04716 status = NT_STATUS_OBJECT_NAME_INVALID;
04717 break;
04718 }
04719
04720 status = NT_STATUS_ACCESS_DENIED;
04721 slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
04722
04723
04724 status = check_name(conn, fname);
04725 if (!NT_STATUS_IS_OK(status)) {
04726 return status;
04727 }
04728
04729 if (!vfs_object_exist(conn, fname, &sbuf1)) {
04730 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
04731 DEBUG(6, ("rename %s failed. Error %s\n",
04732 fname, nt_errstr(status)));
04733 continue;
04734 }
04735 status = can_rename(conn,fname,attrs,&sbuf1,False);
04736 if (!NT_STATUS_IS_OK(status)) {
04737 DEBUG(6, ("rename %s refused\n", fname));
04738 continue;
04739 }
04740 pstrcpy(destname,newname);
04741
04742 if (!resolve_wildcards(fname,destname)) {
04743 DEBUG(6, ("resolve_wildcards %s %s failed\n",
04744 fname, destname));
04745 continue;
04746 }
04747
04748
04749 status = check_name(conn, destname);
04750 if (!NT_STATUS_IS_OK(status)) {
04751 return status;
04752 }
04753
04754 if (strcsequal(fname,destname)) {
04755 DEBUG(3,("rename_internals: identical names "
04756 "in wildcard rename %s - success\n",
04757 fname));
04758 count++;
04759 status = NT_STATUS_OK;
04760 continue;
04761 }
04762
04763 if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
04764 DEBUG(6,("file_exist %s\n", destname));
04765 status = NT_STATUS_OBJECT_NAME_COLLISION;
04766 continue;
04767 }
04768
04769 if (rename_path_prefix_equal(fname, destname)) {
04770 return NT_STATUS_SHARING_VIOLATION;
04771 }
04772
04773 lck = get_share_mode_lock(NULL, sbuf1.st_dev,
04774 sbuf1.st_ino, NULL, NULL);
04775
04776 if (!SMB_VFS_RENAME(conn,fname,destname)) {
04777 rename_open_files(conn, lck, sbuf1.st_dev,
04778 sbuf1.st_ino, newname);
04779 count++;
04780 status = NT_STATUS_OK;
04781 }
04782 TALLOC_FREE(lck);
04783 DEBUG(3,("rename_internals: doing rename on %s -> "
04784 "%s\n",fname,destname));
04785 }
04786 CloseDir(dir_hnd);
04787
04788 if (count == 0 && NT_STATUS_IS_OK(status)) {
04789 status = map_nt_error_from_unix(errno);
04790 }
04791
04792 return status;
04793 }
04794
04795
04796
04797
04798
04799 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
04800 int dum_buffsize)
04801 {
04802 int outsize = 0;
04803 pstring name;
04804 pstring newname;
04805 char *p;
04806 uint32 attrs = SVAL(inbuf,smb_vwv0);
04807 NTSTATUS status;
04808 BOOL src_has_wcard = False;
04809 BOOL dest_has_wcard = False;
04810
04811 START_PROFILE(SMBmv);
04812
04813 p = smb_buf(inbuf) + 1;
04814 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
04815 if (!NT_STATUS_IS_OK(status)) {
04816 END_PROFILE(SMBmv);
04817 return ERROR_NT(status);
04818 }
04819 p++;
04820 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
04821 if (!NT_STATUS_IS_OK(status)) {
04822 END_PROFILE(SMBmv);
04823 return ERROR_NT(status);
04824 }
04825
04826 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
04827 if (!NT_STATUS_IS_OK(status)) {
04828 END_PROFILE(SMBmv);
04829 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
04830 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
04831 }
04832 return ERROR_NT(status);
04833 }
04834
04835 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
04836 if (!NT_STATUS_IS_OK(status)) {
04837 END_PROFILE(SMBmv);
04838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
04839 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
04840 }
04841 return ERROR_NT(status);
04842 }
04843
04844 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
04845
04846 status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
04847 if (!NT_STATUS_IS_OK(status)) {
04848 END_PROFILE(SMBmv);
04849 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
04850
04851 return -1;
04852 }
04853 return ERROR_NT(status);
04854 }
04855
04856 outsize = set_message(outbuf,0,0,False);
04857
04858 END_PROFILE(SMBmv);
04859 return(outsize);
04860 }
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870 NTSTATUS copy_file(connection_struct *conn,
04871 char *src,
04872 char *dest1,
04873 int ofun,
04874 int count,
04875 BOOL target_is_directory)
04876 {
04877 SMB_STRUCT_STAT src_sbuf, sbuf2;
04878 SMB_OFF_T ret=-1;
04879 files_struct *fsp1,*fsp2;
04880 pstring dest;
04881 uint32 dosattrs;
04882 uint32 new_create_disposition;
04883 NTSTATUS status;
04884
04885 pstrcpy(dest,dest1);
04886 if (target_is_directory) {
04887 char *p = strrchr_m(src,'/');
04888 if (p) {
04889 p++;
04890 } else {
04891 p = src;
04892 }
04893 pstrcat(dest,"/");
04894 pstrcat(dest,p);
04895 }
04896
04897 if (!vfs_file_exist(conn,src,&src_sbuf)) {
04898 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
04899 }
04900
04901 if (!target_is_directory && count) {
04902 new_create_disposition = FILE_OPEN;
04903 } else {
04904 if (!map_open_params_to_ntcreate(dest1,0,ofun,
04905 NULL, NULL, &new_create_disposition, NULL)) {
04906 return NT_STATUS_INVALID_PARAMETER;
04907 }
04908 }
04909
04910 status = open_file_ntcreate(conn,src,&src_sbuf,
04911 FILE_GENERIC_READ,
04912 FILE_SHARE_READ|FILE_SHARE_WRITE,
04913 FILE_OPEN,
04914 0,
04915 FILE_ATTRIBUTE_NORMAL,
04916 INTERNAL_OPEN_ONLY,
04917 NULL, &fsp1);
04918
04919 if (!NT_STATUS_IS_OK(status)) {
04920 return status;
04921 }
04922
04923 dosattrs = dos_mode(conn, src, &src_sbuf);
04924 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
04925 ZERO_STRUCTP(&sbuf2);
04926 }
04927
04928 status = open_file_ntcreate(conn,dest,&sbuf2,
04929 FILE_GENERIC_WRITE,
04930 FILE_SHARE_READ|FILE_SHARE_WRITE,
04931 new_create_disposition,
04932 0,
04933 dosattrs,
04934 INTERNAL_OPEN_ONLY,
04935 NULL, &fsp2);
04936
04937 if (!NT_STATUS_IS_OK(status)) {
04938 close_file(fsp1,ERROR_CLOSE);
04939 return status;
04940 }
04941
04942 if ((ofun&3) == 1) {
04943 if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
04944 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
04945
04946
04947
04948 ret = -1;
04949 src_sbuf.st_size = 0;
04950 }
04951 }
04952
04953 if (src_sbuf.st_size) {
04954 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
04955 }
04956
04957 close_file(fsp1,NORMAL_CLOSE);
04958
04959
04960 fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
04961
04962
04963
04964
04965
04966
04967
04968 status = close_file(fsp2,NORMAL_CLOSE);
04969
04970 if (!NT_STATUS_IS_OK(status)) {
04971 return status;
04972 }
04973
04974 if (ret != (SMB_OFF_T)src_sbuf.st_size) {
04975 return NT_STATUS_DISK_FULL;
04976 }
04977
04978 return NT_STATUS_OK;
04979 }
04980
04981
04982
04983
04984
04985 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
04986 {
04987 int outsize = 0;
04988 pstring name;
04989 pstring directory;
04990 pstring mask,newname;
04991 char *p;
04992 int count=0;
04993 int error = ERRnoaccess;
04994 int err = 0;
04995 int tid2 = SVAL(inbuf,smb_vwv0);
04996 int ofun = SVAL(inbuf,smb_vwv1);
04997 int flags = SVAL(inbuf,smb_vwv2);
04998 BOOL target_is_directory=False;
04999 BOOL source_has_wild = False;
05000 BOOL dest_has_wild = False;
05001 SMB_STRUCT_STAT sbuf1, sbuf2;
05002 NTSTATUS status;
05003 START_PROFILE(SMBcopy);
05004
05005 *directory = *mask = 0;
05006
05007 p = smb_buf(inbuf);
05008 p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
05009 if (!NT_STATUS_IS_OK(status)) {
05010 END_PROFILE(SMBcopy);
05011 return ERROR_NT(status);
05012 }
05013 p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
05014 if (!NT_STATUS_IS_OK(status)) {
05015 END_PROFILE(SMBcopy);
05016 return ERROR_NT(status);
05017 }
05018
05019 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
05020
05021 if (tid2 != conn->cnum) {
05022
05023 DEBUG(3,("Rejecting inter-share copy\n"));
05024 END_PROFILE(SMBcopy);
05025 return ERROR_DOS(ERRSRV,ERRinvdevice);
05026 }
05027
05028 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
05029 if (!NT_STATUS_IS_OK(status)) {
05030 END_PROFILE(SMBcopy);
05031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
05032 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
05033 }
05034 return ERROR_NT(status);
05035 }
05036
05037 status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
05038 if (!NT_STATUS_IS_OK(status)) {
05039 END_PROFILE(SMBcopy);
05040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
05041 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
05042 }
05043 return ERROR_NT(status);
05044 }
05045
05046 status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
05047 if (!NT_STATUS_IS_OK(status)) {
05048 END_PROFILE(SMBcopy);
05049 return ERROR_NT(status);
05050 }
05051
05052 status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
05053 if (!NT_STATUS_IS_OK(status)) {
05054 END_PROFILE(SMBcopy);
05055 return ERROR_NT(status);
05056 }
05057
05058 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
05059
05060 if ((flags&1) && target_is_directory) {
05061 END_PROFILE(SMBcopy);
05062 return ERROR_DOS(ERRDOS,ERRbadfile);
05063 }
05064
05065 if ((flags&2) && !target_is_directory) {
05066 END_PROFILE(SMBcopy);
05067 return ERROR_DOS(ERRDOS,ERRbadpath);
05068 }
05069
05070 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
05071
05072 DEBUG(3,("Rejecting tree copy\n"));
05073 END_PROFILE(SMBcopy);
05074 return ERROR_DOS(ERRSRV,ERRerror);
05075 }
05076
05077 p = strrchr_m(name,'/');
05078 if (!p) {
05079 pstrcpy(directory,"./");
05080 pstrcpy(mask,name);
05081 } else {
05082 *p = 0;
05083 pstrcpy(directory,name);
05084 pstrcpy(mask,p+1);
05085 }
05086
05087
05088
05089
05090
05091
05092
05093
05094
05095
05096 if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
05097 mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
05098 }
05099
05100 if (!source_has_wild) {
05101 pstrcat(directory,"/");
05102 pstrcat(directory,mask);
05103 if (dest_has_wild) {
05104 if (!resolve_wildcards(directory,newname)) {
05105 END_PROFILE(SMBcopy);
05106 return ERROR_NT(NT_STATUS_NO_MEMORY);
05107 }
05108 }
05109
05110 status = check_name(conn, directory);
05111 if (!NT_STATUS_IS_OK(status)) {
05112 return ERROR_NT(status);
05113 }
05114
05115 status = check_name(conn, newname);
05116 if (!NT_STATUS_IS_OK(status)) {
05117 return ERROR_NT(status);
05118 }
05119
05120 status = copy_file(conn,directory,newname,ofun,
05121 count,target_is_directory);
05122
05123 if(!NT_STATUS_IS_OK(status)) {
05124 END_PROFILE(SMBcopy);
05125 return ERROR_NT(status);
05126 } else {
05127 count++;
05128 }
05129 } else {
05130 struct smb_Dir *dir_hnd = NULL;
05131 const char *dname;
05132 long offset = 0;
05133 pstring destname;
05134
05135 if (strequal(mask,"????????.???"))
05136 pstrcpy(mask,"*");
05137
05138 status = check_name(conn, directory);
05139 if (!NT_STATUS_IS_OK(status)) {
05140 return ERROR_NT(status);
05141 }
05142
05143 dir_hnd = OpenDir(conn, directory, mask, 0);
05144 if (dir_hnd == NULL) {
05145 status = map_nt_error_from_unix(errno);
05146 return ERROR_NT(status);
05147 }
05148
05149 error = ERRbadfile;
05150
05151 while ((dname = ReadDirName(dir_hnd, &offset))) {
05152 pstring fname;
05153 pstrcpy(fname,dname);
05154
05155 if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
05156 continue;
05157 }
05158
05159 if(!mask_match(fname, mask, conn->case_sensitive)) {
05160 continue;
05161 }
05162
05163 error = ERRnoaccess;
05164 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
05165 pstrcpy(destname,newname);
05166 if (!resolve_wildcards(fname,destname)) {
05167 continue;
05168 }
05169
05170 status = check_name(conn, fname);
05171 if (!NT_STATUS_IS_OK(status)) {
05172 CloseDir(dir_hnd);
05173 return ERROR_NT(status);
05174 }
05175
05176 status = check_name(conn, destname);
05177 if (!NT_STATUS_IS_OK(status)) {
05178 CloseDir(dir_hnd);
05179 return ERROR_NT(status);
05180 }
05181
05182 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
05183
05184 status = copy_file(conn,fname,destname,ofun,
05185 count,target_is_directory);
05186 if (NT_STATUS_IS_OK(status)) {
05187 count++;
05188 }
05189 }
05190 CloseDir(dir_hnd);
05191 }
05192
05193 if (count == 0) {
05194 if(err) {
05195
05196 errno = err;
05197 END_PROFILE(SMBcopy);
05198 return(UNIXERROR(ERRHRD,ERRgeneral));
05199 }
05200
05201 END_PROFILE(SMBcopy);
05202 return ERROR_DOS(ERRDOS,error);
05203 }
05204
05205 outsize = set_message(outbuf,1,0,True);
05206 SSVAL(outbuf,smb_vwv0,count);
05207
05208 END_PROFILE(SMBcopy);
05209 return(outsize);
05210 }
05211
05212
05213
05214
05215
05216 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
05217 {
05218 int snum;
05219 int outsize = 0;
05220 pstring newdir;
05221 NTSTATUS status;
05222
05223 START_PROFILE(pathworks_setdir);
05224
05225 snum = SNUM(conn);
05226 if (!CAN_SETDIR(snum)) {
05227 END_PROFILE(pathworks_setdir);
05228 return ERROR_DOS(ERRDOS,ERRnoaccess);
05229 }
05230
05231 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
05232 if (!NT_STATUS_IS_OK(status)) {
05233 END_PROFILE(pathworks_setdir);
05234 return ERROR_NT(status);
05235 }
05236
05237 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
05238 if (!NT_STATUS_IS_OK(status)) {
05239 END_PROFILE(pathworks_setdir);
05240 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
05241 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
05242 }
05243 return ERROR_NT(status);
05244 }
05245
05246 if (strlen(newdir) != 0) {
05247 if (!vfs_directory_exist(conn,newdir,NULL)) {
05248 END_PROFILE(pathworks_setdir);
05249 return ERROR_DOS(ERRDOS,ERRbadpath);
05250 }
05251 set_conn_connectpath(conn,newdir);
05252 }
05253
05254 outsize = set_message(outbuf,0,0,False);
05255 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
05256
05257 DEBUG(3,("setdir %s\n", newdir));
05258
05259 END_PROFILE(pathworks_setdir);
05260 return(outsize);
05261 }
05262
05263 #undef DBGC_CLASS
05264 #define DBGC_CLASS DBGC_LOCKING
05265
05266
05267
05268
05269
05270 uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
05271 {
05272 if(!large_file_format)
05273 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
05274 else
05275 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
05276 }
05277
05278
05279
05280
05281
05282 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
05283 {
05284 SMB_BIG_UINT count = 0;
05285
05286 if(!large_file_format) {
05287 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
05288 } else {
05289
05290 #if defined(HAVE_LONGLONG)
05291 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
05292 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
05293 #else
05294
05295
05296
05297
05298
05299
05300
05301
05302 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
05303 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
05304 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
05305 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
05306 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
05307 }
05308
05309 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
05310 #endif
05311 }
05312
05313 return count;
05314 }
05315
05316 #if !defined(HAVE_LONGLONG)
05317
05318
05319
05320
05321 static uint32 map_lock_offset(uint32 high, uint32 low)
05322 {
05323 unsigned int i;
05324 uint32 mask = 0;
05325 uint32 highcopy = high;
05326
05327
05328
05329
05330
05331 for(i = 0; highcopy; i++)
05332 highcopy >>= 1;
05333
05334
05335
05336
05337
05338
05339 mask = (~0) << (31 - i);
05340
05341 if(low & mask)
05342 return 0;
05343
05344 high <<= (31 - i);
05345
05346 return (high|low);
05347 }
05348 #endif
05349
05350
05351
05352
05353
05354 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
05355 {
05356 SMB_BIG_UINT offset = 0;
05357
05358 *err = False;
05359
05360 if(!large_file_format) {
05361 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
05362 } else {
05363
05364 #if defined(HAVE_LONGLONG)
05365 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
05366 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
05367 #else
05368
05369
05370
05371
05372
05373
05374
05375
05376 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
05377 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
05378 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
05379 uint32 new_low = 0;
05380
05381 if((new_low = map_lock_offset(high, low)) == 0) {
05382 *err = True;
05383 return (SMB_BIG_UINT)-1;
05384 }
05385
05386 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
05387 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
05388 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
05389 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
05390 }
05391
05392 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
05393 #endif
05394 }
05395
05396 return offset;
05397 }
05398
05399
05400
05401
05402
05403 int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
05404 int length, int bufsize)
05405 {
05406 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
05407 unsigned char locktype = CVAL(inbuf,smb_vwv3);
05408 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
05409 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
05410 uint16 num_locks = SVAL(inbuf,smb_vwv7);
05411 SMB_BIG_UINT count = 0, offset = 0;
05412 uint32 lock_pid;
05413 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
05414 int i;
05415 char *data;
05416 BOOL large_file_format =
05417 (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
05418 BOOL err;
05419 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
05420
05421 START_PROFILE(SMBlockingX);
05422
05423 CHECK_FSP(fsp,conn);
05424
05425 data = smb_buf(inbuf);
05426
05427 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
05428
05429
05430
05431 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
05432 }
05433
05434
05435
05436
05437 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
05438
05439 BOOL break_to_none = (oplocklevel == 0);
05440 BOOL result;
05441
05442 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
05443 "for fnum = %d\n", (unsigned int)oplocklevel,
05444 fsp->fnum ));
05445
05446
05447
05448
05449
05450
05451 if (fsp->oplock_type == 0) {
05452
05453
05454
05455
05456
05457
05458
05459 DEBUG(5,("reply_lockingX: Error : oplock break from "
05460 "client for fnum = %d (oplock=%d) and no "
05461 "oplock granted on this file (%s).\n",
05462 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
05463
05464
05465
05466 if (num_locks == 0 && num_ulocks == 0) {
05467 END_PROFILE(SMBlockingX);
05468 return -1;
05469 } else {
05470 END_PROFILE(SMBlockingX);
05471 return ERROR_DOS(ERRDOS,ERRlock);
05472 }
05473 }
05474
05475 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
05476 (break_to_none)) {
05477 result = remove_oplock(fsp);
05478 } else {
05479 result = downgrade_oplock(fsp);
05480 }
05481
05482 if (!result) {
05483 DEBUG(0, ("reply_lockingX: error in removing "
05484 "oplock on file %s\n", fsp->fsp_name));
05485
05486 smb_panic("internal tdb error");
05487 }
05488
05489 reply_to_oplock_break_requests(fsp);
05490
05491
05492
05493 if (num_locks == 0 && num_ulocks == 0) {
05494
05495
05496 if(CVAL(inbuf,smb_vwv0) != 0xff)
05497 DEBUG(0,("reply_lockingX: Error : pure oplock "
05498 "break is a chained %d request !\n",
05499 (unsigned int)CVAL(inbuf,smb_vwv0) ));
05500 END_PROFILE(SMBlockingX);
05501 return -1;
05502 }
05503 }
05504
05505
05506
05507
05508
05509
05510 release_level_2_oplocks_on_change(fsp);
05511
05512
05513
05514 for(i = 0; i < (int)num_ulocks; i++) {
05515 lock_pid = get_lock_pid( data, i, large_file_format);
05516 count = get_lock_count( data, i, large_file_format);
05517 offset = get_lock_offset( data, i, large_file_format, &err);
05518
05519
05520
05521
05522 if(err) {
05523 END_PROFILE(SMBlockingX);
05524 return ERROR_DOS(ERRDOS,ERRnoaccess);
05525 }
05526
05527 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
05528 "pid %u, file %s\n", (double)offset, (double)count,
05529 (unsigned int)lock_pid, fsp->fsp_name ));
05530
05531 status = do_unlock(fsp,
05532 lock_pid,
05533 count,
05534 offset,
05535 WINDOWS_LOCK);
05536
05537 if (NT_STATUS_V(status)) {
05538 END_PROFILE(SMBlockingX);
05539 return ERROR_NT(status);
05540 }
05541 }
05542
05543
05544
05545 if (!lp_blocking_locks(SNUM(conn))) {
05546 lock_timeout = 0;
05547 }
05548
05549
05550 data += ((large_file_format ? 20 : 10)*num_ulocks);
05551
05552
05553
05554
05555 for(i = 0; i < (int)num_locks; i++) {
05556 enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
05557 READ_LOCK:WRITE_LOCK);
05558 lock_pid = get_lock_pid( data, i, large_file_format);
05559 count = get_lock_count( data, i, large_file_format);
05560 offset = get_lock_offset( data, i, large_file_format, &err);
05561
05562
05563
05564
05565 if(err) {
05566 END_PROFILE(SMBlockingX);
05567 return ERROR_DOS(ERRDOS,ERRnoaccess);
05568 }
05569
05570 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
05571 "%u, file %s timeout = %d\n", (double)offset,
05572 (double)count, (unsigned int)lock_pid,
05573 fsp->fsp_name, (int)lock_timeout ));
05574
05575 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
05576 if (lp_blocking_locks(SNUM(conn))) {
05577
05578
05579
05580
05581
05582 if (!blocking_lock_cancel(fsp,
05583 lock_pid,
05584 offset,
05585 count,
05586 WINDOWS_LOCK,
05587 locktype,
05588 NT_STATUS_FILE_LOCK_CONFLICT)) {
05589 END_PROFILE(SMBlockingX);
05590 return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
05591 }
05592 }
05593
05594 status = do_lock_cancel(fsp,
05595 lock_pid,
05596 count,
05597 offset,
05598 WINDOWS_LOCK);
05599 } else {
05600 BOOL blocking_lock = lock_timeout ? True : False;
05601 BOOL defer_lock = False;
05602 struct byte_range_lock *br_lck;
05603 uint32 block_smbpid;
05604
05605 br_lck = do_lock(fsp,
05606 lock_pid,
05607 count,
05608 offset,
05609 lock_type,
05610 WINDOWS_LOCK,
05611 blocking_lock,
05612 &status,
05613 &block_smbpid);
05614
05615 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
05616
05617
05618 if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
05619 lock_timeout = lp_lock_spin_time();
05620 }
05621 defer_lock = True;
05622 }
05623
05624
05625
05626
05627
05628
05629 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
05630 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
05631 defer_lock = True;
05632 lock_timeout = lp_lock_spin_time();
05633 }
05634
05635 if (br_lck && defer_lock) {
05636
05637
05638
05639
05640
05641 if(push_blocking_lock_request(br_lck,
05642 inbuf, length,
05643 fsp,
05644 lock_timeout,
05645 i,
05646 lock_pid,
05647 lock_type,
05648 WINDOWS_LOCK,
05649 offset,
05650 count,
05651 block_smbpid)) {
05652 TALLOC_FREE(br_lck);
05653 END_PROFILE(SMBlockingX);
05654 return -1;
05655 }
05656 }
05657
05658 TALLOC_FREE(br_lck);
05659 }
05660
05661 if (NT_STATUS_V(status)) {
05662 END_PROFILE(SMBlockingX);
05663 return ERROR_NT(status);
05664 }
05665 }
05666
05667
05668
05669
05670 if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
05671 (i != num_locks) &&
05672 (num_locks != 0)) {
05673
05674
05675
05676
05677
05678 for(i--; i >= 0; i--) {
05679 lock_pid = get_lock_pid( data, i, large_file_format);
05680 count = get_lock_count( data, i, large_file_format);
05681 offset = get_lock_offset( data, i, large_file_format,
05682 &err);
05683
05684
05685
05686
05687
05688 if(err) {
05689 END_PROFILE(SMBlockingX);
05690 return ERROR_DOS(ERRDOS,ERRnoaccess);
05691 }
05692
05693 do_unlock(fsp,
05694 lock_pid,
05695 count,
05696 offset,
05697 WINDOWS_LOCK);
05698 }
05699 END_PROFILE(SMBlockingX);
05700 return ERROR_NT(status);
05701 }
05702
05703 set_message(outbuf,2,0,True);
05704
05705 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
05706 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
05707
05708 END_PROFILE(SMBlockingX);
05709 return chain_reply(inbuf,outbuf,length,bufsize);
05710 }
05711
05712 #undef DBGC_CLASS
05713 #define DBGC_CLASS DBGC_ALL
05714
05715
05716
05717
05718
05719 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
05720 {
05721 ssize_t nread = -1;
05722 ssize_t total_read;
05723 char *data;
05724 SMB_OFF_T startpos;
05725 int outsize;
05726 size_t maxcount;
05727 int max_per_packet;
05728 size_t tcount;
05729 int pad;
05730 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
05731 START_PROFILE(SMBreadBmpx);
05732
05733
05734 if (!lp_readbmpx()) {
05735 END_PROFILE(SMBreadBmpx);
05736 return ERROR_DOS(ERRSRV,ERRuseSTD);
05737 }
05738
05739 outsize = set_message(outbuf,8,0,True);
05740
05741 CHECK_FSP(fsp,conn);
05742 if (!CHECK_READ(fsp,inbuf)) {
05743 return(ERROR_DOS(ERRDOS,ERRbadaccess));
05744 }
05745
05746 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
05747 maxcount = SVAL(inbuf,smb_vwv3);
05748
05749 data = smb_buf(outbuf);
05750 pad = ((long)data)%4;
05751 if (pad)
05752 pad = 4 - pad;
05753 data += pad;
05754
05755 max_per_packet = bufsize-(outsize+pad);
05756 tcount = maxcount;
05757 total_read = 0;
05758
05759 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
05760 END_PROFILE(SMBreadBmpx);
05761 return ERROR_DOS(ERRDOS,ERRlock);
05762 }
05763
05764 do {
05765 size_t N = MIN(max_per_packet,tcount-total_read);
05766
05767 nread = read_file(fsp,data,startpos,N);
05768
05769 if (nread <= 0)
05770 nread = 0;
05771
05772 if (nread < (ssize_t)N)
05773 tcount = total_read + nread;
05774
05775 set_message(outbuf,8,nread+pad,False);
05776 SIVAL(outbuf,smb_vwv0,startpos);
05777 SSVAL(outbuf,smb_vwv2,tcount);
05778 SSVAL(outbuf,smb_vwv6,nread);
05779 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
05780
05781 show_msg(outbuf);
05782 if (!send_smb(smbd_server_fd(),outbuf))
05783 exit_server_cleanly("reply_readbmpx: send_smb failed.");
05784
05785 total_read += nread;
05786 startpos += nread;
05787 } while (total_read < (ssize_t)tcount);
05788
05789 END_PROFILE(SMBreadBmpx);
05790 return(-1);
05791 }
05792
05793
05794
05795
05796
05797 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
05798 {
05799 struct timespec ts[2];
05800 int outsize = 0;
05801 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
05802 START_PROFILE(SMBsetattrE);
05803
05804 outsize = set_message(outbuf,0,0,False);
05805
05806 if(!fsp || (fsp->conn != conn)) {
05807 END_PROFILE(SMBsetattrE);
05808 return ERROR_DOS(ERRDOS,ERRbadfid);
05809 }
05810
05811
05812
05813
05814
05815
05816 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3));
05817 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5));
05818
05819
05820
05821
05822
05823
05824 if (null_timespec(ts[0]) && null_timespec(ts[1])) {
05825
05826 if( DEBUGLVL( 3 ) ) {
05827 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
05828 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
05829 }
05830 END_PROFILE(SMBsetattrE);
05831 return(outsize);
05832 } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
05833
05834 ts[1] = ts[0];
05835 }
05836
05837
05838
05839 if(file_ntimes(conn, fsp->fsp_name, ts)) {
05840 END_PROFILE(SMBsetattrE);
05841 return ERROR_DOS(ERRDOS,ERRnoaccess);
05842 }
05843
05844 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
05845 fsp->fnum,
05846 (unsigned int)ts[0].tv_sec,
05847 (unsigned int)ts[1].tv_sec));
05848
05849 END_PROFILE(SMBsetattrE);
05850 return(outsize);
05851 }
05852
05853
05854
05855
05856
05857
05858
05859
05860 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
05861 {
05862 size_t numtowrite;
05863 ssize_t nwritten = -1;
05864 int outsize = 0;
05865 SMB_OFF_T startpos;
05866 size_t tcount;
05867 BOOL write_through;
05868 int smb_doff;
05869 char *data;
05870 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
05871 NTSTATUS status;
05872 START_PROFILE(SMBwriteBmpx);
05873
05874 CHECK_FSP(fsp,conn);
05875 if (!CHECK_WRITE(fsp)) {
05876 return(ERROR_DOS(ERRDOS,ERRbadaccess));
05877 }
05878 if (HAS_CACHED_ERROR(fsp)) {
05879 return(CACHED_ERROR(fsp));
05880 }
05881
05882 tcount = SVAL(inbuf,smb_vwv1);
05883 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
05884 write_through = BITSETW(inbuf+smb_vwv7,0);
05885 numtowrite = SVAL(inbuf,smb_vwv10);
05886 smb_doff = SVAL(inbuf,smb_vwv11);
05887
05888 data = smb_base(inbuf) + smb_doff;
05889
05890
05891
05892 SCVAL(outbuf,smb_com,SMBwritec);
05893
05894 if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
05895 END_PROFILE(SMBwriteBmpx);
05896 return(ERROR_DOS(ERRDOS,ERRlock));
05897 }
05898
05899 nwritten = write_file(fsp,data,startpos,numtowrite);
05900
05901 status = sync_file(conn, fsp, write_through);
05902 if (!NT_STATUS_IS_OK(status)) {
05903 END_PROFILE(SMBwriteBmpx);
05904 DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
05905 fsp->fsp_name, nt_errstr(status) ));
05906 return ERROR_NT(status);
05907 }
05908
05909 if(nwritten < (ssize_t)numtowrite) {
05910 END_PROFILE(SMBwriteBmpx);
05911 return(UNIXERROR(ERRHRD,ERRdiskfull));
05912 }
05913
05914
05915
05916
05917
05918
05919 if((ssize_t)tcount > nwritten) {
05920 write_bmpx_struct *wbms;
05921 if(fsp->wbmpx_ptr != NULL)
05922 wbms = fsp->wbmpx_ptr;
05923 else
05924 wbms = SMB_MALLOC_P(write_bmpx_struct);
05925 if(!wbms) {
05926 DEBUG(0,("Out of memory in reply_readmpx\n"));
05927 END_PROFILE(SMBwriteBmpx);
05928 return(ERROR_DOS(ERRSRV,ERRnoresource));
05929 }
05930 wbms->wr_mode = write_through;
05931 wbms->wr_discard = False;
05932 wbms->wr_total_written = nwritten;
05933 wbms->wr_errclass = 0;
05934 wbms->wr_error = 0;
05935 fsp->wbmpx_ptr = wbms;
05936 }
05937
05938
05939
05940 SCVAL(outbuf,smb_com,SMBwriteBmpx);
05941
05942 outsize = set_message(outbuf,1,0,True);
05943
05944 SSVALS(outbuf,smb_vwv0,-1);
05945
05946 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
05947 fsp->fnum, (int)numtowrite, (int)nwritten ) );
05948
05949 if (write_through && tcount==nwritten) {
05950
05951 smb_setlen(outbuf,outsize - 4);
05952 show_msg(outbuf);
05953 if (!send_smb(smbd_server_fd(),outbuf))
05954 exit_server_cleanly("reply_writebmpx: send_smb failed.");
05955
05956
05957 outsize = set_message(outbuf,1,0,True);
05958 SCVAL(outbuf,smb_com,SMBwritec);
05959 SSVAL(outbuf,smb_vwv0,nwritten);
05960 }
05961
05962 END_PROFILE(SMBwriteBmpx);
05963 return(outsize);
05964 }
05965
05966
05967
05968
05969
05970 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
05971 {
05972 size_t numtowrite;
05973 ssize_t nwritten = -1;
05974 int outsize = 0;
05975 SMB_OFF_T startpos;
05976 size_t tcount;
05977 BOOL write_through;
05978 int smb_doff;
05979 char *data;
05980 write_bmpx_struct *wbms;
05981 BOOL send_response = False;
05982 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
05983 NTSTATUS status;
05984 START_PROFILE(SMBwriteBs);
05985
05986 CHECK_FSP(fsp,conn);
05987 if (!CHECK_WRITE(fsp)) {
05988 return(ERROR_DOS(ERRDOS,ERRbadaccess));
05989 }
05990
05991 tcount = SVAL(inbuf,smb_vwv1);
05992 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
05993 numtowrite = SVAL(inbuf,smb_vwv6);
05994 smb_doff = SVAL(inbuf,smb_vwv7);
05995
05996 data = smb_base(inbuf) + smb_doff;
05997
05998
05999 SCVAL(outbuf,smb_com,SMBwritec);
06000
06001
06002
06003 wbms = fsp->wbmpx_ptr;
06004 if(!wbms) {
06005 END_PROFILE(SMBwriteBs);
06006 return(-1);
06007 }
06008
06009
06010 write_through = wbms->wr_mode;
06011
06012
06013 if(wbms->wr_discard) {
06014 END_PROFILE(SMBwriteBs);
06015 return -1;
06016 }
06017
06018 nwritten = write_file(fsp,data,startpos,numtowrite);
06019
06020 status = sync_file(conn, fsp, write_through);
06021
06022 if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
06023 if(write_through) {
06024
06025 if (wbms)
06026 free((char *)wbms);
06027 fsp->wbmpx_ptr = NULL;
06028 END_PROFILE(SMBwriteBs);
06029 return(ERROR_DOS(ERRHRD,ERRdiskfull));
06030 }
06031 wbms->wr_errclass = ERRHRD;
06032 wbms->wr_error = ERRdiskfull;
06033 wbms->wr_status = NT_STATUS_DISK_FULL;
06034 wbms->wr_discard = True;
06035 END_PROFILE(SMBwriteBs);
06036 return -1;
06037 }
06038
06039
06040
06041 wbms->wr_total_written += nwritten;
06042 if(wbms->wr_total_written >= tcount) {
06043 if (write_through) {
06044 outsize = set_message(outbuf,1,0,True);
06045 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
06046 send_response = True;
06047 }
06048
06049 free((char *)wbms);
06050 fsp->wbmpx_ptr = NULL;
06051 }
06052
06053 if(send_response) {
06054 END_PROFILE(SMBwriteBs);
06055 return(outsize);
06056 }
06057
06058 END_PROFILE(SMBwriteBs);
06059 return(-1);
06060 }
06061
06062
06063
06064
06065
06066 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
06067 {
06068 SMB_STRUCT_STAT sbuf;
06069 int outsize = 0;
06070 int mode;
06071 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
06072 START_PROFILE(SMBgetattrE);
06073
06074 outsize = set_message(outbuf,11,0,True);
06075
06076 if(!fsp || (fsp->conn != conn)) {
06077 END_PROFILE(SMBgetattrE);
06078 return ERROR_DOS(ERRDOS,ERRbadfid);
06079 }
06080
06081
06082 if(fsp_stat(fsp, &sbuf)) {
06083 END_PROFILE(SMBgetattrE);
06084 return(UNIXERROR(ERRDOS,ERRnoaccess));
06085 }
06086
06087 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
06088
06089
06090
06091
06092
06093
06094
06095 srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
06096 srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
06097
06098 srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
06099
06100 if (mode & aDIR) {
06101 SIVAL(outbuf,smb_vwv6,0);
06102 SIVAL(outbuf,smb_vwv8,0);
06103 } else {
06104 uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
06105 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
06106 SIVAL(outbuf,smb_vwv8,allocation_size);
06107 }
06108 SSVAL(outbuf,smb_vwv10, mode);
06109
06110 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
06111
06112 END_PROFILE(SMBgetattrE);
06113 return(outsize);
06114 }