00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdOfsCVSID = "$Id: XrdOfs.cc 38011 2011-02-08 18:35:57Z ganis $";
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <unistd.h>
00031 #include <dirent.h>
00032 #include <errno.h>
00033 #include <fcntl.h>
00034 #include <memory.h>
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <time.h>
00038 #include <netdb.h>
00039 #include <stdlib.h>
00040 #include <sys/param.h>
00041 #include <sys/stat.h>
00042 #include <sys/time.h>
00043 #include <sys/types.h>
00044
00045 #include "XrdVersion.hh"
00046
00047 #include "XrdOfs/XrdOfs.hh"
00048 #include "XrdOfs/XrdOfsEvs.hh"
00049 #include "XrdOfs/XrdOfsPoscq.hh"
00050 #include "XrdOfs/XrdOfsTrace.hh"
00051 #include "XrdOfs/XrdOfsSecurity.hh"
00052 #include "XrdOfs/XrdOfsStats.hh"
00053
00054 #include "XrdCms/XrdCmsClient.hh"
00055
00056 #include "XrdOss/XrdOss.hh"
00057
00058 #include "XrdNet/XrdNetDNS.hh"
00059
00060 #include "XrdSys/XrdSysHeaders.hh"
00061 #include "XrdOuc/XrdOuca2x.hh"
00062 #include "XrdOuc/XrdOucEnv.hh"
00063 #include "XrdSys/XrdSysError.hh"
00064 #include "XrdOuc/XrdOucLock.hh"
00065 #include "XrdSys/XrdSysLogger.hh"
00066 #include "XrdOuc/XrdOucMsubs.hh"
00067 #include "XrdSys/XrdSysPlatform.hh"
00068 #include "XrdSys/XrdSysPthread.hh"
00069 #include "XrdOuc/XrdOucTList.hh"
00070 #include "XrdOuc/XrdOucTrace.hh"
00071 #include "XrdSec/XrdSecEntity.hh"
00072 #include "XrdSfs/XrdSfsAio.hh"
00073 #include "XrdSfs/XrdSfsInterface.hh"
00074
00075 #ifdef AIX
00076 #include <sys/mode.h>
00077 #endif
00078
00079
00080
00081
00082
00083 XrdSysError OfsEroute(0);
00084
00085 XrdOucTrace OfsTrace(&OfsEroute);
00086
00087
00088
00089
00090
00091 XrdOfsStats OfsStats;
00092
00093
00094
00095
00096
00097 XrdOfsHandle *XrdOfs::dummyHandle;
00098
00099 int XrdOfs::MaxDelay = 60;
00100 int XrdOfs::OSSDelay = 30;
00101
00102
00103
00104
00105
00106 extern XrdOfs XrdOfsFS;
00107
00108
00109
00110
00111
00112 XrdOss *XrdOfsOss;
00113
00114
00115
00116
00117
00118 XrdOfs::XrdOfs()
00119 {
00120 unsigned int myIPaddr = 0;
00121 char buff[256], *bp;
00122 int i;
00123
00124
00125
00126 Authorization = 0;
00127 Finder = 0;
00128 Balancer = 0;
00129 evsObject = 0;
00130 myRole = strdup("server");
00131 myPort = 0;
00132
00133
00134
00135 poscQ = 0;
00136 poscLog = 0;
00137 poscHold= 10*60;
00138 poscAuto= 0;
00139
00140
00141
00142 HostName = XrdNetDNS::getHostName();
00143 if (!XrdNetDNS::Host2IP(HostName, &myIPaddr)) myIPaddr = 0x7f000001;
00144 strcpy(buff, "[::"); bp = buff+3;
00145 bp += XrdNetDNS::IP2String(myIPaddr, 0, bp, 128);
00146 *bp++ = ']'; *bp++ = ':';
00147 sprintf(bp, "%d", myPort);
00148 locResp = strdup(buff); locRlen = strlen(buff);
00149 for (i = 0; HostName[i] && HostName[i] != '.'; i++);
00150 HostName[i] = '\0';
00151 HostPref = strdup(HostName);
00152 HostName[i] = '.';
00153
00154
00155
00156 ConfigFN = 0;
00157 XrdOfsHandle::Alloc(&dummyHandle);
00158 }
00159
00160
00161
00162
00163
00164 XrdOfsFile::XrdOfsFile(const char *user) : XrdSfsFile(user)
00165 {
00166 oh = XrdOfs::dummyHandle;
00167 dorawio = 0;
00168 viaDel = 0;
00169 tident = (user ? user : "");
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 int XrdOfsDirectory::open(const char *dir_path,
00182 const XrdSecEntity *client,
00183 const char *info)
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 {
00199 EPNAME("opendir");
00200 XrdOucEnv Open_Env(info,0,client);
00201 int retc;
00202
00203
00204
00205 XTRACE(opendir, dir_path, "");
00206
00207
00208
00209 if (dp) return
00210 XrdOfsFS.Emsg(epname, error, EADDRINUSE, "open directory", dir_path);
00211
00212
00213
00214 AUTHORIZE(client,&Open_Env,AOP_Readdir,"open directory",dir_path,error);
00215
00216
00217
00218 if (!(dp = XrdOfsOss->newDir(tident))) retc = -ENOMEM;
00219 else if (!(retc = dp->Opendir(dir_path)))
00220 {fname = strdup(dir_path);
00221 return SFS_OK;
00222 }
00223 else {delete dp; dp = 0;}
00224
00225
00226
00227 return XrdOfsFS.Emsg(epname, error, retc, "open directory", dir_path);
00228 }
00229
00230
00231
00232
00233
00234 const char *XrdOfsDirectory::nextEntry()
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 {
00255 EPNAME("readdir");
00256 int retc;
00257
00258
00259
00260 if (!dp) {XrdOfsFS.Emsg(epname, error, EBADF, "read directory");
00261 return 0;
00262 }
00263
00264
00265
00266 if (atEOF) return 0;
00267
00268
00269
00270 if ((retc = dp->Readdir(dname, sizeof(dname))) < 0)
00271 {XrdOfsFS.Emsg(epname, error, retc, "read directory", fname);
00272 return 0;
00273 }
00274
00275
00276
00277 if (!*dname)
00278 {atEOF = 1;
00279 error.clear();
00280 XTRACE(readdir, fname, "<eof>");
00281 return 0;
00282 }
00283
00284
00285
00286 XTRACE(readdir, fname, dname);
00287 return (const char *)(dname);
00288 }
00289
00290
00291
00292
00293
00294 int XrdOfsDirectory::close()
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 {
00308 EPNAME("closedir");
00309 int retc;
00310
00311
00312
00313 if (!dp) {XrdOfsFS.Emsg(epname, error, EBADF, "close directory");
00314 return SFS_ERROR;
00315 }
00316 XTRACE(closedir, fname, "");
00317
00318
00319
00320 if ((retc = dp->Close()))
00321 retc = XrdOfsFS.Emsg(epname, error, retc, "close", fname);
00322 else retc = SFS_OK;
00323
00324
00325
00326 delete dp;
00327 dp = 0;
00328 free(fname);
00329 fname = 0;
00330 return retc;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 int XrdOfsFile::open(const char *path,
00343 XrdSfsFileOpenMode open_mode,
00344 mode_t Mode,
00345 const XrdSecEntity *client,
00346 const char *info)
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 {
00371 EPNAME("open");
00372 static const int crMask = (SFS_O_CREAT | SFS_O_TRUNC);
00373 static const int opMask = (SFS_O_RDONLY | SFS_O_WRONLY | SFS_O_RDWR);
00374
00375 struct OpenHelper
00376 {const char *Path;
00377 XrdOfsHandle *hP;
00378 XrdOssDF *fP;
00379 int poscNum;
00380
00381 int OK() {hP = 0; fP = 0; poscNum = 0; return SFS_OK;}
00382
00383 OpenHelper(const char *path)
00384 : Path(path), hP(0), fP(0), poscNum(0) {}
00385
00386 ~OpenHelper()
00387 {if (hP) hP->Retire();
00388 if (fP) delete fP;
00389 if (poscNum > 0) XrdOfsFS.poscQ->Del(Path, poscNum, 1);
00390 }
00391 } oP(path);
00392
00393 mode_t theMode = Mode & S_IAMB;
00394 int retc, isPosc = 0, crOpts = 0, isRW = 0, open_flag = 0;
00395 int find_flag = open_mode & (SFS_O_NOWAIT | SFS_O_RESET);
00396 XrdOucEnv Open_Env(info,0,client);
00397
00398
00399
00400 ZTRACE(open, std::hex <<open_mode <<"-" <<std::oct <<Mode <<std::dec <<" fn=" <<path);
00401
00402
00403
00404 XrdOfsFS.ocMutex.Lock();
00405 if (oh != XrdOfs::dummyHandle)
00406 {XrdOfsFS.ocMutex.UnLock();
00407 return XrdOfsFS.Emsg(epname,error,EADDRINUSE,"open file",path);
00408 }
00409 XrdOfsFS.ocMutex.UnLock();
00410
00411
00412
00413 if (open_mode & crMask)
00414 {crOpts = (Mode & SFS_O_MKPTH ? XRDOSS_mkpath : 0);
00415 if (XrdOfsFS.poscQ && ((open_mode & SFS_O_POSC) ||
00416 XrdOfsFS.poscAuto || Open_Env.Get("ofs.posc")))
00417 {isPosc = 1; isRW = XrdOfsHandle::opPC;}
00418 else isRW = XrdOfsHandle::opRW;
00419 if (open_mode & SFS_O_CREAT)
00420 {open_flag = O_RDWR | O_CREAT | O_EXCL;
00421 find_flag |= SFS_O_RDWR | SFS_O_CREAT | (open_mode & SFS_O_REPLICA);
00422 crOpts |= XRDOSS_new;
00423 } else {
00424 open_flag |= O_RDWR | O_CREAT | O_TRUNC;
00425 find_flag |= SFS_O_RDWR | SFS_O_TRUNC;
00426 }
00427 }
00428 else
00429 switch(open_mode & opMask)
00430 {case SFS_O_RDONLY: open_flag = O_RDONLY; find_flag |= SFS_O_RDONLY;
00431 break;
00432 case SFS_O_WRONLY: open_flag = O_WRONLY; find_flag |= SFS_O_WRONLY;
00433 isRW = XrdOfsHandle::opRW;
00434 if (XrdOfsFS.poscQ && ((open_mode & SFS_O_POSC) ||
00435 Open_Env.Get("ofs.posc"))) oP.poscNum = -1;
00436 break;
00437 case SFS_O_RDWR: open_flag = O_RDWR; find_flag |= SFS_O_RDWR;
00438 isRW = XrdOfsHandle::opRW;
00439 if (XrdOfsFS.poscQ && ((open_mode & SFS_O_POSC) ||
00440 Open_Env.Get("ofs.posc"))) oP.poscNum = -1;
00441 break;
00442 default: open_flag = O_RDONLY; find_flag |= SFS_O_RDONLY;
00443 break;
00444 }
00445
00446
00447
00448
00449
00450 if (XrdOfsFS.Finder && (retc = XrdOfsFS.Finder->Locate(error, path,
00451 find_flag, &Open_Env)))
00452 return XrdOfsFS.fsError(error, retc);
00453
00454
00455
00456 if (open_flag & O_CREAT)
00457 {
00458
00459 AUTHORIZE(client,&Open_Env,AOP_Create,"create",path,error);
00460 OOIDENTENV(client, Open_Env);
00461
00462
00463
00464 if (isPosc && (oP.poscNum = XrdOfsFS.poscQ->Add(tident,path)) < 0)
00465 return XrdOfsFS.Emsg(epname, error, oP.poscNum, "pcreate", path);
00466
00467
00468
00469
00470 if ((retc = XrdOfsOss->Create(tident, path, theMode, Open_Env,
00471 ((open_flag << 8) | crOpts))))
00472 {if (retc > 0) return XrdOfsFS.Stall(error, retc, path);
00473 if (retc == -EINPROGRESS)
00474 {XrdOfsFS.evrObject.Wait4Event(path,&error);
00475 return XrdOfsFS.fsError(error, retc);
00476 }
00477 if (retc != -ENOTSUP)
00478 {if (XrdOfsFS.Balancer) XrdOfsFS.Balancer->Removed(path);
00479 return XrdOfsFS.Emsg(epname, error, retc, "create", path);
00480 }
00481 } else {
00482 if (XrdOfsFS.Balancer) XrdOfsFS.Balancer->Added(path, isPosc);
00483 open_flag = O_RDWR|O_TRUNC;
00484 if (XrdOfsFS.evsObject
00485 && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Create))
00486 {XrdOfsEvsInfo evInfo(tident,path,info,&Open_Env,Mode);
00487 XrdOfsFS.evsObject->Notify(XrdOfsEvs::Create, evInfo);
00488 }
00489 }
00490
00491 } else {
00492
00493
00494
00495 AUTHORIZE(client,&Open_Env,(isRW?AOP_Update:AOP_Read),"open",path,error);
00496 OOIDENTENV(client, Open_Env);
00497 }
00498
00499
00500
00501 if ((retc = XrdOfsHandle::Alloc(path, isRW, &oP.hP)))
00502 {if (retc > 0) return XrdOfsFS.Stall(error, retc, path);
00503 return XrdOfsFS.Emsg(epname, error, retc, "attach", path);
00504 }
00505
00506
00507
00508
00509 if (oP.hP->isRW == XrdOfsHandle::opPC)
00510 {if (!isRW) return XrdOfsFS.Stall(error, -1, path);
00511 if ((retc = oP.hP->PoscSet(tident, oP.poscNum, theMode)))
00512 {if (retc > 0) XrdOfsFS.poscQ->Del(path, retc);
00513 else return XrdOfsFS.Emsg(epname, error, retc, "access", path);
00514 }
00515 }
00516
00517
00518
00519 if (!(oP.hP->Inactive()))
00520 {dorawio = (oh->isCompressed && open_mode & SFS_O_RAWIO ? 1 : 0);
00521 XrdOfsFS.ocMutex.Lock(); oh = oP.hP; XrdOfsFS.ocMutex.UnLock();
00522 FTRACE(open, "attach use=" <<oh->Usage());
00523 if (oP.poscNum > 0) XrdOfsFS.poscQ->Commit(path, oP.poscNum);
00524 oP.hP->UnLock();
00525 OfsStats.sdMutex.Lock();
00526 isRW ? OfsStats.Data.numOpenW++ : OfsStats.Data.numOpenR++;
00527 if (oP.poscNum > 0) OfsStats.Data.numOpenP++;
00528 OfsStats.sdMutex.UnLock();
00529 return oP.OK();
00530 }
00531
00532
00533
00534 if (!(oP.fP = XrdOfsOss->newFile(tident)))
00535 return XrdOfsFS.Emsg(epname, error, ENOMEM, "open", path);
00536
00537
00538
00539 if ((retc = oP.fP->Open(path, open_flag, Mode, Open_Env)))
00540 {if (retc > 0) return XrdOfsFS.Stall(error, retc, path);
00541 if (retc == -EINPROGRESS)
00542 {XrdOfsFS.evrObject.Wait4Event(path,&error);
00543 return XrdOfsFS.fsError(error, retc);
00544 }
00545 if (retc == -ETXTBSY) return XrdOfsFS.Stall(error, -1, path);
00546 if (XrdOfsFS.Balancer) XrdOfsFS.Balancer->Removed(path);
00547 return XrdOfsFS.Emsg(epname, error, retc, "open", path);
00548 }
00549
00550
00551
00552 if (oP.poscNum > 0)
00553 {if ((retc = oP.fP->Fchmod(static_cast<mode_t>(theMode | S_ISUID))))
00554 return XrdOfsFS.Emsg(epname, error, retc, "fchmod", path);
00555 XrdOfsFS.poscQ->Commit(path, oP.poscNum);
00556 }
00557
00558
00559
00560 if (oP.fP->isCompressed())
00561 {oP.hP->isCompressed = 1;
00562 dorawio = (open_mode & SFS_O_RAWIO ? 1 : 0);
00563 }
00564 oP.hP->Activate(oP.fP);
00565 oP.hP->UnLock();
00566
00567
00568
00569 if (XrdOfsFS.evsObject)
00570 {XrdOfsEvs::Event theEvent = (isRW ? XrdOfsEvs::Openw : XrdOfsEvs::Openr);
00571 if (XrdOfsFS.evsObject->Enabled(theEvent))
00572 {XrdOfsEvsInfo evInfo(tident, path, info, &Open_Env);
00573 XrdOfsFS.evsObject->Notify(theEvent, evInfo);
00574 }
00575 }
00576
00577
00578
00579 OfsStats.sdMutex.Lock();
00580 isRW ? OfsStats.Data.numOpenW++ : OfsStats.Data.numOpenR++;
00581 if (oP.poscNum > 0) OfsStats.Data.numOpenP++;
00582 OfsStats.sdMutex.UnLock();
00583
00584
00585
00586 XrdOfsFS.ocMutex.Lock(); oh = oP.hP; XrdOfsFS.ocMutex.UnLock();
00587 return oP.OK();
00588 }
00589
00590
00591
00592
00593
00594 int XrdOfsFile::close()
00595
00596
00597
00598
00599
00600
00601
00602 {
00603 EPNAME("close");
00604
00605 class CloseFH : public XrdOfsHanCB
00606 {public: void Retired(XrdOfsHandle *hP) {XrdOfsFS.Unpersist(hP);}};
00607 static XrdOfsHanCB *hCB = static_cast<XrdOfsHanCB *>(new CloseFH);
00608
00609 XrdOfsHandle *hP;
00610 int poscNum, retc;
00611 short theMode;
00612
00613
00614
00615 FTRACE(close, "use=" <<oh->Usage());
00616
00617
00618
00619 XrdOfsFS.ocMutex.Lock();
00620 if (oh == XrdOfs::dummyHandle)
00621 {XrdOfsFS.ocMutex.UnLock(); return SFS_OK;}
00622 if ((oh->Inactive()))
00623 {XrdOfsFS.ocMutex.UnLock();
00624 return XrdOfsFS.Emsg(epname, error, EBADF, "close file");
00625 }
00626 hP = oh; oh = XrdOfs::dummyHandle;
00627 XrdOfsFS.ocMutex.UnLock();
00628 hP->Lock();
00629
00630
00631
00632 OfsStats.sdMutex.Lock();
00633 if (!(hP->isRW)) OfsStats.Data.numOpenR--;
00634 else {OfsStats.Data.numOpenW--;
00635 if (hP->isRW == XrdOfsHandle::opPC) OfsStats.Data.numOpenP--;
00636 }
00637 OfsStats.sdMutex.UnLock();
00638
00639
00640
00641
00642
00643 if ((poscNum = hP->PoscGet(theMode, !viaDel)))
00644 {if (viaDel)
00645 {if (hP->Inactive() || !XrdOfsFS.poscHold)
00646 {XrdOfsFS.Unpersist(hP, !hP->Inactive()); hP->Retire();}
00647 else hP->Retire(hCB, XrdOfsFS.poscHold);
00648 return SFS_OK;
00649 }
00650 if ((retc = hP->Select().Fchmod(theMode)))
00651 XrdOfsFS.Emsg(epname, error, retc, "fchmod", hP->Name());
00652 else {XrdOfsFS.poscQ->Del(hP->Name(), poscNum);
00653 if (XrdOfsFS.Balancer) XrdOfsFS.Balancer->Added(hP->Name());
00654 }
00655 }
00656
00657
00658
00659
00660
00661
00662
00663 if (XrdOfsFS.evsObject && tident
00664 && XrdOfsFS.evsObject->Enabled(hP->isRW ? XrdOfsEvs::Closew
00665 : XrdOfsEvs::Closer))
00666 {long long FSize, *retsz;
00667 char pathbuff[MAXPATHLEN+8];
00668 XrdOfsEvs::Event theEvent;
00669 if (hP->isRW) {theEvent = XrdOfsEvs::Closew; retsz = &FSize;}
00670 else { theEvent = XrdOfsEvs::Closer; retsz = 0; FSize=0;}
00671 if (!(hP->Retire(retsz, pathbuff, sizeof(pathbuff))))
00672 {XrdOfsEvsInfo evInfo(tident, pathbuff, "" , 0, 0, FSize);
00673 XrdOfsFS.evsObject->Notify(theEvent, evInfo);
00674 } else hP->Retire();
00675 } else hP->Retire();
00676
00677
00678
00679 return SFS_OK;
00680 }
00681
00682
00683
00684
00685
00686 int XrdOfsFile::fctl(const int cmd,
00687 const char *args,
00688 XrdOucErrInfo &out_error)
00689 {
00690
00691
00692 if (cmd == SFS_FCTL_GETFD)
00693 {out_error.setErrCode(oh->Select().getFD());
00694 return SFS_OK;
00695 }
00696
00697
00698
00699 out_error.setErrInfo(EEXIST, "fctl operation not supported");
00700 return SFS_ERROR;
00701 }
00702
00703
00704
00705
00706
00707 int XrdOfsFile::read(XrdSfsFileOffset offset,
00708 XrdSfsXferSize blen)
00709
00710
00711
00712
00713
00714
00715
00716
00717 {
00718 EPNAME("read");
00719 int retc;
00720
00721
00722
00723 FTRACE(read, "preread " <<blen <<"@" <<offset);
00724
00725
00726
00727 #if _FILE_OFFSET_BITS!=64
00728 if (offset > 0x000000007fffffff)
00729 return XrdOfsFS.Emsg(epname, error, EFBIG, "read", oh->Name());
00730 #endif
00731
00732
00733
00734 if ((retc = oh->Select().Read((off_t)offset, (size_t)blen)) < 0)
00735 return XrdOfsFS.Emsg(epname, error, (int)retc, "preread", oh->Name());
00736
00737
00738
00739 return retc;
00740 }
00741
00742
00743
00744
00745
00746 XrdSfsXferSize XrdOfsFile::read(XrdSfsFileOffset offset,
00747 char *buff,
00748 XrdSfsXferSize blen)
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 {
00761 EPNAME("read");
00762 XrdSfsXferSize nbytes;
00763
00764
00765
00766 FTRACE(read, blen <<"@" <<offset);
00767
00768
00769
00770 #if _FILE_OFFSET_BITS!=64
00771 if (offset > 0x000000007fffffff)
00772 return XrdOfsFS.Emsg(epname, error, EFBIG, "read", oh->Name());
00773 #endif
00774
00775
00776
00777 nbytes = (dorawio ?
00778 (XrdSfsXferSize)(oh->Select().ReadRaw((void *)buff,
00779 (off_t)offset, (size_t)blen))
00780 : (XrdSfsXferSize)(oh->Select().Read((void *)buff,
00781 (off_t)offset, (size_t)blen)));
00782 if (nbytes < 0)
00783 return XrdOfsFS.Emsg(epname, error, (int)nbytes, "read", oh->Name());
00784
00785
00786
00787 return nbytes;
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 int XrdOfsFile::read(XrdSfsAio *aiop)
00804 {
00805 EPNAME("aioread");
00806 int rc;
00807
00808
00809
00810 if (oh->isCompressed)
00811 {aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
00812 (char *)aiop->sfsAio.aio_buf,
00813 (XrdSfsXferSize)aiop->sfsAio.aio_nbytes);
00814 aiop->doneRead();
00815 return 0;
00816 }
00817
00818
00819
00820 FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
00821
00822
00823
00824 #if _FILE_OFFSET_BITS!=64
00825 if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
00826 return XrdOfsFS.Emsg(epname, error, EFBIG, "read", oh->Name());
00827 #endif
00828
00829
00830
00831 if ((rc = oh->Select().Read(aiop)) < 0)
00832 return XrdOfsFS.Emsg(epname, error, rc, "read", oh->Name());
00833
00834
00835
00836 return SFS_OK;
00837 }
00838
00839
00840
00841
00842
00843 XrdSfsXferSize XrdOfsFile::write(XrdSfsFileOffset offset,
00844 const char *buff,
00845 XrdSfsXferSize blen)
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 {
00861 EPNAME("write");
00862 XrdSfsXferSize nbytes;
00863
00864
00865
00866 FTRACE(write, blen <<"@" <<offset);
00867
00868
00869
00870 #if _FILE_OFFSET_BITS!=64
00871 if (offset > 0x000000007fffffff)
00872 return XrdOfsFS.Emsg(epname, error, EFBIG, "write", oh);
00873 #endif
00874
00875
00876
00877 if (XrdOfsFS.evsObject && !(oh->isChanged)
00878 && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
00879
00880
00881
00882 oh->isPending = 1;
00883 nbytes = (XrdSfsXferSize)(oh->Select().Write((const void *)buff,
00884 (off_t)offset, (size_t)blen));
00885 if (nbytes < 0)
00886 return XrdOfsFS.Emsg(epname, error, (int)nbytes, "write", oh);
00887
00888
00889
00890 return nbytes;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899 int XrdOfsFile::write(XrdSfsAio *aiop)
00900 {
00901 EPNAME("aiowrite");
00902 int rc;
00903
00904
00905
00906 FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
00907
00908
00909
00910
00911 if (oh->isRW == XrdOfsHandle::opPC)
00912 {aiop->Result = this->write(aiop->sfsAio.aio_offset,
00913 (const char *)aiop->sfsAio.aio_buf,
00914 aiop->sfsAio.aio_nbytes);
00915 aiop->doneWrite();
00916 return 0;
00917 }
00918
00919
00920
00921 #if _FILE_OFFSET_BITS!=64
00922 if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
00923 return XrdOfsFS.Emsg(epname, error, EFBIG, "write", oh->Name());
00924 #endif
00925
00926
00927
00928 if (XrdOfsFS.evsObject && !(oh->isChanged)
00929 && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
00930
00931
00932
00933 oh->isPending = 1;
00934 if ((rc = oh->Select().Write(aiop)) < 0)
00935 return XrdOfsFS.Emsg(epname, error, rc, "write", oh->Name());
00936
00937
00938
00939 return SFS_OK;
00940 }
00941
00942
00943
00944
00945
00946 int XrdOfsFile::getMmap(void **Addr, off_t &Size)
00947
00948
00949
00950
00951
00952
00953
00954 {
00955
00956
00957
00958 Size = oh->Select().getMmap(Addr);
00959
00960 return SFS_OK;
00961 }
00962
00963
00964
00965
00966
00967 int XrdOfsFile::stat(struct stat *buf)
00968
00969
00970
00971
00972
00973
00974
00975 {
00976 EPNAME("fstat");
00977 int retc;
00978
00979
00980
00981 FTRACE(stat, "");
00982
00983
00984
00985 if ((retc = oh->Select().Fstat(buf)) < 0)
00986 return XrdOfsFS.Emsg(epname,error,retc,"get state for",oh->Name());
00987
00988 return SFS_OK;
00989 }
00990
00991
00992
00993
00994
00995 int XrdOfsFile::sync()
00996
00997
00998
00999
01000
01001
01002
01003 {
01004 EPNAME("sync");
01005 int retc;
01006
01007
01008
01009 FTRACE(sync, "");
01010
01011
01012
01013
01014 if (!(oh->isPending)) return SFS_OK;
01015
01016
01017
01018
01019 oh->Lock();
01020 oh->isPending = 0;
01021 oh->UnLock();
01022
01023
01024
01025 if ((retc = oh->Select().Fsync()))
01026 {oh->isPending = 1;
01027 return XrdOfsFS.Emsg(epname, error, retc, "synchronize", oh);
01028 }
01029
01030
01031
01032 return SFS_OK;
01033 }
01034
01035
01036
01037
01038
01039
01040
01041 int XrdOfsFile::sync(XrdSfsAio *aiop)
01042 {
01043 aiop->Result = this->sync();
01044 aiop->doneWrite();
01045 return 0;
01046 }
01047
01048
01049
01050
01051
01052 int XrdOfsFile::truncate(XrdSfsFileOffset flen)
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066 {
01067 EPNAME("trunc");
01068 int retc;
01069
01070
01071
01072 FTRACE(truncate, "len=" <<flen);
01073
01074
01075
01076 if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
01077 return XrdOfsFS.Emsg(epname, error, EFBIG, "truncate", oh);
01078
01079
01080
01081 if (XrdOfsFS.evsObject && !(oh->isChanged)
01082 && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
01083
01084
01085
01086 oh->isPending = 1;
01087 if ((retc = oh->Select().Ftruncate(flen)))
01088 return XrdOfsFS.Emsg(epname, error, retc, "truncate", oh);
01089
01090
01091
01092 return SFS_OK;
01093 }
01094
01095
01096
01097
01098
01099 int XrdOfsFile::getCXinfo(char cxtype[4], int &cxrsz)
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 {
01111
01112
01113
01114 cxrsz = oh->Select().isCompressed(cxtype);
01115 return SFS_OK;
01116 }
01117
01118
01119
01120
01121
01122
01123
01124
01125 void XrdOfsFile::GenFWEvent()
01126 {
01127 int first_write;
01128
01129
01130
01131
01132 oh->Lock();
01133 if ((first_write = !(oh->isChanged))) oh->isChanged = 1;
01134 oh->UnLock();
01135 if (first_write)
01136 {XrdOfsEvsInfo evInfo(tident, oh->Name());
01137 XrdOfsFS.evsObject->Notify(XrdOfsEvs::Fwrite, evInfo);
01138 }
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150 int XrdOfs::chmod(const char *path,
01151 XrdSfsMode Mode,
01152 XrdOucErrInfo &einfo,
01153 const XrdSecEntity *client,
01154 const char *info)
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165 {
01166 EPNAME("chmod");
01167 mode_t acc_mode = Mode & S_IAMB;
01168 const char *tident = einfo.getErrUser();
01169 XrdOucEnv chmod_Env(info,0,client);
01170 int retc;
01171 XTRACE(chmod, path, "");
01172
01173
01174
01175 AUTHORIZE(client,&chmod_Env,AOP_Chmod,"chmod",path,einfo);
01176
01177
01178
01179 if (Finder && Finder->isRemote())
01180 {if (fwdCHMOD.Cmd)
01181 {char buff[8];
01182 sprintf(buff, "%o", static_cast<int>(acc_mode));
01183 if (Forward(retc, einfo, fwdCHMOD, path, buff, info)) return retc;
01184 }
01185 else if ((retc = Finder->Locate(einfo,path,SFS_O_RDWR|SFS_O_META)))
01186 return fsError(einfo, retc);
01187 }
01188
01189
01190
01191 if (evsObject && evsObject->Enabled(XrdOfsEvs::Chmod))
01192 {XrdOfsEvsInfo evInfo(tident, path, info, &chmod_Env, acc_mode);
01193 evsObject->Notify(XrdOfsEvs::Chmod, evInfo);
01194 }
01195
01196
01197
01198 if (!(retc = XrdOfsOss->Chmod(path, acc_mode))) return SFS_OK;
01199
01200
01201
01202 return XrdOfsFS.Emsg(epname, einfo, retc, "change", path);
01203 }
01204
01205
01206
01207
01208
01209 int XrdOfs::exists(const char *path,
01210 XrdSfsFileExistence &file_exists,
01211 XrdOucErrInfo &einfo,
01212 const XrdSecEntity *client,
01213 const char *info)
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231 {
01232 EPNAME("exists");
01233 struct stat fstat;
01234 int retc;
01235 const char *tident = einfo.getErrUser();
01236 XrdOucEnv stat_Env(info,0,client);
01237 XTRACE(exists, path, "");
01238
01239
01240
01241 AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
01242
01243
01244
01245 if (Finder && Finder->isRemote()
01246 && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY)))
01247 return fsError(einfo, retc);
01248
01249
01250
01251 retc = XrdOfsOss->Stat(path, &fstat);
01252 if (!retc)
01253 { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
01254 else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
01255 else file_exists=XrdSfsFileExistNo;
01256 return SFS_OK;
01257 }
01258 if (retc == -ENOENT)
01259 {file_exists=XrdSfsFileExistNo;
01260 return SFS_OK;
01261 }
01262
01263
01264
01265 return XrdOfsFS.Emsg(epname, einfo, retc, "locate", path);
01266 }
01267
01268
01269
01270
01271
01272 int XrdOfs::fsctl(const int cmd,
01273 const char *args,
01274 XrdOucErrInfo &einfo,
01275 const XrdSecEntity *client)
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292 {
01293 EPNAME("fsctl");
01294 static int PrivTab[] = {XrdAccPriv_Delete, XrdAccPriv_Insert,
01295 XrdAccPriv_Lock, XrdAccPriv_Lookup,
01296 XrdAccPriv_Rename, XrdAccPriv_Read,
01297 XrdAccPriv_Write};
01298 static char PrivLet[] = {'d', 'i',
01299 'k', 'l',
01300 'n', 'r',
01301 'w'};
01302 static const int PrivNum = sizeof(PrivLet);
01303
01304 int retc, find_flag = SFS_O_LOCATE | (cmd & (SFS_O_NOWAIT | SFS_O_RESET));
01305 int i, blen, privs, opcode = cmd & SFS_FSCTL_CMD;
01306 const char *tident = einfo.getErrUser();
01307 char *bP, *cP;
01308 XTRACE(fsctl, args, "");
01309
01310
01311
01312 if (opcode == SFS_FSCTL_LOCATE)
01313 {struct stat fstat;
01314 const char *Path, *locArg;
01315 char rType[3], *Resp[] = {rType, locResp};
01316 if (*args == '*') {Path = args+1; locArg = args;}
01317 else if (cmd & SFS_O_TRUNC) {Path = args; locArg = (char *)"*";}
01318 else Path = locArg = args;
01319 AUTHORIZE(client,0,AOP_Stat,"locate",Path,einfo);
01320 if (Finder && Finder->isRemote()
01321 && (retc = Finder->Locate(einfo, locArg, find_flag)))
01322 return fsError(einfo, retc);
01323 if ((retc = XrdOfsOss->Stat(Path, &fstat)))
01324 return XrdOfsFS.Emsg(epname, einfo, retc, "locate", Path);
01325 rType[0] = ((fstat.st_mode & S_IFBLK) == S_IFBLK ? 's' : 'S');
01326 rType[1] = (fstat.st_mode & S_IWUSR ? 'w' : 'r');
01327 rType[2] = '\0';
01328 einfo.setErrInfo(locRlen+3, (const char **)Resp, 2);
01329 return SFS_DATA;
01330 }
01331
01332
01333
01334 if (opcode == SFS_FSCTL_STATFS)
01335 {AUTHORIZE(client,0,AOP_Stat,"statfs",args,einfo);
01336 if (Finder && Finder->isRemote()
01337 && (retc = Finder->Space(einfo, args))) return fsError(einfo, retc);
01338 bP = einfo.getMsgBuff(blen);
01339 if ((retc = XrdOfsOss->StatFS(args, bP, blen)))
01340 return XrdOfsFS.Emsg(epname, einfo, retc, "statfs", args);
01341 einfo.setErrCode(blen+1);
01342 return SFS_DATA;
01343 }
01344
01345
01346
01347 if (opcode == SFS_FSCTL_STATLS)
01348 {const char *path;
01349 char pbuff[1024], *opq = (char *) index(args, '?');
01350 XrdOucEnv statls_Env(opq ? opq+1 : 0,0,client);
01351 if (!opq) path = args;
01352 else {int plen = opq-args;
01353 if (plen >= (int)sizeof(pbuff)) plen = sizeof(pbuff)-1;
01354 strncpy(pbuff, args, plen);
01355 path = pbuff;
01356 }
01357 AUTHORIZE(client,0,AOP_Stat,"statfs",path,einfo);
01358 if (Finder && Finder->isRemote()
01359 && (retc = Finder->Space(einfo, path))) return fsError(einfo, retc);
01360 bP = einfo.getMsgBuff(blen);
01361 if ((retc = XrdOfsOss->StatLS(statls_Env, path, bP, blen)))
01362 return XrdOfsFS.Emsg(epname, einfo, retc, "statls", path);
01363 einfo.setErrCode(blen+1);
01364 return SFS_DATA;
01365 }
01366
01367
01368
01369 if (opcode == SFS_FSCTL_STATXA)
01370 {AUTHORIZE(client,0,AOP_Stat,"statxa",args,einfo);
01371 if (Finder && Finder->isRemote()
01372 && (retc = Finder->Locate(einfo, args, SFS_O_RDONLY|SFS_O_STAT)))
01373 return fsError(einfo, retc);
01374 bP = einfo.getMsgBuff(blen);
01375 if ((retc = XrdOfsOss->StatXA(args, bP, blen)))
01376 return XrdOfsFS.Emsg(epname, einfo, retc, "statxa", args);
01377 if (!client || !XrdOfsFS.Authorization) privs = XrdAccPriv_All;
01378 else privs = XrdOfsFS.Authorization->Access(client, args, AOP_Any);
01379 cP = bP + blen; strcpy(cP, "&ofs.ap="); cP += 8;
01380 if (privs == XrdAccPriv_All) *cP++ = 'a';
01381 else {for (i = 0; i < PrivNum; i++)
01382 if (PrivTab[i] & privs) *cP++ = PrivLet[i];
01383 if (cP == (bP + blen + 1)) *cP++ = '?';
01384 }
01385 *cP++ = '\0';
01386 einfo.setErrCode(cP-bP+1);
01387 return SFS_DATA;
01388 }
01389
01390
01391
01392 return XrdOfsFS.Emsg(epname, einfo, ENOTSUP, "fsctl", args);
01393
01394 }
01395
01396
01397
01398
01399
01400 int XrdOfs::getStats(char *buff, int blen)
01401 {
01402 int n;
01403
01404
01405
01406 if (!buff) return OfsStats.Report(0,0) + XrdOfsOss->Stats(0,0);
01407
01408
01409
01410 n = OfsStats.Report(buff, blen);
01411 buff += n; blen -= n;
01412 n += XrdOfsOss->Stats(buff, blen);
01413
01414
01415
01416 return n;
01417 }
01418
01419
01420
01421
01422
01423 const char *XrdOfs::getVersion() {return XrdVSTRING;}
01424
01425
01426
01427
01428
01429 int XrdOfs::mkdir(const char *path,
01430 XrdSfsMode Mode,
01431 XrdOucErrInfo &einfo,
01432 const XrdSecEntity *client,
01433 const char *info)
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447 {
01448 EPNAME("mkdir");
01449 static const int LocOpts = SFS_O_RDWR | SFS_O_CREAT | SFS_O_META;
01450 mode_t acc_mode = Mode & S_IAMB;
01451 int retc, mkpath = Mode & SFS_O_MKPTH;
01452 const char *tident = einfo.getErrUser();
01453 XrdOucEnv mkdir_Env(info,0,client);
01454 XTRACE(mkdir, path, "");
01455
01456
01457
01458 AUTHORIZE(client,&mkdir_Env,AOP_Mkdir,"mkdir",path,einfo);
01459
01460
01461
01462 if (Finder && Finder->isRemote())
01463 {if (fwdMKDIR.Cmd)
01464 {char buff[8];
01465 sprintf(buff, "%o", static_cast<int>(acc_mode));
01466 if (Forward(retc, einfo, (mkpath ? fwdMKPATH:fwdMKDIR),
01467 path, buff, info)) return retc;
01468 }
01469 else if ((retc = Finder->Locate(einfo,path,LocOpts)))
01470 return fsError(einfo, retc);
01471 }
01472
01473
01474
01475 if ((retc = XrdOfsOss->Mkdir(path, acc_mode, mkpath)))
01476 return XrdOfsFS.Emsg(epname, einfo, retc, "mkdir", path);
01477
01478
01479
01480 if (evsObject && evsObject->Enabled(XrdOfsEvs::Mkdir))
01481 {XrdOfsEvsInfo evInfo(tident, path, info, &mkdir_Env, acc_mode);
01482 evsObject->Notify(XrdOfsEvs::Mkdir, evInfo);
01483 }
01484
01485 return SFS_OK;
01486 }
01487
01488
01489
01490
01491
01492 int XrdOfs::prepare( XrdSfsPrep &pargs,
01493 XrdOucErrInfo &out_error,
01494 const XrdSecEntity *client)
01495 {
01496 EPNAME("prepare");
01497 XrdOucTList *tp = pargs.paths;
01498 int retc;
01499
01500
01501
01502 while(tp)
01503 {AUTHORIZE(client,0,AOP_Read,"prepare",tp->text,out_error);
01504 tp = tp->next;
01505 }
01506
01507
01508
01509
01510 if (XrdOfsFS.Finder && (retc = XrdOfsFS.Finder->Prepare(out_error, pargs)))
01511 return fsError(out_error, retc);
01512 return 0;
01513 }
01514
01515
01516
01517
01518
01519 int XrdOfs::remove(const char type,
01520 const char *path,
01521 XrdOucErrInfo &einfo,
01522 const XrdSecEntity *client,
01523 const char *info)
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 {
01536 EPNAME("remove");
01537 int retc, Opt;
01538 const char *tident = einfo.getErrUser();
01539 XrdOucEnv rem_Env(info,0,client);
01540 XTRACE(remove, path, type);
01541
01542
01543
01544 AUTHORIZE(client,&rem_Env,AOP_Delete,"remove",path,einfo);
01545
01546
01547
01548 if (Finder && Finder->isRemote())
01549 {struct fwdOpt *fSpec = (type == 'd' ? &fwdRMDIR : &fwdRM);
01550 if (fSpec->Cmd)
01551 {if (Forward(retc, einfo, *fSpec, path, 0, info)) return retc;}
01552 else if ((retc = Finder->Locate(einfo,path,SFS_O_WRONLY|SFS_O_META)))
01553 return fsError(einfo, retc);
01554 }
01555
01556
01557
01558 if (evsObject)
01559 {XrdOfsEvs::Event theEvent=(type == 'd' ? XrdOfsEvs::Rmdir:XrdOfsEvs::Rm);
01560 if (evsObject->Enabled(theEvent))
01561 {XrdOfsEvsInfo evInfo(tident, path, info, &rem_Env);
01562 evsObject->Notify(theEvent, evInfo);
01563 }
01564 }
01565
01566
01567
01568 Opt = (rem_Env.Get("ofs.lcl") ? XRDOSS_Online : 0);
01569
01570
01571
01572 retc = (type=='d' ? XrdOfsOss->Remdir(path) : XrdOfsOss->Unlink(path,Opt));
01573 if (retc) return XrdOfsFS.Emsg(epname, einfo, retc, "remove", path);
01574 if (type == 'f')
01575 {XrdOfsHandle::Hide(path);
01576 if (Balancer) Balancer->Removed(path);
01577 }
01578 return SFS_OK;
01579 }
01580
01581
01582
01583
01584
01585 int XrdOfs::rename(const char *old_name,
01586 const char *new_name,
01587 XrdOucErrInfo &einfo,
01588 const XrdSecEntity *client,
01589 const char *infoO,
01590 const char *infoN)
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 {
01604 EPNAME("rename");
01605 int retc;
01606 const char *tident = einfo.getErrUser();
01607 XrdOucEnv old_Env(infoO,0,client);
01608 XrdOucEnv new_Env(infoN,0,client);
01609 XTRACE(rename, new_name, "old fn=" <<old_name <<" new ");
01610
01611
01612
01613 AUTHORIZE2(client, einfo,
01614 AOP_Rename, "renaming", old_name, &old_Env,
01615 AOP_Insert, "renaming to", new_name, &new_Env );
01616
01617
01618
01619 if (Finder && Finder->isRemote())
01620 {if (fwdMV.Cmd)
01621 {if (Forward(retc, einfo, fwdMV, old_name, new_name, infoO, infoN))
01622 return retc;
01623 }
01624 else if ((retc = Finder->Locate(einfo,old_name,SFS_O_RDWR|SFS_O_META)))
01625 return fsError(einfo, retc);
01626 }
01627
01628
01629
01630 if (evsObject && evsObject->Enabled(XrdOfsEvs::Mv))
01631 {XrdOfsEvsInfo evInfo(tident, old_name, infoO, &old_Env, 0, 0,
01632 new_name, infoN, &new_Env);
01633 evsObject->Notify(XrdOfsEvs::Mv, evInfo);
01634 }
01635
01636
01637
01638 if ((retc = XrdOfsOss->Rename(old_name, new_name)))
01639 return XrdOfsFS.Emsg(epname, einfo, retc, "rename", old_name);
01640 XrdOfsHandle::Hide(old_name);
01641 if (Balancer) {Balancer->Removed(old_name);
01642 Balancer->Added(new_name);
01643 }
01644 return SFS_OK;
01645 }
01646
01647
01648
01649
01650
01651 int XrdOfs::stat(const char *path,
01652 struct stat *buf,
01653 XrdOucErrInfo &einfo,
01654 const XrdSecEntity *client,
01655 const char *info)
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 {
01668 EPNAME("stat");
01669 int retc;
01670 const char *tident = einfo.getErrUser();
01671 XrdOucEnv stat_Env(info,0,client);
01672 XTRACE(stat, path, "");
01673
01674
01675
01676 AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
01677
01678
01679
01680 if (Finder && Finder->isRemote()
01681 && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY|SFS_O_STAT, &stat_Env)))
01682 return fsError(einfo, retc);
01683
01684
01685
01686 if ((retc = XrdOfsOss->Stat(path, buf)))
01687 return XrdOfsFS.Emsg(epname, einfo, retc, "locate", path);
01688 return SFS_OK;
01689 }
01690
01691
01692
01693 int XrdOfs::stat(const char *path,
01694 mode_t &mode,
01695 XrdOucErrInfo &einfo,
01696 const XrdSecEntity *client,
01697 const char *info)
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711 {
01712 EPNAME("stat");
01713 struct stat buf;
01714 int retc;
01715 const char *tident = einfo.getErrUser();
01716 XrdOucEnv stat_Env(info,0,client);
01717 XTRACE(stat, path, "");
01718
01719
01720
01721 AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
01722 mode = (mode_t)-1;
01723
01724
01725
01726 if (Finder && Finder->isRemote()
01727 && (retc = Finder->Locate(einfo,path,SFS_O_NOWAIT|SFS_O_RDONLY|SFS_O_STAT,
01728 &stat_Env)))
01729 return fsError(einfo, retc);
01730
01731
01732
01733 if (!(retc = XrdOfsOss->Stat(path, &buf, XRDOSS_resonly))) mode=buf.st_mode;
01734 else if ((-ENOMSG) != retc) return XrdOfsFS.Emsg(epname, einfo, retc,
01735 "locate", path);
01736 return SFS_OK;
01737 }
01738
01739
01740
01741
01742
01743 int XrdOfs::truncate(const char *path,
01744 XrdSfsFileOffset Size,
01745 XrdOucErrInfo &einfo,
01746 const XrdSecEntity *client,
01747 const char *info)
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 {
01760 EPNAME("truncate");
01761 const char *tident = einfo.getErrUser();
01762 XrdOucEnv trunc_Env(info,0,client);
01763 int retc;
01764 XTRACE(truncate, path, "");
01765
01766
01767
01768 AUTHORIZE(client,&trunc_Env,AOP_Update,"truncate",path,einfo);
01769
01770
01771
01772 if (Finder && Finder->isRemote())
01773 {if (fwdTRUNC.Cmd)
01774 {char xSz[32];
01775 sprintf(xSz, "%lld", static_cast<long long>(Size));
01776 if (Forward(retc, einfo, fwdTRUNC, path, xSz, info)) return retc;
01777 }
01778 else if ((retc = Finder->Locate(einfo,path,SFS_O_RDWR)))
01779 return fsError(einfo, retc);
01780 }
01781
01782
01783
01784 if (evsObject && evsObject->Enabled(XrdOfsEvs::Trunc))
01785 {XrdOfsEvsInfo evInfo(tident, path, info, &trunc_Env, 0, Size);
01786 evsObject->Notify(XrdOfsEvs::Trunc, evInfo);
01787 }
01788
01789
01790
01791 if (!(retc = XrdOfsOss->Truncate(path, Size))) return SFS_OK;
01792
01793
01794
01795 return XrdOfsFS.Emsg(epname, einfo, retc, "trunc", path);
01796 }
01797
01798
01799
01800
01801
01802 int XrdOfs::Emsg(const char *pfx,
01803 XrdOucErrInfo &einfo,
01804 int ecode,
01805 const char *op,
01806 XrdOfsHandle *hP)
01807 {
01808 int rc;
01809
01810
01811
01812 if ((rc = Emsg(pfx, einfo, ecode, op, hP->Name())) != SFS_ERROR) return rc;
01813
01814
01815
01816
01817 if (hP->isRW == XrdOfsHandle::opPC)
01818 {hP->Lock();
01819 XrdOfsFS.Unpersist(hP);
01820 hP->UnLock();
01821 }
01822
01823
01824
01825 return SFS_ERROR;
01826 }
01827
01828
01829
01830 int XrdOfs::Emsg(const char *pfx,
01831 XrdOucErrInfo &einfo,
01832 int ecode,
01833 const char *op,
01834 const char *target)
01835 {
01836 char *etext, buffer[MAXPATHLEN+80], unkbuff[64];
01837
01838
01839
01840
01841 if (ecode < 0) ecode = -ecode;
01842 if (ecode == EBUSY) return 5;
01843
01844
01845
01846 if (ecode == ETIMEDOUT) return OSSDelay;
01847
01848
01849
01850 if (!(etext = OfsEroute.ec2text(ecode)))
01851 {sprintf(unkbuff, "reason unknown (%d)", ecode); etext = unkbuff;}
01852
01853
01854
01855 snprintf(buffer,sizeof(buffer),"Unable to %s %s; %s", op, target, etext);
01856
01857
01858
01859 #ifndef NODEBUG
01860 OfsEroute.Emsg(pfx, einfo.getErrUser(), buffer);
01861 #endif
01862
01863
01864
01865 einfo.setErrInfo(ecode, buffer);
01866 return SFS_ERROR;
01867 }
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877 const char *XrdOfs::Fname(const char *path)
01878 {
01879 int i = strlen(path)-1;
01880 while(i) if (path[i] == '/') return &path[i+1];
01881 else i--;
01882 return path;
01883 }
01884
01885
01886
01887
01888
01889 int XrdOfs::Forward(int &Result, XrdOucErrInfo &Resp, struct fwdOpt &Fwd,
01890 const char *arg1, const char *arg2,
01891 const char *arg3, const char *arg4)
01892 {
01893 int retc;
01894
01895 if ((retc = Finder->Forward(Resp, Fwd.Cmd, arg1, arg2, arg3, arg4)))
01896 {Result = fsError(Resp, retc);
01897 return 1;
01898 }
01899
01900 if (Fwd.Port <= 0)
01901 {Result = SFS_OK;
01902 return (Fwd.Port ? 0 : 1);
01903 }
01904
01905 Resp.setErrInfo(Fwd.Port, Fwd.Host);
01906 Result = SFS_REDIRECT;
01907 return 1;
01908 }
01909
01910
01911
01912
01913
01914 int XrdOfs::fsError(XrdOucErrInfo &myError, int rc)
01915 {
01916
01917
01918
01919 if (rc == -EREMOTE) {OfsStats.Data.numRedirect++; return SFS_REDIRECT;}
01920 if (rc == -EINPROGRESS) {OfsStats.Data.numStarted++; return SFS_STARTED; }
01921 if (rc > 0) {OfsStats.Data.numDelays++; return rc; }
01922 if (rc == -EALREADY) {OfsStats.Data.numReplies++; return SFS_DATA; }
01923 {OfsStats.Data.numErrors++; return SFS_ERROR; }
01924 }
01925
01926
01927
01928
01929
01930 int XrdOfs::Stall(XrdOucErrInfo &einfo,
01931 int stime,
01932 const char *path)
01933 {
01934 const char *msgfmt = "File %s is being %s; "
01935 "estimated time to completion %s";
01936 EPNAME("Stall")
01937 #ifndef NODEBUG
01938 const char *tident = "";
01939 #endif
01940 char Mbuff[2048], Tbuff[32];
01941 const char *What = "staged";
01942
01943
01944
01945 if (stime < 0) {stime = 60; What = "created";}
01946
01947
01948
01949 snprintf(Mbuff, sizeof(Mbuff)-1, msgfmt,
01950 Fname(path), What, WaitTime(stime, Tbuff, sizeof(Tbuff)));
01951 ZTRACE(delay, "Stall " <<stime <<": " <<Mbuff <<" for " <<path);
01952
01953
01954
01955 einfo.setErrInfo(0, Mbuff);
01956
01957
01958
01959 return (stime > MaxDelay ? MaxDelay : stime);
01960 }
01961
01962
01963
01964
01965
01966 void XrdOfs::Unpersist(XrdOfsHandle *oh, int xcev)
01967 {
01968 EPNAME("Unpersist");
01969 const char *tident = oh->PoscUsr();
01970 int poscNum, retc;
01971 short theMode;
01972
01973
01974
01975 FTRACE(close, "use=0");
01976
01977
01978
01979 if (xcev && XrdOfsFS.evsObject && *tident != '?'
01980 && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Closew))
01981 {XrdOfsEvsInfo evInfo(tident, oh->Name());
01982 XrdOfsFS.evsObject->Notify(XrdOfsEvs::Closew, evInfo);
01983 }
01984
01985
01986
01987 if (XrdOfsFS.Balancer) XrdOfsFS.Balancer->Removed(oh->Name());
01988 if (XrdOfsFS.evsObject && XrdOfsFS.evsObject->Enabled(XrdOfsEvs::Rm))
01989 {XrdOfsEvsInfo evInfo(tident, oh->Name());
01990 XrdOfsFS.evsObject->Notify(XrdOfsEvs::Rm, evInfo);
01991 }
01992
01993
01994
01995 OfsStats.Add(OfsStats.Data.numUnpsist);
01996
01997
01998
01999 OfsEroute.Emsg(epname, "Unpersisting", tident, oh->Name());
02000 if ((poscNum = oh->PoscGet(theMode))) poscQ->Del(oh->Name(), poscNum, 1);
02001 else if ((retc = XrdOfsOss->Unlink(oh->Name())))
02002 OfsEroute.Emsg(epname, retc, "unpersist", oh->Name());
02003 }
02004
02005
02006
02007
02008
02009 char *XrdOfs::WaitTime(int stime, char *buff, int blen)
02010 {
02011 int mlen, hr, min, sec;
02012
02013
02014
02015 min = stime / 60;
02016 sec = stime % 60;
02017 hr = min / 60;
02018 min = min % 60;
02019
02020
02021
02022 if (!hr && !min)
02023 mlen = snprintf(buff,blen,"%d second%s",sec,(sec > 1 ? "s" : ""));
02024 else if (!hr)
02025 {if (sec > 10) min++;
02026 mlen = snprintf(buff,blen,"%d minute%s",min,(min > 1 ? "s" : ""));
02027 }
02028 else {if (hr == 1)
02029 if (min <= 30)
02030 mlen = snprintf(buff,blen,"%d minutes",min+60);
02031 else mlen = snprintf(buff,blen,"%d hour and %d minutes",hr,min);
02032 else {if (min > 30) hr++;
02033 mlen = snprintf(buff,blen,"%d hours",hr);
02034 }
02035 }
02036
02037
02038
02039 buff[blen-1] = '\0';
02040 return buff;
02041 }