00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdSfsNativeCVSID = "$Id: XrdSfsNative.cc 35287 2010-09-14 21:19:35Z ganis $";
00014
00015 #include <sys/types.h>
00016 #include <unistd.h>
00017 #include <dirent.h>
00018 #include <errno.h>
00019 #include <fcntl.h>
00020 #include <memory.h>
00021 #include <string.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <sys/param.h>
00025 #include <sys/stat.h>
00026
00027 #include "XrdVersion.hh"
00028 #include "XrdSys/XrdSysError.hh"
00029 #include "XrdSys/XrdSysHeaders.hh"
00030 #include "XrdSys/XrdSysLogger.hh"
00031 #include "XrdSys/XrdSysPthread.hh"
00032 #include "XrdSec/XrdSecInterface.hh"
00033 #include "XrdSfs/XrdSfsAio.hh"
00034 #include "XrdSfs/XrdSfsNative.hh"
00035
00036 #ifdef AIX
00037 #include <sys/mode.h>
00038 #endif
00039
00040
00041
00042
00043
00044 #ifndef S_IAMB
00045 #define S_IAMB 0x1FF
00046 #endif
00047
00048
00049
00050
00051
00052 XrdSysError *XrdSfsNative::eDest;
00053
00054
00055
00056
00057
00058 class XrdSfsUFS
00059 {
00060 public:
00061
00062 static int Chmod(const char *fn, mode_t mode) {return chmod(fn, mode);}
00063
00064 static int Close(int fd) {return close(fd);}
00065
00066 static int Mkdir(const char *fn, mode_t mode) {return mkdir(fn, mode);}
00067
00068 static int Open(const char *path, int oflag, mode_t omode)
00069 {return open(path, oflag, omode);}
00070
00071 static int Rem(const char *fn) {return unlink(fn);}
00072
00073 static int Remdir(const char *fn) {return rmdir(fn);}
00074
00075 static int Rename(const char *ofn, const char *nfn) {return rename(ofn, nfn);}
00076
00077 static int Statfd(int fd, struct stat *buf) {return fstat(fd, buf);}
00078
00079 static int Statfn(const char *fn, struct stat *buf) {return stat(fn, buf);}
00080
00081 static int Truncate(const char *fn, off_t flen) {return truncate(fn, flen);}
00082 };
00083
00084
00085
00086
00087
00088 XrdSfsNative::XrdSfsNative(XrdSysError *ep)
00089 {
00090 eDest = ep;
00091 }
00092
00093
00094
00095
00096
00097 XrdSfsFileSystem *XrdSfsGetFileSystem(XrdSfsFileSystem *native_fs,
00098 XrdSysLogger *lp)
00099 {
00100 static XrdSysError Eroute(lp, "XrdSfs");
00101 static XrdSfsNative myFS(&Eroute);
00102
00103 Eroute.Say("Copr. 2007 Stanford University/SLAC "
00104 "sfs (Standard File System) v 9.0n");
00105
00106 return &myFS;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116 int XrdSfsNativeDirectory::open(const char *dir_path,
00117 const XrdSecClientName *client,
00118 const char *info)
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 {
00129 static const char *epname = "opendir";
00130
00131
00132
00133 if (dh) return
00134 XrdSfsNative::Emsg(epname, error, EADDRINUSE,
00135 "open directory", dir_path);
00136
00137
00138
00139 ateof = 0;
00140 fname = strdup(dir_path);
00141
00142
00143
00144 if (!(dh = opendir(dir_path))) return
00145 XrdSfsNative::Emsg(epname,error,errno,"open directory",dir_path);
00146
00147
00148
00149 return SFS_OK;
00150 }
00151
00152
00153
00154
00155
00156 const char *XrdSfsNativeDirectory::nextEntry()
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 {
00168 static const char *epname = "nextEntry";
00169 struct dirent *rp;
00170 int retc;
00171
00172
00173
00174 if (!dh)
00175 {XrdSfsNative::Emsg(epname,error,EBADF,"read directory",fname);
00176 return (const char *)0;
00177 }
00178
00179
00180
00181 if (ateof) return (const char *)0;
00182
00183
00184
00185 errno = 0;
00186 if ((retc = readdir_r(dh, d_pnt, &rp)))
00187 {if (retc && errno != 0)
00188 XrdSfsNative::Emsg(epname,error,retc,"read directory",fname);
00189 d_pnt->d_name[0] = '\0';
00190 return (const char *)0;
00191 }
00192
00193
00194
00195 if (retc || !rp || !d_pnt->d_name[0])
00196 {ateof = 1;
00197 error.clear();
00198 return (const char *)0;
00199 }
00200
00201
00202
00203 return (const char *)(d_pnt->d_name);
00204 }
00205
00206
00207
00208
00209
00210 int XrdSfsNativeDirectory::close()
00211
00212
00213
00214
00215
00216
00217
00218 {
00219 static const char *epname = "closedir";
00220
00221
00222
00223 if (dh && closedir(dh))
00224 {XrdSfsNative::Emsg(epname, error, errno, "close directory", fname);
00225 return SFS_ERROR;
00226 }
00227
00228
00229
00230 if (fname) free(fname);
00231 dh = (DIR *)0;
00232 return SFS_OK;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242 int XrdSfsNativeFile::open(const char *path,
00243 XrdSfsFileOpenMode open_mode,
00244 mode_t Mode,
00245 const XrdSecClientName *client,
00246 const char *info)
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 {
00268 static const char *epname = "open";
00269 const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH;
00270 char *opname;
00271 mode_t acc_mode = Mode & S_IAMB;
00272 int retc, open_flag = 0;
00273 struct stat buf;
00274
00275
00276
00277 if (oh >= 0)
00278 return XrdSfsNative::Emsg(epname,error,EADDRINUSE,"open file",path);
00279 fname = strdup(path);
00280
00281
00282
00283 switch(open_mode & (SFS_O_RDONLY | SFS_O_WRONLY | SFS_O_RDWR))
00284 {
00285 case SFS_O_RDONLY: open_flag = O_RDONLY; break;
00286 case SFS_O_WRONLY: open_flag = O_WRONLY; break;
00287 case SFS_O_RDWR: open_flag = O_RDWR; break;
00288 default: open_flag = O_RDONLY; break;
00289 }
00290
00291
00292
00293 if (open_mode & SFS_O_CREAT)
00294 {open_flag = O_RDWR | O_CREAT | O_EXCL;
00295 opname = (char *)"create";
00296 if ((Mode & SFS_O_MKPTH) && (retc = XrdSfsNative::Mkpath(path,AMode,info)))
00297 return XrdSfsNative::Emsg(epname,error,retc,"create path for",path);
00298 } else if (open_mode & SFS_O_TRUNC)
00299 {open_flag = O_RDWR | O_CREAT | O_TRUNC;
00300 opname = (char *)"truncate";
00301 } else opname = (char *)"open";
00302
00303
00304
00305 if ((oh = XrdSfsUFS::Open(path, open_flag, acc_mode)) >= 0)
00306 {do {retc = XrdSfsUFS::Statfd(oh, &buf);} while(retc && errno == EINTR);
00307 if (!retc && !(buf.st_mode & S_IFREG))
00308 {close(); oh = (buf.st_mode & S_IFDIR ? -EISDIR : -ENOTBLK);}
00309 } else {
00310 oh = -errno;
00311 if (errno == EEXIST)
00312 {do {retc = XrdSfsUFS::Statfn(path, &buf);}
00313 while(retc && errno == EINTR);
00314 if (!retc && (buf.st_mode & S_IFDIR)) oh = -EISDIR;
00315 }
00316 }
00317
00318
00319
00320 if (oh < 0) return XrdSfsNative::Emsg(epname, error, oh, opname, path);
00321 return SFS_OK;
00322 }
00323
00324
00325
00326
00327
00328 int XrdSfsNativeFile::close()
00329
00330
00331
00332
00333
00334
00335
00336 {
00337 static const char *epname = "close";
00338
00339
00340
00341 if (oh >= 0 && XrdSfsUFS::Close(oh))
00342 return XrdSfsNative::Emsg(epname, error, errno, "close", fname);
00343 oh = -1;
00344 if (fname) {free(fname); fname = 0;}
00345 return SFS_OK;
00346 }
00347
00348
00349
00350
00351
00352 int XrdSfsNativeFile::fctl(const int cmd,
00353 const char *args,
00354 XrdOucErrInfo &out_error)
00355 {
00356
00357
00358 if (cmd == SFS_FCTL_GETFD)
00359 {out_error.setErrCode(oh);
00360 return SFS_OK;
00361 }
00362
00363
00364
00365 out_error.setErrInfo(EEXIST, "fctl operation not supported");
00366 return SFS_ERROR;
00367 }
00368
00369
00370
00371
00372
00373 XrdSfsXferSize XrdSfsNativeFile::read(XrdSfsFileOffset offset,
00374 char *buff,
00375 XrdSfsXferSize blen)
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 {
00388 static const char *epname = "read";
00389 XrdSfsXferSize nbytes;
00390
00391
00392
00393 #if _FILE_OFFSET_BITS!=64
00394 if (offset > 0x000000007fffffff)
00395 return XrdSfsNative::Emsg(epname, error, EFBIG, "read", fname);
00396 #endif
00397
00398
00399
00400 do { nbytes = pread(oh, (void *)buff, (size_t)blen, (off_t)offset); }
00401 while(nbytes < 0 && errno == EINTR);
00402
00403 if (nbytes < 0)
00404 return XrdSfsNative::Emsg(epname, error, errno, "read", fname);
00405
00406
00407
00408 return nbytes;
00409 }
00410
00411
00412
00413
00414
00415 int XrdSfsNativeFile::read(XrdSfsAio *aiop)
00416 {
00417
00418
00419
00420 aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
00421 (char *)aiop->sfsAio.aio_buf,
00422 (XrdSfsXferSize)aiop->sfsAio.aio_nbytes);
00423 aiop->doneRead();
00424 return 0;
00425 }
00426
00427
00428
00429
00430
00431 XrdSfsXferSize XrdSfsNativeFile::write(XrdSfsFileOffset offset,
00432 const char *buff,
00433 XrdSfsXferSize blen)
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 {
00449 static const char *epname = "write";
00450 XrdSfsXferSize nbytes;
00451
00452
00453
00454 #if _FILE_OFFSET_BITS!=64
00455 if (offset > 0x000000007fffffff)
00456 return XrdSfsNative::Emsg(epname, error, EFBIG, "write", fname);
00457 #endif
00458
00459
00460
00461 do { nbytes = pwrite(oh, (void *)buff, (size_t)blen, (off_t)offset); }
00462 while(nbytes < 0 && errno == EINTR);
00463
00464 if (nbytes < 0)
00465 return XrdSfsNative::Emsg(epname, error, errno, "write", fname);
00466
00467
00468
00469 return nbytes;
00470 }
00471
00472
00473
00474
00475
00476 int XrdSfsNativeFile::write(XrdSfsAio *aiop)
00477 {
00478
00479
00480
00481 aiop->Result = this->write((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
00482 (char *)aiop->sfsAio.aio_buf,
00483 (XrdSfsXferSize)aiop->sfsAio.aio_nbytes);
00484 aiop->doneWrite();
00485 return 0;
00486 }
00487
00488
00489
00490
00491
00492 int XrdSfsNativeFile::stat(struct stat *buf)
00493
00494
00495
00496
00497
00498
00499
00500 {
00501 static const char *epname = "stat";
00502
00503
00504
00505 if (XrdSfsUFS::Statfd(oh, buf))
00506 return XrdSfsNative::Emsg(epname, error, errno, "state", fname);
00507
00508
00509
00510 return SFS_OK;
00511 }
00512
00513
00514
00515
00516
00517 int XrdSfsNativeFile::sync()
00518
00519
00520
00521
00522
00523
00524
00525 {
00526 static const char *epname = "sync";
00527
00528
00529
00530 if (fsync(oh))
00531 return XrdSfsNative::Emsg(epname,error,errno,"synchronize",fname);
00532
00533
00534
00535 return SFS_OK;
00536 }
00537
00538
00539
00540
00541
00542 int XrdSfsNativeFile::sync(XrdSfsAio *aiop)
00543 {
00544
00545
00546
00547 aiop->Result = this->sync();
00548 aiop->doneWrite();
00549 return 0;
00550 }
00551
00552
00553
00554
00555
00556 int XrdSfsNativeFile::truncate(XrdSfsFileOffset flen)
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 {
00571 static const char *epname = "trunc";
00572
00573
00574
00575 if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
00576 return XrdSfsNative::Emsg(epname, error, EFBIG, "truncate", fname);
00577
00578
00579
00580 if (ftruncate(oh, flen))
00581 return XrdSfsNative::Emsg(epname, error, errno, "truncate", fname);
00582
00583
00584
00585 return SFS_OK;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595 int XrdSfsNative::chmod(const char *path,
00596 XrdSfsMode Mode,
00597 XrdOucErrInfo &error,
00598 const XrdSecClientName *client,
00599 const char *info)
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610 {
00611 static const char *epname = "chmod";
00612 mode_t acc_mode = Mode & S_IAMB;
00613
00614
00615
00616 if (XrdSfsUFS::Chmod(path, acc_mode) )
00617 return XrdSfsNative::Emsg(epname,error,errno,"change mode on",path);
00618
00619
00620
00621 return SFS_OK;
00622 }
00623
00624
00625
00626
00627
00628 int XrdSfsNative::exists(const char *path,
00629 XrdSfsFileExistence &file_exists,
00630 XrdOucErrInfo &error,
00631 const XrdSecClientName *client,
00632 const char *info)
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 {
00651 static const char *epname = "exists";
00652 struct stat fstat;
00653
00654
00655
00656 if (!XrdSfsUFS::Statfn(path, &fstat) )
00657 { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
00658 else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
00659 else file_exists=XrdSfsFileExistNo;
00660 return SFS_OK;
00661 }
00662 if (errno == ENOENT)
00663 {file_exists=XrdSfsFileExistNo;
00664 return SFS_OK;
00665 }
00666
00667
00668
00669 return XrdSfsNative::Emsg(epname, error, errno, "locate", path);
00670 }
00671
00672
00673
00674
00675
00676 int XrdSfsNative::fsctl(const int cmd,
00677 const char *args,
00678 XrdOucErrInfo &out_error,
00679 const XrdSecClientName *client)
00680 {
00681 out_error.setErrInfo(ENOTSUP, "Operation not supported.");
00682 return SFS_ERROR;
00683 }
00684
00685
00686
00687
00688
00689 const char *XrdSfsNative::getVersion() {return XrdVERSION;}
00690
00691
00692
00693
00694
00695 int XrdSfsNative::mkdir(const char *path,
00696 XrdSfsMode Mode,
00697 XrdOucErrInfo &error,
00698 const XrdSecClientName *client,
00699 const char *info)
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712 {
00713 static const char *epname = "mkdir";
00714 mode_t acc_mode = Mode & S_IAMB;
00715
00716
00717
00718 if (Mode & SFS_O_MKPTH) Mkpath(path, acc_mode, info);
00719
00720
00721
00722 if (XrdSfsUFS::Mkdir(path, acc_mode) )
00723 return XrdSfsNative::Emsg(epname,error,errno,"create directory",path);
00724
00725
00726
00727 return SFS_OK;
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 int XrdSfsNative::Mkpath(const char *path, mode_t mode, const char *info)
00744 {
00745 char actual_path[MAXPATHLEN], *local_path, *next_path;
00746 unsigned int plen;
00747 struct stat buf;
00748
00749
00750
00751 if (!(plen = strlen(path))) return -ENOENT;
00752 if (plen >= sizeof(actual_path)) return -ENAMETOOLONG;
00753 strcpy(actual_path, path);
00754 if (actual_path[plen-1] == '/') actual_path[plen-1] = '\0';
00755
00756
00757
00758 if (!(local_path = rindex(actual_path, (int)'/'))
00759 || local_path == actual_path) return 0;
00760 *local_path = '\0';
00761 if (!XrdSfsUFS::Statfn(actual_path, &buf)) return 0;
00762 *local_path = '/';
00763
00764
00765
00766
00767 local_path = actual_path+1;
00768 while((next_path = index(local_path, int('/'))))
00769 {*next_path = '\0';
00770 if (XrdSfsUFS::Mkdir(actual_path,mode) && errno != EEXIST)
00771 return -errno;
00772 *next_path = '/';
00773 local_path = next_path+1;
00774 }
00775
00776
00777
00778 return 0;
00779 }
00780
00781
00782
00783
00784
00785 int XrdSfsNative::rem(const char *path,
00786 XrdOucErrInfo &error,
00787 const XrdSecClientName *client,
00788 const char *info)
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 {
00800 static const char *epname = "rem";
00801
00802
00803
00804 if (XrdSfsUFS::Rem(path) )
00805 return XrdSfsNative::Emsg(epname, error, errno, "remove", path);
00806
00807
00808
00809 return SFS_OK;
00810 }
00811
00812
00813
00814
00815
00816 int XrdSfsNative::remdir(const char *path,
00817 XrdOucErrInfo &error,
00818 const XrdSecClientName *client,
00819 const char *info)
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 {
00831 static const char *epname = "remdir";
00832
00833
00834
00835 if (XrdSfsUFS::Remdir(path) )
00836 return XrdSfsNative::Emsg(epname, error, errno, "remove", path);
00837
00838
00839
00840 return SFS_OK;
00841 }
00842
00843
00844
00845
00846
00847 int XrdSfsNative::rename(const char *old_name,
00848 const char *new_name,
00849 XrdOucErrInfo &error,
00850 const XrdSecClientName *client,
00851 const char *infoO,
00852 const char *infoN)
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 {
00866 static const char *epname = "rename";
00867
00868
00869
00870 if (XrdSfsUFS::Rename(old_name, new_name) )
00871 return XrdSfsNative::Emsg(epname, error, errno, "rename", old_name);
00872
00873
00874
00875 return SFS_OK;
00876 }
00877
00878
00879
00880
00881
00882 int XrdSfsNative::stat(const char *path,
00883 struct stat *buf,
00884 XrdOucErrInfo &error,
00885 const XrdSecClientName *client,
00886 const char *info)
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 {
00899 static const char *epname = "stat";
00900
00901
00902
00903 if (XrdSfsUFS::Statfn(path, buf) )
00904 return XrdSfsNative::Emsg(epname, error, errno, "state", path);
00905
00906
00907
00908 return SFS_OK;
00909 }
00910
00911
00912
00913
00914
00915 int XrdSfsNative::truncate(const char *path,
00916 XrdSfsFileOffset flen,
00917 XrdOucErrInfo &error,
00918 const XrdSecClientName *client,
00919 const char *info)
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 {
00938 static const char *epname = "trunc";
00939
00940
00941
00942 if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
00943 return XrdSfsNative::Emsg(epname, error, EFBIG, "truncate", path);
00944
00945
00946
00947 if (XrdSfsUFS::Truncate(path, flen) )
00948 return XrdSfsNative::Emsg(epname, error, errno, "truncate", path);
00949
00950
00951
00952 return SFS_OK;
00953 }
00954
00955
00956
00957
00958
00959 int XrdSfsNative::Emsg(const char *pfx,
00960 XrdOucErrInfo &einfo,
00961 int ecode,
00962 const char *op,
00963 const char *target)
00964 {
00965 char *etext, buffer[MAXPATHLEN+80], unkbuff[64];
00966
00967
00968
00969 if (ecode < 0) ecode = -ecode;
00970 if (!(etext = strerror(ecode)))
00971 {sprintf(unkbuff, "reason unknown (%d)", ecode); etext = unkbuff;}
00972
00973
00974
00975 snprintf(buffer,sizeof(buffer),"Unable to %s %s; %s", op, target, etext);
00976
00977
00978
00979 #ifndef NODEBUG
00980 eDest->Emsg(pfx, buffer);
00981 #endif
00982
00983
00984
00985 einfo.setErrInfo(ecode, buffer);
00986
00987 return SFS_ERROR;
00988 }