00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <unistd.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <signal.h>
00024 #include <strings.h>
00025 #include <stdio.h>
00026 #include <sys/file.h>
00027 #include <sys/stat.h>
00028 #include <sys/types.h>
00029 #include <sys/param.h>
00030 #ifdef __solaris__
00031 #include <sys/vnode.h>
00032 #endif
00033
00034 #include "XrdVersion.hh"
00035
00036 #include "XrdOss/XrdOssApi.hh"
00037 #include "XrdOss/XrdOssCache.hh"
00038 #include "XrdOss/XrdOssConfig.hh"
00039 #include "XrdOss/XrdOssError.hh"
00040 #include "XrdOss/XrdOssLock.hh"
00041 #include "XrdOss/XrdOssMio.hh"
00042 #include "XrdOss/XrdOssTrace.hh"
00043 #include "XrdOuc/XrdOucName2Name.hh"
00044 #include "XrdSys/XrdSysError.hh"
00045 #include "XrdSys/XrdSysHeaders.hh"
00046 #include "XrdSys/XrdSysPlatform.hh"
00047 #include "XrdSys/XrdSysPlugin.hh"
00048
00049 #ifdef XRDOSSCX
00050 #include "oocx_CXFile.h"
00051 #endif
00052
00053
00054
00055
00056
00057 XrdOssSys *XrdOssSS = 0;
00058
00059 XrdSysError OssEroute(0, "oss_");
00060
00061 XrdOucTrace OssTrace(&OssEroute);
00062
00063
00064
00065
00066
00067 char XrdOssSys::tryMmap = 0;
00068 char XrdOssSys::chkMmap = 0;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 XrdOss *XrdOssGetSS(XrdSysLogger *Logger, const char *config_fn,
00079 const char *OssLib)
00080 {
00081 static XrdOssSys myOssSys;
00082 extern XrdSysError OssEroute;
00083 XrdSysPlugin *myLib;
00084 XrdOss *(*ep)(XrdOss *, XrdSysLogger *, const char *, const char *);
00085 char *parms;
00086
00087
00088
00089 if (!OssLib) {if (myOssSys.Init(Logger, config_fn)) return 0;
00090 else return (XrdOss *)&myOssSys;
00091 }
00092
00093
00094
00095 parms = (char *)OssLib;
00096 while(*parms && *parms != ' ') parms++;
00097 if (*parms) *parms++ = '\0';
00098 while(*parms && *parms == ' ') parms++;
00099 if (!*parms) parms = 0;
00100
00101
00102
00103
00104 OssEroute.logger(Logger);
00105 if (!(myLib = new XrdSysPlugin(&OssEroute, OssLib))) return 0;
00106
00107
00108
00109 ep = (XrdOss *(*)(XrdOss *, XrdSysLogger *, const char *, const char *))
00110 (myLib->getPlugin("XrdOssGetStorageSystem"));
00111 if (!ep) return 0;
00112
00113
00114
00115 return ep((XrdOss *)&myOssSys, Logger, config_fn, parms);
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 int XrdOssSys::Init(XrdSysLogger *lp, const char *configfn)
00133 {
00134 int retc;
00135
00136
00137
00138 OssEroute.logger(lp);
00139
00140
00141
00142 XrdOssSS = this;
00143 if ( (retc = Configure(configfn, OssEroute)) ) return retc;
00144
00145
00146
00147 return XrdOssOK;
00148 }
00149
00150
00151
00152
00153
00154 int XrdOssSys::Lfn2Pfn(const char *oldp, char *newp, int blen)
00155 {
00156 if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, blen));
00157 if ((int)strlen(oldp) >= blen) return -ENAMETOOLONG;
00158 strcpy(newp, oldp);
00159 return 0;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 int XrdOssSys::GenLocalPath(const char *oldp, char *newp)
00172 {
00173 if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, MAXPATHLEN));
00174 if (strlen(oldp) >= MAXPATHLEN) return -ENAMETOOLONG;
00175 strcpy(newp, oldp);
00176 return 0;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 int XrdOssSys::GenRemotePath(const char *oldp, char *newp)
00189 {
00190 if (rmt_N2N) return -(rmt_N2N->lfn2rfn(oldp, newp, MAXPATHLEN));
00191 if (strlen(oldp) >= MAXPATHLEN) return -ENAMETOOLONG;
00192 strcpy(newp, oldp);
00193 return 0;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 int XrdOssSys::Chmod(const char *path, mode_t mode)
00211 {
00212 char actual_path[MAXPATHLEN+1], *local_path;
00213 int retc;
00214
00215
00216
00217 if (lcl_N2N)
00218 if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path))))
00219 return retc;
00220 else local_path = actual_path;
00221 else local_path = (char *)path;
00222
00223
00224
00225 return (chmod(local_path, mode) ? -errno : XrdOssOK);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 int XrdOssSys::Mkdir(const char *path, mode_t mode, int mkpath)
00244 {
00245 char actual_path[MAXPATHLEN+1], *local_path;
00246 int retc;
00247
00248
00249
00250 if (lcl_N2N)
00251 if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path))))
00252 return retc;
00253 else local_path = actual_path;
00254 else local_path = (char *)path;
00255
00256
00257
00258 if (!mkdir(local_path, mode)) return XrdOssOK;
00259 if (mkpath && errno == ENOENT) return Mkpath(local_path, mode);
00260 return -errno;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 int XrdOssSys::Mkpath(const char *path, mode_t mode)
00278 {
00279 char local_path[MAXPATHLEN+1], *next_path;
00280 int i = strlen(path);
00281
00282
00283
00284 strcpy(local_path, path);
00285
00286
00287
00288 while(i && local_path[--i] == '/') local_path[i] = '\0';
00289 if (!i) return -ENOENT;
00290
00291
00292
00293 next_path = local_path;
00294 while((next_path = index(next_path+1, int('/'))))
00295 {*next_path = '\0';
00296 if (mkdir(local_path, mode) && errno != EEXIST) return -errno;
00297 *next_path = '/';
00298 }
00299
00300
00301
00302 if (mkdir(local_path, mode) && errno != EEXIST) return -errno;
00303 return XrdOssOK;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320 int XrdOssSys::Stats(char *buff, int blen)
00321 {
00322 static const char statfmt1[] = "<stats id=\"oss\" v=\"2\">";
00323 static const char statfmt2[] = "</stats>";
00324 static const int statflen = sizeof(statfmt1) + sizeof(statfmt2);
00325 char *bp = buff;
00326 int n;
00327
00328
00329
00330 if (!buff) return statflen + getStats(0,0);
00331
00332
00333
00334 if (blen < statflen) return 0;
00335 strcpy(bp, statfmt1);
00336 bp += sizeof(statfmt1)-1; blen -= sizeof(statfmt1)-1;
00337
00338
00339
00340 n = getStats(bp, blen);
00341 bp += n; blen -= n;
00342
00343
00344
00345 if (blen >= (int)sizeof(statfmt2))
00346 {strcpy(bp, statfmt2); bp += (sizeof(statfmt2)-1);}
00347 return bp - buff;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 int XrdOssSys::Truncate(const char *path, unsigned long long size)
00366 {
00367 struct stat statbuff;
00368 char actual_path[MAXPATHLEN+1], *local_path;
00369 long long oldsz;
00370 int retc;
00371
00372
00373
00374 if (lcl_N2N)
00375 if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path))))
00376 return retc;
00377 else local_path = actual_path;
00378 else local_path = (char *)path;
00379
00380
00381
00382 if (lstat(local_path, &statbuff)) return -errno;
00383 else if ((statbuff.st_mode & S_IFMT) == S_IFLNK)
00384 {struct stat buff;
00385 if (stat(local_path, &buff)) return -errno;
00386 oldsz = buff.st_size;
00387 } else oldsz = statbuff.st_size;
00388
00389
00390
00391 if (truncate(local_path, size)) return -errno;
00392 XrdOssCache::Adjust(local_path,static_cast<long long>(size)-oldsz,&statbuff);
00393 return XrdOssOK;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 int XrdOssDir::Opendir(const char *dir_path)
00414 {
00415 EPNAME("Opendir");
00416 char actual_path[MAXPATHLEN+1], *local_path, *remote_path;
00417 int retc;
00418
00419
00420
00421 if (isopen) return -XRDOSS_E8001;
00422
00423
00424
00425 pflags = XrdOssSS->PathOpts(dir_path);
00426 ateof = 0;
00427
00428
00429
00430 if (XrdOssSS->lcl_N2N)
00431 if ((retc = XrdOssSS->lcl_N2N->lfn2pfn(dir_path, actual_path, sizeof(actual_path))))
00432 return retc;
00433 else local_path = actual_path;
00434 else local_path = (char *)dir_path;
00435
00436
00437
00438 if (!(pflags & XRDEXP_STAGE) || (pflags & XRDEXP_NODREAD))
00439 {TRACE(Opendir, "lcl path " <<local_path <<" (" <<dir_path <<")");
00440 if ((lclfd = opendir((char *)local_path))) {isopen = 1; return XrdOssOK;}
00441 return -errno;
00442 }
00443
00444
00445
00446 if (XrdOssSS->rmt_N2N)
00447 if ((retc = XrdOssSS->rmt_N2N->lfn2rfn(dir_path, actual_path, sizeof(actual_path))))
00448 return retc;
00449 else remote_path = actual_path;
00450 else remote_path = (char *)dir_path;
00451
00452 TRACE(Opendir, "rmt path " << remote_path <<" (" << dir_path <<")");
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 if (!(mssfd = XrdOssSS->MSS_Opendir(remote_path, retc))) return retc;
00470 isopen = 1;
00471 return XrdOssOK;
00472 }
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 int XrdOssDir::Readdir(char *buff, int blen)
00494 {
00495 struct dirent *rp;
00496
00497
00498
00499 if (!isopen) return -XRDOSS_E8002;
00500
00501
00502
00503 if (lclfd)
00504 {errno = 0;
00505 if ((rp = readdir(lclfd)))
00506 {strlcpy(buff, rp->d_name, blen);
00507 return XrdOssOK;
00508 }
00509 *buff = '\0'; ateof = 1;
00510 return -errno;
00511 }
00512
00513
00514
00515 if (pflags & XRDEXP_NODREAD)
00516 {if (ateof) *buff = '\0';
00517 else {*buff = '.'; ateof = 1;}
00518 return XrdOssOK;
00519 }
00520
00521
00522
00523 return XrdOssSS->MSS_Readdir(mssfd, buff, blen);
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 int XrdOssDir::Close(long long *retsz)
00538 {
00539 int retc;
00540
00541
00542
00543 if (!isopen) return -XRDOSS_E8002;
00544
00545
00546
00547 if (lclfd) {if (!(retc = closedir(lclfd))) lclfd = 0;}
00548 else if (mssfd) { if (!(retc = XrdOssSS->MSS_Closedir(mssfd))) mssfd = 0;}
00549 else retc = 0;
00550
00551
00552
00553 return retc;
00554 }
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 int XrdOssFile::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &Env)
00575 {
00576 unsigned long long popts;
00577 int retc, mopts;
00578 char actual_path[MAXPATHLEN+1], *local_path;
00579 struct stat buf;
00580
00581
00582
00583 if (fd >= 0) return -XRDOSS_E8003;
00584 else cxobj = 0;
00585
00586
00587
00588 popts = XrdOssSS->PathOpts(path);
00589
00590
00591
00592 if (XrdOssSS->lcl_N2N)
00593 if ((retc = XrdOssSS->lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path))))
00594 return retc;
00595 else local_path = actual_path;
00596 else local_path = (char *)path;
00597
00598
00599
00600 if ((Oflag & (O_WRONLY | O_RDWR)) && (popts & XRDEXP_NOTRW))
00601 {if (popts & XRDEXP_FORCERO) Oflag = O_RDONLY;
00602 else return OssEroute.Emsg("Open",-XRDOSS_E8005,"open r/w",path);
00603 }
00604
00605
00606
00607
00608 if ( (fd = (int)Open_ufs(local_path, Oflag, Mode, popts)) == -ENOENT
00609 && (popts & XRDEXP_REMOTE))
00610 {if (!(popts & XRDEXP_STAGE))
00611 return OssEroute.Emsg("Open",-XRDOSS_E8006,"open",path);
00612 if ((retc = XrdOssSS->Stage(tident, path, Env, Oflag, Mode, popts)))
00613 return retc;
00614 fd = (int)Open_ufs(local_path, Oflag, Mode, popts & ~XRDEXP_REMOTE);
00615 }
00616
00617
00618
00619 if (fd >= 0)
00620 {do {retc = fstat(fd, &buf);} while(retc && errno == EINTR);
00621 if (!retc && !(buf.st_mode & S_IFREG))
00622 {close(fd); fd = (buf.st_mode & S_IFDIR ? -EISDIR : -ENOTBLK);}
00623 if (Oflag & (O_WRONLY | O_RDWR))
00624 {FSize = buf.st_size; cacheP = XrdOssCache::Find(local_path);}
00625 else {if (buf.st_mode & S_ISUID && fd >= 0) {close(fd); fd=-ETXTBSY;}
00626 FSize = -1; cacheP = 0;
00627 }
00628 } else if (fd == -EEXIST)
00629 {do {retc = stat(local_path,&buf);} while(retc && errno==EINTR);
00630 if (!retc && (buf.st_mode & S_IFDIR)) fd = -EISDIR;
00631 }
00632
00633
00634
00635 if (fd >= 0 && XrdOssSS->tryMmap)
00636 {mopts = 0;
00637 if (popts & XRDEXP_MKEEP) mopts |= OSSMIO_MPRM;
00638 if (popts & XRDEXP_MLOK) mopts |= OSSMIO_MLOK;
00639 if (popts & XRDEXP_MMAP) mopts |= OSSMIO_MMAP;
00640 if (XrdOssSS->chkMmap) mopts = XrdOssMio::getOpts(local_path, mopts);
00641 if (mopts) mmFile = XrdOssMio::Map(local_path, fd, mopts);
00642 } else mmFile = 0;
00643
00644
00645
00646 return (fd < 0 ? fd : XrdOssOK);
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 int XrdOssFile::Close(long long *retsz)
00661 {
00662 if (fd < 0) return -XRDOSS_E8004;
00663 if (retsz || cacheP)
00664 {struct stat buf;
00665 int retc;
00666 do {retc = fstat(fd, &buf);} while(retc && errno == EINTR);
00667 if (cacheP && FSize != buf.st_size)
00668 XrdOssCache::Adjust(cacheP, buf.st_size - FSize);
00669 if (retsz) *retsz = buf.st_size;
00670 }
00671 if (close(fd)) return -errno;
00672 if (mmFile) {XrdOssMio::Recycle(mmFile); mmFile = 0;}
00673 #ifdef XRDOSSCX
00674 if (cxobj) {delete cxobj; cxobj = 0;}
00675 #endif
00676 fd = -1; FSize = -1; cacheP = 0;
00677 return XrdOssOK;
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 ssize_t XrdOssFile::Read(off_t offset, size_t blen)
00694 {
00695
00696 if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00697
00698 return 0;
00699 }
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 ssize_t XrdOssFile::Read(void *buff, off_t offset, size_t blen)
00719 {
00720 ssize_t retval;
00721
00722 if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00723
00724 #ifdef XRDOSSCX
00725 if (cxobj)
00726 if (XrdOssSS->DirFlags & XrdOssNOSSDEC) return (ssize_t)-XRDOSS_E8021;
00727 else retval = cxobj->Read((char *)buff, blen, offset);
00728 else
00729 #endif
00730 do { retval = pread(fd, buff, blen, offset); }
00731 while(retval < 0 && errno == EINTR);
00732
00733 return (retval >= 0 ? retval : (ssize_t)-errno);
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 ssize_t XrdOssFile::ReadRaw(void *buff, off_t offset, size_t blen)
00753 {
00754 ssize_t retval;
00755
00756 if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00757
00758 #ifdef XRDOSSCX
00759 if (cxobj) retval = cxobj->ReadRaw((char *)buff, blen, offset);
00760 else
00761 #endif
00762 do { retval = pread(fd, buff, blen, offset); }
00763 while(retval < 0 && errno == EINTR);
00764
00765 return (retval >= 0 ? retval : (ssize_t)-errno);
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 ssize_t XrdOssFile::Write(const void *buff, off_t offset, size_t blen)
00784 {
00785 ssize_t retval;
00786
00787 if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00788
00789 if (XrdOssSS->MaxSize && (long long)(offset+blen) > XrdOssSS->MaxSize)
00790 return (ssize_t)-XRDOSS_E8007;
00791
00792 do { retval = pwrite(fd, buff, blen, offset); }
00793 while(retval < 0 && errno == EINTR);
00794
00795 if (retval < 0) retval = (retval == EBADF && cxobj ? -XRDOSS_E8022 : -errno);
00796 return retval;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 int XrdOssFile::Fchmod(mode_t Mode)
00812 {
00813 return (fchmod(fd, Mode) ? -errno : XrdOssOK);
00814 }
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 int XrdOssFile::Fstat(struct stat *buff)
00829 {
00830 return (fstat(fd, buff) ? -errno : XrdOssOK);
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 int XrdOssFile::Fsync(void)
00845 {
00846 return (fsync(fd) ? -errno : XrdOssOK);
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 off_t XrdOssFile::getMmap(void **addr)
00864 {
00865 if (mmFile) return (addr ? mmFile->Export(addr) : 1);
00866 if (addr) *addr = 0;
00867 return 0;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 int XrdOssFile::isCompressed(char *cxidp)
00885 {
00886 if (cxpgsz)
00887 {cxidp[0] = cxid[0]; cxidp[1] = cxid[1];
00888 cxidp[2] = cxid[2]; cxidp[3] = cxid[3];
00889 }
00890 return cxpgsz;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 int XrdOssFile::Ftruncate(unsigned long long flen) {
00916 off_t newlen = flen;
00917
00918 if (sizeof(newlen) < sizeof(flen) && (flen>>31)) return -XRDOSS_E8008;
00919
00920
00921
00922 return (ftruncate(fd, newlen) ? -errno : XrdOssOK);
00923 }
00924
00925
00926
00927
00928
00929
00930
00931
00932 int XrdOssFile::Open_ufs(const char *path, int Oflag, int Mode,
00933 unsigned long long popts)
00934 {
00935 EPNAME("Open_ufs")
00936 static const int isWritable = O_WRONLY|O_RDWR;
00937 int myfd, newfd, retc;
00938 #ifndef NODEBUG
00939 char *ftype = (char *)" path=";
00940 #endif
00941 XrdOssLock ufs_file;
00942 #ifdef XRDOSSCX
00943 int attcx = 0;
00944 #endif
00945
00946
00947
00948 if ((popts & XRDEXP_REMOTE)
00949 && (retc = ufs_file.Serialize(path, XrdOssDIR|XrdOssEXC)) < 0) return retc;
00950
00951
00952
00953 do { myfd = open(path, Oflag|O_LARGEFILE, Mode);}
00954 while( myfd < 0 && errno == EINTR);
00955
00956
00957
00958
00959
00960 if (popts & XRDEXP_PURGE || (popts & XRDEXP_MIG && Oflag & isWritable))
00961 ufs_file.Serialize(myfd, XrdOssSHR);
00962
00963
00964
00965 if (myfd < 0) myfd = -errno;
00966 #ifdef XRDOSSCX
00967 else if ((popts & XRDEXP_COMPCHK)
00968 && oocx_CXFile::isCompressed(myfd, cxid, &cxpgsz))
00969 if (Oflag != O_RDONLY) {close(myfd); return -XRDOSS_E8022;}
00970 else attcx = 1;
00971 #endif
00972
00973
00974
00975 if (myfd >= 0)
00976 {if (myfd < XrdOssSS->FDFence)
00977 {if ((newfd = fcntl(myfd, F_DUPFD, XrdOssSS->FDFence)) < 0)
00978 OssEroute.Emsg("Open_ufs",errno,"reloc FD",path);
00979 else {close(myfd); myfd = newfd;}
00980 }
00981 fcntl(myfd, F_SETFD, FD_CLOEXEC);
00982 #ifdef XRDOSSCX
00983
00984
00985 if (attcx) {cxobj = new oocx_CXFile;
00986 ftype = (char *)" CXpath=";
00987 if ((retc = cxobj->Attach(myfd, path)) < 0)
00988 {close(myfd); myfd = retc; delete cxobj; cxobj = 0;}
00989 }
00990 #endif
00991 }
00992
00993
00994
00995 TRACE(Open, "fd=" <<myfd <<" flags=" <<std::hex <<Oflag <<" mode="
00996 <<std::oct <<Mode <<std::dec <<ftype <<path);
00997
00998
00999
01000 if (popts & XRDEXP_REMOTE) ufs_file.UnSerialize(0);
01001 return myfd;
01002 }