00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdPosixXrootdCVSID = "$Id: XrdPosixXrootd.cc 38049 2011-02-11 11:42:35Z rdm $";
00014
00015 #include <errno.h>
00016 #include <fcntl.h>
00017 #include <sys/time.h>
00018 #include <sys/param.h>
00019 #include <sys/resource.h>
00020 #include <sys/uio.h>
00021
00022 #include "XrdClient/XrdClient.hh"
00023 #include "XrdClient/XrdClientAdmin.hh"
00024 #include "XrdClient/XrdClientCallback.hh"
00025 #include "XrdClient/XrdClientEnv.hh"
00026 #include "XrdClient/XrdClientUrlInfo.hh"
00027 #include "XrdClient/XrdClientVector.hh"
00028 #include "XrdSys/XrdSysHeaders.hh"
00029 #include "XrdSys/XrdSysPlatform.hh"
00030 #include "XrdOuc/XrdOucString.hh"
00031 #include "XrdPosix/XrdPosixCallBack.hh"
00032 #include "XrdPosix/XrdPosixLinkage.hh"
00033 #include "XrdPosix/XrdPosixXrootd.hh"
00034
00035
00036
00037
00038
00039
00040
00041
00042 class XrdPosixAdminNew
00043 {
00044 public:
00045
00046 XrdClientAdmin Admin;
00047
00048 int Fault();
00049
00050 int isOK() {return eNum == 0;}
00051
00052 int lastError()
00053 {return XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);}
00054
00055 int Result() {if (eNum) {errno = eNum; return -1;}
00056 return 0;
00057 }
00058
00059 XrdPosixAdminNew(const char *path);
00060 ~XrdPosixAdminNew() {}
00061
00062 private:
00063
00064 int eNum;
00065 };
00066
00067
00068
00069
00070
00071 class XrdPosixDir {
00072
00073 public:
00074 XrdPosixDir(int dirno, const char *path);
00075 ~XrdPosixDir();
00076
00077 void Lock() { myMutex.Lock(); }
00078 void UnLock() { myMutex.UnLock(); }
00079 int dirNo() { return fdirno; }
00080 long getEntries() { return fentries.GetSize(); }
00081 long getOffset() { return fentry; }
00082 void setOffset(long offset) { fentry = offset; }
00083 dirent64 *nextEntry(dirent64 *dp=0);
00084 void rewind() { fentry = -1; fentries.Clear();}
00085 int Status() { return eNum;}
00086
00087
00088 private:
00089 XrdSysMutex myMutex;
00090 XrdClientAdmin XAdmin;
00091 dirent64 *myDirent;
00092 static int maxname;
00093 int fdirno;
00094 char *fpath;
00095 vecString fentries;
00096 long fentry;
00097 int eNum;
00098 };
00099
00100
00101
00102
00103
00104 class XrdPosixFile : public XrdClientCallback
00105 {
00106 public:
00107
00108 XrdClient *XClient;
00109
00110 int Active() {return doClose;}
00111
00112 void isOpen() {doClose = 1;}
00113
00114 long long Offset() {return currOffset;}
00115
00116 long long addOffset(long long offs, int updtSz=0)
00117 {currOffset += offs;
00118 if (updtSz && currOffset > stat.size) stat.size=currOffset;
00119 return currOffset;
00120 }
00121
00122 long long setOffset(long long offs)
00123 {currOffset = offs;
00124 return currOffset;
00125 }
00126
00127 void Lock() {myMutex.Lock();}
00128 void UnLock() {myMutex.UnLock();}
00129
00130 void OpenComplete(XrdClientAbs *clientP, void *cbArg, bool res)
00131 {if (cbDone) return;
00132 XrdPosixXrootd::OpenCB(this, cbArg, res);
00133 cbDone=1;
00134 }
00135
00136 XrdClientStatInfo stat;
00137 XrdPosixCallBack *theCB;
00138 XrdPosixFile *Next;
00139 int FD;
00140 int cbResult;
00141
00142 static const int realFD = 1;
00143 static const int isSync = 2;
00144
00145 XrdPosixFile(int fd, const char *path,
00146 XrdPosixCallBack *cbP=0, int Opts=realFD);
00147 ~XrdPosixFile();
00148
00149 private:
00150
00151 XrdSysMutex myMutex;
00152 long long currOffset;
00153 short doClose;
00154 short cbDone;
00155 short fdClose;
00156 };
00157
00158
00159 typedef XrdClientVector<XrdOucString> vecString;
00160 typedef XrdClientVector<bool> vecBool;
00161
00162
00163
00164
00165
00166 #define Scuttle(fp, rc) fp->UnLock(); errno = rc; return -1
00167
00168
00169
00170
00171
00172 int XrdPosixDir::maxname = 255;
00173 XrdSysMutex XrdPosixXrootd::myMutex;
00174 XrdPosixFile **XrdPosixXrootd::myFiles = 0;
00175 XrdPosixDir **XrdPosixXrootd::myDirs = 0;
00176 int XrdPosixXrootd::highFD = -1;
00177 int XrdPosixXrootd::lastFD = -1;
00178 int XrdPosixXrootd::baseFD = 0;
00179 int XrdPosixXrootd::freeFD = 0;
00180 int XrdPosixXrootd::highDir = -1;
00181 int XrdPosixXrootd::lastDir = -1;
00182 int XrdPosixXrootd::devNull = -1;
00183 int XrdPosixXrootd::pllOpen = 0;
00184 int XrdPosixXrootd::maxThreads= 0;
00185 int XrdPosixXrootd::initDone = 0;
00186 int XrdPosixXrootd::Debug = -2;
00187
00188
00189
00190
00191
00192 void *XrdPosixXrootdCB(void *carg)
00193 {XrdPosixXrootd::OpenCB(0,0,0); return (void *)0;}
00194
00195
00196
00197
00198
00199
00200
00201
00202 XrdPosixAdminNew::XrdPosixAdminNew(const char *path) : Admin(path)
00203 {
00204
00205
00206
00207 if (!Admin.Connect())
00208 eNum = XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);
00209 else eNum = 0;
00210 }
00211
00212
00213
00214
00215
00216 int XrdPosixAdminNew::Fault()
00217 {
00218 char *etext = Admin.LastServerError()->errmsg;
00219 int RC = XrdPosixXrootd::mapError(Admin.LastServerError()->errnum);
00220
00221 if (RC != ENOENT && *etext && XrdPosixXrootd::Debug > -2)
00222 cerr <<"XrdPosix: " <<etext <<endl;
00223 errno = RC;
00224 return -1;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234 XrdPosixDir::XrdPosixDir(int dirno, const char *path) : XAdmin(path)
00235 {
00236
00237
00238
00239 if (!XAdmin.Connect())
00240 eNum = XrdPosixXrootd::mapError(XAdmin.LastServerError()->errnum);
00241 else eNum = 0;
00242
00243 fentry = -1;
00244 fentries.Clear();
00245 fdirno = dirno;
00246
00247
00248
00249 XrdOucString str(path);
00250 XrdClientUrlInfo url(str);
00251 XrdOucString dir = url.File;
00252 fpath = strdup(dir.c_str());
00253
00254
00255
00256
00257 if (!(myDirent = (dirent64 *)malloc(sizeof(dirent64) + maxname + 1)))
00258 eNum = ENOMEM;
00259 }
00260
00261
00262
00263
00264
00265 XrdPosixDir::~XrdPosixDir()
00266 {
00267 if (fpath) free(fpath);
00268 if (myDirent) free(myDirent);
00269 close(fdirno);
00270 }
00271
00272
00273
00274
00275
00276 dirent64 *XrdPosixDir::nextEntry(dirent64 *dp)
00277 {
00278 const char *cp;
00279 const int dirhdrln = dp->d_name - (char *)dp;
00280 int reclen;
00281
00282
00283
00284
00285 if (fentry<0)
00286 {if (XAdmin.DirList(fpath,fentries)) fentry = 0;
00287 else {eNum = XrdPosixXrootd::mapError(XAdmin.LastServerError()->errnum);
00288 return 0;
00289 }
00290 }
00291
00292
00293
00294 if ((fentries.GetSize()==0) || (fentry>=fentries.GetSize())) return 0;
00295
00296
00297
00298 if (!dp) dp = myDirent;
00299 cp = (fentries[fentry]).c_str();
00300 reclen = strlen(cp);
00301 if (reclen > maxname) reclen = maxname;
00302 #if defined(__macos__) || defined(__FreeBSD__)
00303 dp->d_fileno = fentry;
00304 dp->d_type = DT_UNKNOWN;
00305 dp->d_namlen = reclen;
00306 #else
00307 dp->d_ino = fentry;
00308 dp->d_off = fentry*maxname;
00309 #endif
00310 dp->d_reclen = reclen + dirhdrln;
00311 strncpy(dp->d_name, cp, reclen);
00312 dp->d_name[reclen] = '\0';
00313 fentry++;
00314 return dp;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324 XrdPosixFile::XrdPosixFile(int fd, const char *path, XrdPosixCallBack *cbP,
00325 int Opts)
00326 : theCB(cbP),
00327 Next(0),
00328 FD(fd),
00329 cbResult(0),
00330 currOffset(0),
00331 doClose(0),
00332 cbDone(0),
00333 fdClose(Opts & realFD)
00334 {
00335 static int OneVal = 1;
00336 XrdClientCallback *myCB = (cbP ? (XrdClientCallback *)this : 0);
00337 void *cbArg = (Opts & isSync ? (void *)&OneVal : 0);
00338
00339
00340
00341 if (!(XClient = new XrdClient(path, myCB, cbArg))) stat.size = 0;
00342 }
00343
00344
00345
00346
00347
00348 XrdPosixFile::~XrdPosixFile()
00349 {
00350 XrdClient *cP;
00351 if ((cP = XClient))
00352 {XClient = 0;
00353 if (doClose) {doClose = 0; cP->Close();}
00354 delete cP;
00355 }
00356 if (FD >= 0 && fdClose) close(FD);
00357 }
00358
00359
00360
00361
00362
00363
00364
00365
00366 XrdPosixXrootd::XrdPosixXrootd(int fdnum, int dirnum, int thrnum)
00367 {
00368 extern XrdPosixLinkage Xunix;
00369 struct rlimit rlim;
00370 long isize;
00371
00372
00373
00374 myMutex.Lock();
00375 if (initDone) {myMutex.UnLock(); return;}
00376 initDone = 1;
00377 myMutex.UnLock();
00378
00379
00380
00381 Xunix.Init();
00382
00383
00384
00385
00386
00387 initEnv();
00388 maxThreads = thrnum;
00389
00390
00391
00392
00393
00394 if (fdnum < 0)
00395 {fdnum = -fdnum;
00396 baseFD = ( getrlimit(RLIMIT_NOFILE, &rlim) ? 32768 : (int)rlim.rlim_cur);
00397 } else {
00398 if (!getrlimit(RLIMIT_NOFILE, &rlim)) fdnum = (int)rlim.rlim_cur;
00399 if (fdnum > 65536) fdnum = 65536;
00400 }
00401 isize = fdnum * sizeof(XrdPosixFile *);
00402
00403
00404
00405 if (!(myFiles = (XrdPosixFile **)malloc(isize))) lastFD = -1;
00406 else {memset((void *)myFiles, 0, isize); lastFD = fdnum+baseFD;}
00407
00408
00409
00410 if (dirnum > 32768) dirnum = 32768;
00411 isize = dirnum * sizeof(XrdPosixDir *);
00412 if (!(myDirs = (XrdPosixDir **)malloc(isize))) lastDir = -1;
00413 else {memset((void *)myDirs, 0, isize); lastDir = dirnum;}
00414
00415
00416
00417 devNull = open("/dev/null", O_RDWR, 0744);
00418 }
00419
00420
00421
00422
00423
00424 XrdPosixXrootd::~XrdPosixXrootd()
00425 {
00426 XrdPosixDir *dP;
00427 XrdPosixFile *fP;
00428 int i;
00429
00430 myMutex.Lock();
00431 if (myFiles)
00432 {for (i = 0; i <= highFD; i++)
00433 if ((fP = myFiles[i])) {myFiles[i] = 0; delete fP;};
00434 free(myFiles); myFiles = 0;
00435 }
00436
00437 if (myDirs) {
00438 for (i = 0; i <= highDir; i++)
00439 if ((dP = myDirs[i])) {myDirs[i] = 0; delete dP;}
00440 free(myDirs); myDirs = 0;
00441 }
00442
00443 initDone = 0;
00444 myMutex.UnLock();
00445 }
00446
00447
00448
00449
00450
00451 int XrdPosixXrootd::Access(const char *path, int amode)
00452 {
00453 XrdPosixAdminNew admin(path);
00454 long st_flags, st_modtime, st_id;
00455 long long st_size;
00456 int st_mode, aOK = 1;
00457
00458
00459
00460 if (!admin.isOK()) return admin.Result();
00461
00462
00463
00464 XrdOucString str(path);
00465 XrdClientUrlInfo url(str);
00466
00467
00468
00469 if (!admin.Admin.Stat(url.File.c_str(),
00470 st_id, st_size, st_flags, st_modtime))
00471 {errno = admin.lastError();
00472 return -1;
00473 }
00474
00475
00476
00477 st_mode = mapFlags(st_flags);
00478 if (amode & R_OK && !(st_mode & S_IRUSR)) aOK = 0;
00479 if (amode & W_OK && !(st_mode & S_IWUSR)) aOK = 0;
00480 if (amode & X_OK && !(st_mode & S_IXUSR)) aOK = 0;
00481
00482
00483
00484 if (aOK) return 0;
00485 errno = EACCES;
00486 return -1;
00487 }
00488
00489
00490
00491
00492
00493 int XrdPosixXrootd::Close(int fildes, int Stream)
00494 {
00495 XrdPosixFile *fp;
00496
00497
00498
00499 if (!(fp = findFP(fildes, 1))) return -1;
00500 if (baseFD)
00501 {int myFD = fp->FD - baseFD;
00502 if (myFD < freeFD) freeFD = myFD;
00503 myFiles[myFD] = 0;
00504 } else myFiles[fp->FD] = 0;
00505 if (Stream) fp->FD = -1;
00506
00507
00508
00509 fp->UnLock();
00510 myMutex.UnLock();
00511 delete fp;
00512 return 0;
00513 }
00514
00515
00516
00517
00518
00519 int XrdPosixXrootd::Closedir(DIR *dirp)
00520 {
00521 XrdPosixDir *XrdDirp = findDIR(dirp,1);
00522 if (!XrdDirp) return -1;
00523
00524
00525
00526 myDirs[XrdDirp->dirNo()] = 0;
00527 XrdDirp->UnLock();
00528 myMutex.UnLock();
00529 if (XrdDirp) delete XrdDirp;
00530 return 0;
00531 }
00532
00533
00534
00535
00536
00537 int XrdPosixXrootd::endPoint(int FD, char *Buff, int Blen)
00538 {
00539 XrdPosixFile *fp;
00540 XrdClientUrlInfo fURL;
00541
00542
00543
00544 if (!(fp = findFP(FD))) return 0;
00545
00546
00547
00548 fURL = fp->XClient->GetCurrentUrl();
00549 fp->UnLock();
00550
00551
00552
00553 if (!fURL.IsValid()) return -ENOTCONN;
00554
00555
00556
00557 if (snprintf(Buff, Blen, "%s:%d", fURL.Host.c_str(), fURL.Port) >= Blen)
00558 return -ENAMETOOLONG;
00559
00560
00561
00562 return fURL.Port;
00563 }
00564
00565
00566
00567
00568
00569 int XrdPosixXrootd::Fstat(int fildes, struct stat *buf)
00570 {
00571 XrdPosixFile *fp;
00572
00573
00574
00575 if (!(fp = findFP(fildes))) return -1;
00576
00577
00578
00579 initStat(buf);
00580 buf->st_size = fp->stat.size;
00581 buf->st_atime = buf->st_mtime = buf->st_ctime = fp->stat.modtime;
00582 buf->st_blocks = buf->st_size/512+1;
00583 buf->st_ino = fp->stat.id;
00584 buf->st_mode = mapFlags(fp->stat.flags);
00585
00586
00587
00588 fp->UnLock();
00589 return 0;
00590 }
00591
00592
00593
00594
00595
00596 int XrdPosixXrootd::Fsync(int fildes)
00597 {
00598 XrdPosixFile *fp;
00599
00600
00601
00602 if (!(fp = findFP(fildes))) return -1;
00603
00604
00605
00606 if (!fp->XClient->Sync()) return Fault(fp);
00607 fp->UnLock();
00608 return 0;
00609 }
00610
00611
00612
00613
00614
00615 int XrdPosixXrootd::Ftruncate(int fildes, off_t offset)
00616 {
00617 XrdPosixFile *fp;
00618
00619
00620
00621 if (!(fp = findFP(fildes))) return -1;
00622
00623
00624
00625 if (!fp->XClient->Truncate(offset)) return Fault(fp);
00626 fp->UnLock();
00627 return 0;
00628 }
00629
00630
00631
00632
00633
00634 #ifndef ENOATTR
00635 #define ENOATTR ENOTSUP
00636 #endif
00637
00638 long long XrdPosixXrootd::Getxattr (const char *path, const char *name,
00639 void *value, unsigned long long size)
00640 {
00641 XrdPosixAdminNew admin(path);
00642 kXR_int16 ReqCode = 0;
00643 kXR_int32 vsize;
00644
00645
00646
00647 if (size == 0) return 1024;
00648 vsize = static_cast<kXR_int32>(size);
00649
00650
00651
00652 if (name)
00653 { if (!strcmp(name, "xroot.space")) ReqCode = kXR_Qspace;
00654 else if (!strcmp(name, "xroot.xattr")) ReqCode = kXR_Qxattr;
00655 else {errno = ENOATTR; return -1;}
00656 }else {errno = EINVAL; return -1;}
00657
00658 if (admin.isOK())
00659 {XrdOucString str(path);
00660 XrdClientUrlInfo url(str);
00661 if (admin.Admin.Query(ReqCode, (kXR_char *)url.File.c_str(),
00662 (kXR_char *)value, vsize))
00663 return strlen((char *)value);
00664 return admin.Fault();
00665 }
00666 return admin.Result();
00667 }
00668
00669
00670
00671
00672
00673 off_t XrdPosixXrootd::Lseek(int fildes, off_t offset, int whence)
00674 {
00675 XrdPosixFile *fp;
00676 long long curroffset;
00677
00678
00679
00680 if (!(fp = findFP(fildes))) return -1;
00681
00682
00683
00684 if (whence == SEEK_SET) curroffset = fp->setOffset(offset);
00685 else if (whence == SEEK_CUR) curroffset = fp->addOffset(offset);
00686 else if (whence == SEEK_END)
00687 curroffset = fp->setOffset(fp->stat.size+offset);
00688 else {Scuttle(fp, EINVAL);}
00689
00690
00691
00692 fp->UnLock();
00693 return curroffset;
00694 }
00695
00696
00697
00698
00699
00700 int XrdPosixXrootd::Mkdir(const char *path, mode_t mode)
00701 {
00702 XrdPosixAdminNew admin(path);
00703 int uMode = 0, gMode = 0, oMode = 0;
00704
00705 if (admin.isOK())
00706 {XrdOucString str(path);
00707 XrdClientUrlInfo url(str);
00708 if (mode & S_IRUSR) uMode |= 4;
00709 if (mode & S_IWUSR) uMode |= 2;
00710 if (mode & S_IXUSR) uMode |= 1;
00711 if (mode & S_IRGRP) gMode |= 4;
00712 if (mode & S_IWGRP) gMode |= 2;
00713 if (mode & S_IXGRP) gMode |= 1;
00714 if (mode & S_IROTH) oMode |= 4;
00715 if (mode & S_IXOTH) oMode |= 1;
00716 if (admin.Admin.Mkdir(url.File.c_str(), uMode, gMode, oMode))
00717 return 0;
00718 return admin.Fault();
00719 }
00720 return admin.Result();
00721 }
00722
00723
00724
00725
00726
00727 int XrdPosixXrootd::Open(const char *path, int oflags, mode_t mode,
00728 XrdPosixCallBack *cbP)
00729 {
00730 XrdPosixFile *fp;
00731 int Opts = ((maxThreads==0) || (oflags & O_SYNC) ? XrdPosixFile::isSync : 0)
00732 | (baseFD ? 0 : XrdPosixFile::realFD);
00733 int XMode = (mode && (oflags & O_CREAT) ? mapMode(mode) : 0);
00734 int retc = 0, fd, XOflags;
00735
00736
00737
00738
00739 XOflags = (oflags & (O_WRONLY | O_RDWR) ? kXR_open_updt : kXR_open_read);
00740 if (oflags & O_CREAT) {
00741 XOflags |= (oflags & O_EXCL ? kXR_new : kXR_delete);
00742 XOflags |= kXR_mkpath;
00743 }
00744 else if (oflags & O_TRUNC && XOflags & kXR_open_updt)
00745 XOflags |= kXR_delete;
00746
00747
00748
00749 if (baseFD)
00750 {myMutex.Lock();
00751 for (fd = freeFD; fd < baseFD && myFiles[fd]; fd++);
00752 if (fd >= baseFD || oflags & isStream) fd = lastFD;
00753 else freeFD = fd+1;
00754 } else
00755 do{if ((fd = dup(devNull)) < 0) return -1;
00756 if (oflags & isStream && fd > 255)
00757 {close(fd); errno = EMFILE; return -1;}
00758 myMutex.Lock();
00759 if (fd >= lastFD || !myFiles[fd]) break;
00760 cerr <<"XrdPosix: FD " <<fd <<" closed outside of XrdPosix!" <<endl;
00761 myMutex.UnLock();
00762 } while(1);
00763
00764
00765
00766 if (fd >= lastFD || !(fp = new XrdPosixFile(fd+baseFD, path, cbP, Opts)))
00767 {myMutex.UnLock(); errno = EMFILE; return -1;}
00768 myFiles[fd] = fp;
00769 if (fd > highFD) highFD = fd;
00770 myMutex.UnLock();
00771
00772
00773
00774 if (!fp->XClient->Open(XMode, XOflags, (cbP ? 1 : pllOpen))
00775 || (!cbP && (fp->XClient->LastServerResp()->status != kXR_ok)))
00776 {retc = Fault(fp, 0);
00777 myMutex.Lock();
00778 myFiles[fd] = 0;
00779 delete fp;
00780 if (baseFD && fd < freeFD) freeFD = fd;
00781 myMutex.UnLock();
00782 errno = retc;
00783 return -1;
00784 }
00785
00786
00787
00788 if (cbP)
00789 {errno = EINPROGRESS;
00790 return -1;
00791 }
00792
00793
00794
00795 fp->isOpen();
00796 fp->XClient->Stat(&fp->stat);
00797
00798
00799
00800 return fd + baseFD;
00801 }
00802
00803
00804
00805
00806
00807 void XrdPosixXrootd::OpenCB(XrdPosixFile *fp, void *cbArg, int res)
00808 {
00809 static XrdSysMutex cbMutex;
00810 static XrdSysSemaphore cbReady(0);
00811 static XrdPosixFile *First = 0, *Last = 0;
00812 static int Waiting = 0, numThreads = 0;
00813 XrdPosixFile *cbFP;
00814 int rc = 0;
00815
00816
00817
00818 if (!fp)
00819 do {cbMutex.Lock();
00820 if (!First && !Waiting)
00821 {numThreads--; cbMutex.UnLock(); return;}
00822 while(!(cbFP = First))
00823 {Waiting = 1;
00824 cbMutex.UnLock(); cbReady.Wait(); cbMutex.Lock();
00825 Waiting = 0;
00826 }
00827 if (!(First = cbFP->Next)) Last = 0;
00828 cbMutex.UnLock();
00829 if ((rc = (cbFP->cbResult < 0))) errno = -(cbFP->cbResult);
00830 cbFP->theCB->Complete(cbFP->cbResult);
00831 if (rc) delete cbFP;
00832 } while(1);
00833
00834
00835
00836 if (!res || (fp->XClient->LastServerResp()->status) != kXR_ok)
00837 {fp->cbResult = -Fault(fp, 0);
00838 myMutex.Lock();
00839 myFiles[fp->FD - baseFD] = 0;
00840 myMutex.UnLock();
00841 } else {
00842 fp->isOpen();
00843 fp->XClient->Stat(&fp->stat);
00844 fp->cbResult = fp->FD;
00845 }
00846
00847
00848
00849 cbMutex.Lock();
00850 if (Last) Last->Next = fp;
00851 else First = fp;
00852 Last = fp; fp->Next = 0;
00853
00854
00855
00856 if (!Waiting && numThreads < maxThreads)
00857 {pthread_t tid;
00858 if ((rc = XrdSysThread::Run(&tid, XrdPosixXrootdCB, (void *)0,
00859 0, "Callback thread")))
00860 cerr <<"XrdPosix: Unable to create callback thread; "
00861 <<strerror(rc) <<endl;
00862 else numThreads++;
00863 }
00864
00865
00866
00867 cbReady.Post();
00868 cbMutex.UnLock();
00869 }
00870
00871
00872
00873
00874
00875 DIR* XrdPosixXrootd::Opendir(const char *path)
00876 {
00877 XrdPosixDir *dirp = 0;
00878 int rc, fd;
00879
00880
00881
00882 if ((fd = dup(devNull)) < 0) return (DIR*)0;
00883
00884
00885
00886 myMutex.Lock();
00887 if (fd > lastDir) rc = EMFILE;
00888 else if (!(dirp = new XrdPosixDir(fd, path))) rc = ENOMEM;
00889 else rc = dirp->Status();
00890
00891 if (!rc)
00892 {myDirs[fd] = dirp;
00893 if (fd > highDir) highDir = fd;
00894 }
00895 myMutex.UnLock();
00896
00897 if (rc) {if (dirp) {delete dirp; dirp = 0;} errno = rc;}
00898
00899 return (DIR*)dirp;
00900 }
00901
00902
00903
00904
00905
00906 ssize_t XrdPosixXrootd::Pread(int fildes, void *buf, size_t nbyte, off_t offset)
00907 {
00908 XrdPosixFile *fp;
00909 long long offs, bytes;
00910 int iosz;
00911
00912
00913
00914 if (!(fp = findFP(fildes))) return -1;
00915
00916
00917
00918 if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00919 else iosz = static_cast<int>(nbyte);
00920
00921
00922
00923 offs = static_cast<long long>(offset);
00924 if ((bytes = fp->XClient->Read(buf,offs,(int)iosz))<=0) return Fault(fp,-1);
00925
00926
00927
00928 fp->UnLock();
00929 return (ssize_t)bytes;
00930 }
00931
00932
00933
00934
00935
00936 ssize_t XrdPosixXrootd::Pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
00937 {
00938 XrdPosixFile *fp;
00939 long long offs;
00940 int iosz;
00941
00942
00943
00944 if (!(fp = findFP(fildes))) return -1;
00945
00946
00947
00948 if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00949 else iosz = static_cast<int>(nbyte);
00950
00951
00952
00953 offs = static_cast<long long>(offset);
00954 if (!fp->XClient->Write(buf, offs, iosz) && iosz) return Fault(fp);
00955
00956
00957
00958 if (offs+iosz > fp->stat.size) fp->stat.size = offs + iosz;
00959 fp->UnLock();
00960 return (ssize_t)iosz;
00961 }
00962
00963
00964
00965
00966
00967 ssize_t XrdPosixXrootd::Read(int fildes, void *buf, size_t nbyte)
00968 {
00969 XrdPosixFile *fp;
00970 long long bytes;
00971 int iosz;
00972
00973
00974
00975 if (!(fp = findFP(fildes))) return -1;
00976
00977
00978
00979
00980 if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
00981 else iosz = static_cast<int>(nbyte);
00982
00983
00984
00985 if ((bytes = fp->XClient->Read(buf, fp->Offset(), iosz)) <= 0)
00986 return Fault(fp,-1);
00987
00988
00989
00990 fp->addOffset(bytes);
00991 fp->UnLock();
00992 return (ssize_t)bytes;
00993 }
00994
00995
00996
00997
00998
00999 ssize_t XrdPosixXrootd::Readv(int fildes, const struct iovec *iov, int iovcnt)
01000 {
01001 ssize_t bytes, totbytes = 0;
01002 int i;
01003
01004
01005
01006 for (i = 0; i < iovcnt; i++)
01007 {bytes = Read(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len);
01008 if (bytes > 0) totbytes += bytes;
01009 else if (bytes < 0) return -1;
01010 else break;
01011 }
01012
01013
01014
01015 return totbytes;
01016 }
01017
01018
01019
01020
01021
01022 struct dirent* XrdPosixXrootd::Readdir(DIR *dirp)
01023 {
01024 dirent64 *dp64;
01025 dirent *dp32;
01026
01027 if (!(dp64 = Readdir64(dirp))) return 0;
01028
01029 dp32 = (struct dirent *)dp64;
01030 if (dp32->d_name != dp64->d_name)
01031 {dp32->d_ino = dp64->d_ino;
01032 #if !defined(__macos__) && !defined(__FreeBSD__)
01033 dp32->d_off = dp64->d_off;
01034 #endif
01035 dp32->d_reclen = dp64->d_reclen;
01036 strcpy(dp32->d_name, dp64->d_name);
01037 }
01038 return dp32;
01039 }
01040
01041 struct dirent64* XrdPosixXrootd::Readdir64(DIR *dirp)
01042 {
01043 XrdPosixDir *XrdDirp = findDIR(dirp);
01044 dirent64 *dp;
01045 int rc;
01046
01047
01048
01049 if (!XrdDirp) return 0;
01050
01051 if (!(dp = XrdDirp->nextEntry())) rc = XrdDirp->Status();
01052 else rc = 0;
01053
01054
01055 XrdDirp->UnLock();
01056 if (rc) errno = rc;
01057 return dp;
01058 }
01059
01060
01061
01062
01063
01064 int XrdPosixXrootd::Readdir_r(DIR *dirp, struct dirent *entry,
01065 struct dirent **result)
01066 {
01067 dirent64 *dp64;
01068 int rc;
01069
01070 if ((rc = Readdir64_r(dirp, 0, &dp64)) <= 0) {*result = 0; return rc;}
01071
01072 entry->d_ino = dp64->d_ino;
01073 #if !defined(__macos__) && !defined(__FreeBSD__)
01074 entry->d_off = dp64->d_off;
01075 #endif
01076 entry->d_reclen = dp64->d_reclen;
01077 strcpy(entry->d_name, dp64->d_name);
01078 *result = entry;
01079 return rc;
01080 }
01081
01082 int XrdPosixXrootd::Readdir64_r(DIR *dirp, struct dirent64 *entry,
01083 struct dirent64 **result)
01084 {
01085 XrdPosixDir *XrdDirp = findDIR(dirp);
01086 int rc;
01087
01088
01089
01090 if (!XrdDirp) {errno = EBADF; return -1;}
01091
01092 if (!(*result = XrdDirp->nextEntry(entry))) rc = XrdDirp->Status();
01093 else rc = 0;
01094
01095 XrdDirp->UnLock();
01096 return rc;
01097 }
01098
01099
01100
01101
01102
01103 int XrdPosixXrootd::Rename(const char *oldpath, const char *newpath)
01104 {
01105 XrdPosixAdminNew admin(oldpath);
01106
01107 if (admin.isOK())
01108 {XrdOucString oldstr(oldpath);
01109 XrdClientUrlInfo oldurl(oldstr);
01110 XrdOucString newstr(newpath);
01111 XrdClientUrlInfo newurl(newstr);
01112 if (admin.Admin.Mv(oldurl.File.c_str(),
01113 newurl.File.c_str())) return 0;
01114 return admin.Fault();
01115 }
01116 return admin.Result();
01117 }
01118
01119
01120
01121
01122
01123
01124 void XrdPosixXrootd::Rewinddir(DIR *dirp)
01125 {
01126
01127
01128 XrdPosixDir *XrdDirp = findDIR(dirp);
01129 if (!XrdDirp) return;
01130
01131 XrdDirp->rewind();
01132 XrdDirp->UnLock();
01133 }
01134
01135
01136
01137
01138
01139 int XrdPosixXrootd::Rmdir(const char *path)
01140 {
01141 XrdPosixAdminNew admin(path);
01142
01143 if (admin.isOK())
01144 {XrdOucString str(path);
01145 XrdClientUrlInfo url(str);
01146 if (admin.Admin.Rmdir(url.File.c_str())) return 0;
01147 return admin.Fault();
01148 }
01149 return admin.Result();
01150 }
01151
01152
01153
01154
01155
01156 void XrdPosixXrootd::Seekdir(DIR *dirp, long loc)
01157 {
01158
01159
01160 XrdPosixDir *XrdDirp = findDIR(dirp);
01161 if (!XrdDirp) return;
01162
01163 if (XrdDirp->getOffset()<0) XrdDirp->nextEntry();
01164 if (loc >= XrdDirp->getEntries()) loc = XrdDirp->getEntries()-1;
01165 else if (loc<0) loc = 0;
01166
01167 XrdDirp->setOffset(loc);
01168 XrdDirp->UnLock();
01169 }
01170
01171
01172
01173
01174
01175 int XrdPosixXrootd::Stat(const char *path, struct stat *buf)
01176 {
01177 XrdPosixAdminNew admin(path);
01178 long st_flags, st_modtime, st_id;
01179 long long st_size;
01180
01181
01182
01183 if (!admin.isOK()) return admin.Result();
01184
01185
01186
01187 XrdOucString str(path);
01188 XrdClientUrlInfo url(str);
01189
01190
01191
01192 if (!admin.Admin.Stat(url.File.c_str(),
01193 st_id, st_size, st_flags, st_modtime))
01194 return admin.Fault();
01195
01196
01197
01198 initStat(buf);
01199 buf->st_size = st_size;
01200 buf->st_blocks = buf->st_size/512+1;
01201 buf->st_atime = buf->st_mtime = buf->st_ctime = st_modtime;
01202 buf->st_ino = st_id;
01203 buf->st_mode = mapFlags(st_flags);
01204 return 0;
01205 }
01206
01207
01208
01209
01210
01211 int XrdPosixXrootd::Statfs(const char *path, struct statfs *buf)
01212 {
01213 struct statvfs myVfs;
01214 int rc;
01215
01216
01217
01218 if ((rc = Statvfs(path, &myVfs))) return rc;
01219
01220
01221
01222 memset(buf, 0, sizeof(buf));
01223 buf->f_bsize = myVfs.f_bsize;
01224 buf->f_blocks = myVfs.f_blocks;
01225 buf->f_bfree = myVfs.f_bfree;
01226 buf->f_files = myVfs.f_files;
01227 buf->f_ffree = myVfs.f_ffree;
01228 #if defined(__macos__) || defined(__FreeBSD__)
01229 buf->f_iosize = myVfs.f_frsize;
01230 #else
01231 buf->f_frsize = myVfs.f_frsize;
01232 #endif
01233 #if defined(__linux__) || defined(__macos__) || defined(__FreeBSD__)
01234 buf->f_bavail = myVfs.f_bavail;
01235 #endif
01236 #if defined(__linux__)
01237 buf->f_namelen = myVfs.f_namemax;
01238 #elif defined(__FreeBSD__)
01239 buf->f_namemax = myVfs.f_namemax;
01240 #endif
01241 return 0;
01242 }
01243
01244
01245
01246
01247
01248 int XrdPosixXrootd::Statvfs(const char *path, struct statvfs *buf)
01249 {
01250 static const int szVFS = sizeof(buf->f_bfree);
01251 static const long long max32 = 0x7fffffffLL;
01252 XrdPosixAdminNew admin(path);
01253 long long rwFree, ssFree, rwBlks;
01254 int rwNum, ssNum, rwUtil, ssUtil;
01255
01256
01257
01258 if (!admin.isOK()) return admin.Result();
01259
01260
01261
01262 XrdOucString str(path);
01263 XrdClientUrlInfo url(str);
01264
01265
01266
01267 if (!admin.Admin.Stat_vfs(url.File.c_str(),
01268 rwNum, rwFree, rwUtil, ssNum, ssFree, ssUtil)) return admin.Fault();
01269 if (rwNum < 0) {errno = ENOENT; return -1;}
01270
01271
01272
01273 if (rwUtil == 0) rwBlks = rwFree;
01274 else if (rwUtil >= 100) rwBlks = 0;
01275 else rwBlks = rwFree * (100 / (100 - rwUtil));
01276 if (ssUtil == 0) rwBlks += ssFree;
01277 else if (ssUtil < 100) rwBlks += ssFree * (100 / (100 - ssUtil));
01278
01279
01280
01281 if (szVFS < 8)
01282 {if (rwBlks > max32) rwBlks = max32;
01283 if (rwFree > max32) rwFree = max32;
01284 if (ssFree > max32) ssFree = max32;
01285 }
01286
01287
01288
01289 memset(buf, 0, sizeof(buf));
01290 buf->f_bsize = 1024*1024;
01291 buf->f_frsize = 1024*1024;
01292 buf->f_blocks = static_cast<fsblkcnt_t>(rwBlks);
01293 buf->f_bfree = static_cast<fsblkcnt_t>(rwFree + ssFree);
01294 buf->f_bavail = static_cast<fsblkcnt_t>(rwFree);
01295 buf->f_ffree = rwNum + ssNum;
01296 buf->f_favail = rwNum;
01297 buf->f_namemax = 255;
01298 buf->f_flag = (rwNum == 0 ? ST_RDONLY|ST_NOSUID : ST_NOSUID);
01299 return 0;
01300 }
01301
01302
01303
01304
01305
01306 long XrdPosixXrootd::Telldir(DIR *dirp)
01307 {
01308
01309
01310 XrdPosixDir *XrdDirp = findDIR(dirp);
01311 if (!XrdDirp) return -1;
01312
01313 long pos;
01314 if (XrdDirp->getOffset()<0) pos = 0;
01315 else pos = XrdDirp->getOffset();
01316 XrdDirp->UnLock();
01317 return pos;
01318 }
01319
01320
01321
01322
01323
01324 int XrdPosixXrootd::Truncate(const char *path, off_t Size)
01325 {
01326 XrdPosixAdminNew admin(path);
01327
01328 if (admin.isOK())
01329 {XrdOucString str(path);
01330 XrdClientUrlInfo url(str);
01331 if (admin.Admin.Truncate(url.File.c_str(), Size)) return 0;
01332 return admin.Fault();
01333 }
01334 return admin.Result();
01335 }
01336
01337
01338
01339
01340
01341 int XrdPosixXrootd::Unlink(const char *path)
01342 {
01343 XrdPosixAdminNew admin(path);
01344
01345 if (admin.isOK())
01346 {XrdOucString str(path);
01347 XrdClientUrlInfo url(str);
01348 if (admin.Admin.Rm(url.File.c_str())) return 0;
01349 return admin.Fault();
01350 }
01351 return admin.Result();
01352 }
01353
01354
01355
01356
01357
01358 ssize_t XrdPosixXrootd::Write(int fildes, const void *buf, size_t nbyte)
01359 {
01360 XrdPosixFile *fp;
01361 int iosz;
01362
01363
01364
01365 if (!(fp = findFP(fildes))) return -1;
01366
01367
01368
01369 if (nbyte > (size_t)0x7fffffff) {Scuttle(fp,EOVERFLOW);}
01370 else iosz = static_cast<int>(nbyte);
01371
01372
01373
01374 if (!fp->XClient->Write(buf, fp->Offset(), iosz) && iosz) return Fault(fp);
01375
01376
01377
01378 fp->addOffset(iosz, 1);
01379 fp->UnLock();
01380 return (ssize_t)iosz;
01381 }
01382
01383
01384
01385
01386
01387 ssize_t XrdPosixXrootd::Writev(int fildes, const struct iovec *iov, int iovcnt)
01388 {
01389 ssize_t totbytes = 0;
01390 int i;
01391
01392
01393
01394 for (i = 0; i < iovcnt; i++)
01395 {if (!Write(fildes,(void *)iov[i].iov_base,(size_t)iov[i].iov_len))
01396 return -1;
01397 totbytes += iov[i].iov_len;
01398 }
01399
01400
01401
01402 return totbytes;
01403 }
01404
01405
01406
01407
01408
01409 void XrdPosixXrootd::initEnv()
01410 {
01411 struct XrdPosix_Env {const char *eName; const char *xName; int *vDest;}
01412 Posix_Env[] =
01413 {
01414 {"XRDPOSIX_DEBUG", NAME_DEBUG, &Debug},
01415 {"XRDPOSIX_DSTTL", NAME_DATASERVERCONN_TTL, 0},
01416 {"XRDPOSIX_POPEN", "", &pllOpen},
01417 {"XRDPOSIX_RASZ", NAME_READAHEADSIZE, 0},
01418 {"XRDPOSIX_RCSZ", NAME_READCACHESIZE, 0},
01419 {"XRDPOSIX_RCRP", NAME_READCACHEBLKREMPOLICY,0},
01420 {"XRDPOSIX_RCUP", NAME_REMUSEDCACHEBLKS, 0},
01421 {"XRDPOSIX_RDTTL", NAME_LBSERVERCONN_TTL, 0},
01422 {"XRDPOSIX_RTO", NAME_REQUESTTIMEOUT, 0},
01423 {"XRDPOSIX_TTO", NAME_TRANSACTIONTIMEOUT, 0},
01424 {"XRDPSOIX_PSPC", NAME_MULTISTREAMCNT, 0},
01425 {"XRDPSOIX_CTO", NAME_CONNECTTIMEOUT, 0},
01426 {"XRDPSOIX_CRDELAY", NAME_RECONNECTWAIT, 0},
01427 {"XRDPSOIX_CRETRY", NAME_FIRSTCONNECTMAXCNT, 0},
01428 {"XRDPSOIX_TCPWSZ", NAME_DFLTTCPWINDOWSIZE, 0}
01429 };
01430 int Posix_Num = sizeof(Posix_Env)/sizeof(XrdPosix_Env);
01431 char *cvar, *evar;
01432 int i, doEcho;
01433 long nval;
01434
01435
01436
01437 if ((cvar = getenv("XRDPOSIX_ECHO"))) doEcho = strcmp(cvar, "0");
01438 else doEcho = 0;
01439
01440
01441
01442 setEnv(NAME_DEBUG, Debug);
01443
01444
01445
01446 for (i = 0; i < Posix_Num; i++)
01447 if ((cvar = getenv(Posix_Env[i].eName)) && *cvar)
01448 {nval = strtol(cvar, &evar, 10);
01449 if (*evar) cerr <<"XrdPosix: Invalid " <<Posix_Env[i].eName
01450 <<" value - " <<cvar <<endl;
01451 else {if (Posix_Env[i].xName[0]) setEnv(Posix_Env[i].xName, nval);
01452 if (Posix_Env[i].vDest)
01453 *Posix_Env[i].vDest = static_cast<int>(nval);
01454 if (doEcho) cerr <<"XrdPosix: " <<Posix_Env[i].eName <<" = "
01455 <<nval <<'(' <<Posix_Env[i].xName <<')' <<endl;
01456 }
01457 }
01458 }
01459
01460
01461
01462
01463
01464 bool XrdPosixXrootd::isXrootdDir(DIR *dirp)
01465 {
01466 if (!dirp) return false;
01467
01468 for (int i = 0; i <= highDir; i++)
01469 if (((XrdPosixDir*)dirp)==myDirs[i]) return true;
01470
01471 return false;
01472 }
01473
01474
01475
01476
01477
01478 int XrdPosixXrootd::mapError(int rc)
01479 {
01480 switch(rc)
01481 {case kXR_NotFound: return ENOENT;
01482 case kXR_NotAuthorized: return EACCES;
01483 case kXR_IOError: return EIO;
01484 case kXR_NoMemory: return ENOMEM;
01485 case kXR_NoSpace: return ENOSPC;
01486 case kXR_ArgTooLong: return ENAMETOOLONG;
01487 case kXR_noserver: return EHOSTUNREACH;
01488 case kXR_NotFile: return ENOTBLK;
01489 case kXR_isDirectory: return EISDIR;
01490 case kXR_FSError: return ENOSYS;
01491 default: return ECANCELED;
01492 }
01493 }
01494
01495
01496
01497
01498
01499 long long XrdPosixXrootd::QueryOpaque(const char *path, char *value, int size)
01500 {
01501 XrdPosixAdminNew admin(path);
01502 kXR_int32 vsize = static_cast<kXR_int32>(size);
01503
01504 if (admin.isOK())
01505 {XrdOucString str(path);
01506 XrdClientUrlInfo url(str);
01507 admin.Admin.GoBackToRedirector();
01508 if (admin.Admin.Query(kXR_Qopaquf, (kXR_char *)url.File.c_str(),
01509 (kXR_char *)value, vsize))
01510 return strlen((char *)value);
01511 return admin.Fault();
01512 }
01513 return admin.Result();
01514 }
01515
01516
01517
01518
01519
01520 void XrdPosixXrootd::setDebug(int val)
01521 {
01522 Debug = static_cast<long>(val);
01523 setEnv("DebugLevel", val);
01524 }
01525
01526
01527
01528
01529
01530 void XrdPosixXrootd::setEnv(const char *var, const char *val)
01531 {
01532 EnvPutString(var, val);
01533 }
01534
01535 void XrdPosixXrootd::setEnv(const char *var, long val)
01536 {
01537 EnvPutInt(var, val);
01538 }
01539
01540
01541
01542
01543
01544
01545
01546
01547 int XrdPosixXrootd::Fault(XrdPosixFile *fp, int complete)
01548 {
01549 char *etext = fp->XClient->LastServerError()->errmsg;
01550 int ecode = fp->XClient->LastServerError()->errnum;
01551 int rc = -1;
01552
01553 if (complete < 0)
01554 {if (ecode && ecode != kXR_noErrorYet) ecode = mapError(ecode);
01555 else ecode = rc = 0;
01556 } else {
01557 ecode = mapError(ecode);
01558 if (ecode != ENOENT && *etext && XrdPosixXrootd::Debug > -2)
01559 cerr <<"XrdPosix: " <<etext <<endl;
01560 }
01561
01562 if (!complete) return ecode;
01563 fp->UnLock();
01564 errno = ecode;
01565 return rc;
01566 }
01567
01568
01569
01570
01571
01572 XrdPosixFile *XrdPosixXrootd::findFP(int fd, int glk)
01573 {
01574 XrdPosixFile *fp;
01575
01576
01577
01578 if (fd >= lastFD || fd < baseFD)
01579 {errno = EBADF; return (XrdPosixFile *)0;}
01580
01581
01582
01583 myMutex.Lock();
01584 if (!(fp = myFiles[fd - baseFD]) || !(fp->Active()))
01585 {myMutex.UnLock(); errno = EBADF; return (XrdPosixFile *)0;}
01586
01587
01588
01589 fp->Lock();
01590 if (!glk) myMutex.UnLock();
01591 return fp;
01592 }
01593
01594
01595
01596
01597
01598 XrdPosixDir *XrdPosixXrootd::findDIR(DIR *dirp, int glk)
01599 {
01600 if (!dirp) { errno = EBADF; return 0; }
01601
01602
01603
01604 XrdPosixDir *XrdDirp = (XrdPosixDir*)dirp;
01605 myMutex.Lock();
01606 if (!(myDirs[XrdDirp->dirNo()]==XrdDirp))
01607 {myMutex.UnLock();
01608 errno = EBADF;
01609 return 0;
01610 }
01611
01612
01613
01614 XrdDirp->Lock();
01615 if (!glk) myMutex.UnLock();
01616 return XrdDirp;
01617 }
01618
01619
01620
01621
01622
01623 void XrdPosixXrootd::initStat(struct stat *buf)
01624 {
01625 static int initStatDone = 0;
01626 static dev_t st_rdev;
01627 static dev_t st_dev;
01628 static uid_t myUID = getuid();
01629 static gid_t myGID = getgid();
01630
01631
01632
01633
01634 if (!initStatDone) {initStatDone = 1; initXdev(st_dev, st_rdev);}
01635 memset(buf, 0, sizeof(struct stat));
01636
01637
01638
01639 buf->st_blksize= 64*1024;
01640 buf->st_dev = st_dev;
01641 buf->st_rdev = st_rdev;
01642 buf->st_nlink = 1;
01643 buf->st_uid = myUID;
01644 buf->st_gid = myGID;
01645 }
01646
01647
01648
01649
01650
01651 void XrdPosixXrootd::initXdev(dev_t &st_dev, dev_t &st_rdev)
01652 {
01653 struct stat buf;
01654
01655
01656
01657 if (stat("/tmp", &buf)) {st_dev = 0; st_rdev = 0;}
01658 else {st_dev = buf.st_dev; st_rdev = buf.st_rdev;}
01659 }
01660
01661
01662
01663
01664
01665 int XrdPosixXrootd::mapFlags(int flags)
01666 {
01667 int newflags = 0;
01668
01669
01670
01671 if (flags & kXR_xset) newflags |= S_IXUSR;
01672 if (flags & kXR_readable) newflags |= S_IRUSR;
01673 if (flags & kXR_writable) newflags |= S_IWUSR;
01674 if (flags & kXR_other) newflags |= S_IFBLK;
01675 else if (flags & kXR_isDir) newflags |= S_IFDIR;
01676 else newflags |= S_IFREG;
01677 if (flags & kXR_offline) newflags |= S_ISVTX;
01678 if (flags & kXR_poscpend)newflags |= S_ISUID;
01679
01680 return newflags;
01681 }
01682
01683
01684
01685
01686
01687 int XrdPosixXrootd::mapMode(mode_t mode)
01688 { int XMode = 0;
01689
01690
01691
01692 if (mode & S_IRUSR) XMode |= kXR_ur;
01693 if (mode & S_IWUSR) XMode |= kXR_uw;
01694 if (mode & S_IXUSR) XMode |= kXR_ux;
01695 if (mode & S_IRGRP) XMode |= kXR_gr;
01696 if (mode & S_IWGRP) XMode |= kXR_gw;
01697 if (mode & S_IXGRP) XMode |= kXR_gx;
01698 if (mode & S_IROTH) XMode |= kXR_or;
01699 if (mode & S_IXOTH) XMode |= kXR_ox;
01700 return XMode;
01701 }