XrdOssMSS.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d O s s M S S . c c                           */
00004 /*                                                                            */
00005 /* (C) 2003 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*                DE-AC03-76-SFO0515 with the Deprtment of Energy             */
00009 /******************************************************************************/
00010   
00011 //         $Id: XrdOssMSS.cc 34000 2010-06-21 06:49:56Z ganis $
00012 
00013 const char *XrdOssMSSCVSID = "$Id: XrdOssMSS.cc 34000 2010-06-21 06:49:56Z ganis $";
00014 
00015 #include <dirent.h>
00016 #include <unistd.h>
00017 #include <errno.h>
00018 #include <strings.h>
00019 #include <signal.h>
00020 #include <stdio.h>
00021 #include <time.h>
00022 #if defined(AIX) || defined(__solaris__)
00023 #include <sys/vnode.h>
00024 #include <sys/mode.h>
00025 #endif
00026 #include <sys/param.h>
00027 #include <sys/types.h>
00028 #include <sys/stat.h>
00029 #include <sys/socket.h>
00030 #include <sys/un.h>
00031 #include <sys/wait.h>
00032 
00033 #include "XrdNet/XrdNetOpts.hh"
00034 #include "XrdNet/XrdNetSocket.hh"
00035 #include "XrdOss/XrdOssApi.hh"
00036 #include "XrdOss/XrdOssConfig.hh"
00037 #include "XrdOss/XrdOssError.hh"
00038 #include "XrdOss/XrdOssTrace.hh"
00039 #include "XrdOuc/XrdOucProg.hh"
00040 #include "XrdOuc/XrdOucStream.hh"
00041 #include "XrdSys/XrdSysError.hh"
00042 #include "XrdSys/XrdSysHeaders.hh"
00043 #include "XrdSys/XrdSysLogger.hh"
00044 #include "XrdSys/XrdSysPlatform.hh"
00045 
00046 /******************************************************************************/
00047 /*                  E r r o r   R o u t i n g   O b j e c t                   */
00048 /******************************************************************************/
00049   
00050 extern XrdSysError OssEroute;
00051 
00052 extern XrdOucTrace OssTrace;
00053 
00054 /******************************************************************************/
00055 /*                               d e f i n e s                                */
00056 /******************************************************************************/
00057 
00058 #define NegVal(x) (x <= 0 ? (x < 0 ? x : -1) : -x)
00059 
00060 /******************************************************************************/
00061 /*                           f i l e   h a n d l e                            */
00062 /******************************************************************************/
00063 
00064 /* These are private data structures. They are allocated dynamically to the
00065    appropriate size (yes, that means dbx has a tough time).
00066 */
00067 
00068 struct XrdOssHandle
00069        {int hflag;
00070         XrdOucStream *sp;
00071 
00072         XrdOssHandle(int type, XrdOucStream *newsp=0) {hflag = type; sp = newsp;}
00073        ~XrdOssHandle() {if (sp) delete sp; hflag = 0;}
00074 
00075        };
00076 
00077 #define XRDOSS_HT_EOF    1
00078 #define XRDOSS_HT_DIR    4
00079 
00080 /******************************************************************************/
00081 /*          M a s s   S t o r a g e   R e l a t e d   M e t h o d s           */
00082 /******************************************************************************/
00083   
00084 /******************************************************************************/
00085 /*                               o p e n d i r                                */
00086 /******************************************************************************/
00087   
00088 void *XrdOssSys::MSS_Opendir(const char *dir_path, int &rc) {
00089 /*
00090   Function: Open the directory `path' and prepare for reading.
00091 
00092   Input:    path      - The fully qualified name of the directory to open.
00093 
00094   Output:   Returns a directory handle to be used for subsequent
00095             operations. If an error occurs, (-errno) is returned.
00096 */
00097      const char *epname = "MSS_Opendir";
00098      struct XrdOssHandle *oh;
00099      XrdOucStream *sp;
00100 
00101      // Make sure the path is not too long.
00102      //
00103      if (strlen(dir_path) > MAXPATHLEN)
00104         {OssEroute.Emsg(epname, "mss path too long - ", dir_path);
00105          rc = -ENAMETOOLONG;
00106          return (void *)0;
00107         }
00108 
00109      // Issue it now to trap any errors but defer reading the result until
00110      // readdir() is called. This does tie up a process, sigh.
00111      //
00112      if ( (rc = MSS_Xeq(&sp, ENOENT, "dlist", dir_path)))
00113         return (void *)0;
00114 
00115      // Allocate storage for the handle and return a copy of it.
00116      //
00117      if (!(oh = new XrdOssHandle(XRDOSS_HT_DIR, sp))) 
00118         {delete sp; rc = -ENOMEM; return (void *)0;}
00119      return (void *)oh;
00120 }
00121 
00122 /******************************************************************************/
00123 /*                               r e a d d i r                                */
00124 /******************************************************************************/
00125 
00126 int XrdOssSys::MSS_Readdir(void *dir_handle, char *buff, int blen) {
00127 /*
00128   Function: Read the next entry if directory 'dir_handle'.
00129 
00130   Input:    dir_handle - The value returned by a successful opendir() call.
00131             buff       - Buffer to hold directory name.
00132             blen       - Size of the buffer.
00133 
00134   Output:   Upon success, places the contents of the next directory entry
00135             in buff. When the end of the directory is encountered buff
00136             will be set to a null string.
00137 
00138             Upon failure, returns a (-errno).
00139 */
00140     const char *epname = "MSS_Readdir";
00141     int retc;
00142     struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
00143     char *resp;
00144 
00145     // Verify that the handle is correct.
00146     //
00147     if ( !(oh->hflag & XRDOSS_HT_DIR) )
00148        {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
00149 
00150     // Read a record from the directory, if possible.
00151     //
00152     if (oh->hflag & XRDOSS_HT_EOF) *buff = '\0';
00153        else if ((resp = oh->sp->GetLine()))
00154                {if ( ((int)strlen(resp)) >= blen )
00155                    {*buff = '\0';
00156                     return OssEroute.Emsg(epname, -EOVERFLOW,
00157                                             "readdir rmt", resp);
00158                    }
00159                    strlcpy(buff, resp, blen);
00160                } else {
00161                 if ((retc = oh->sp->LastError())) return NegVal(retc);
00162                    else {*buff = '\0'; oh->hflag |= XRDOSS_HT_EOF;}
00163                }
00164     return XrdOssOK;
00165 }
00166 
00167 /******************************************************************************/
00168 /*                              c l o s e d i r                               */
00169 /******************************************************************************/
00170   
00171 int XrdOssSys::MSS_Closedir(void *dir_handle) {
00172 /*
00173   Function: Close the directory associated with handle "dir_handle".
00174 
00175   Input:    dir_handle - The handle returned by opendir().
00176 
00177   Output:   Returns 0 upon success and (-errno) upon failure.
00178 */
00179     const char *epname = "MSS_Closedir";
00180     struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
00181 
00182     if ( !(oh->hflag & XRDOSS_HT_DIR) )
00183        {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
00184     delete oh;
00185     return XrdOssOK;
00186 }
00187 
00188 /******************************************************************************/
00189 /*                                c r e a t e                                 */
00190 /******************************************************************************/
00191 
00192 int XrdOssSys::MSS_Create(const char *path, mode_t file_mode, XrdOucEnv &env)
00193 /*
00194   Function: Create a file named `path' with 'file_mode' access mode bits set.
00195 
00196   Input:    path      - The fully qualified name of the file to create.
00197             file_mode - The Posix access mode bits to be assigned to the file.
00198                         These bits correspond to the standard Unix permission
00199                         bits (e.g., 744 == "rwxr--r--").
00200             env         Enviornmental information.
00201 
00202   Output:   Returns zero upon success and (-errno) otherwise.
00203 */
00204 {
00205     const char *epname = "MSS_Create";
00206     char myMode[16];
00207 
00208     // Make sure the path is not too long.
00209     //
00210     if (strlen(path) > MAXPATHLEN)
00211        {OssEroute.Emsg(epname, "mss path too long - ", path);
00212         return -ENAMETOOLONG;
00213        }
00214 
00215     // Construct the cmd to create the file. We currently don't support cosid.
00216     //
00217     sprintf(myMode, "%o", static_cast<int>(file_mode));
00218 
00219     // Create the file in in the mass store system
00220     //
00221     return MSS_Xeq(0, 0, "create", path, myMode);
00222 }
00223 
00224 
00225 /******************************************************************************/
00226 /*                                 s t a t                                    */
00227 /******************************************************************************/
00228 
00229 /*
00230   Function: Determine if file 'path' actually exists.
00231 
00232   Input:    path        - Is the fully qualified name of the file to be tested.
00233             buff        - pointer to a 'stat' structure to hold the attributes
00234                           of the file.
00235 
00236   Output:   Returns 0 upon success and -errno upon failure.
00237 */
00238 
00239 int XrdOssSys::MSS_Stat(const char *path, struct stat *buff)
00240 {
00241     const char *epname = "MSS_Stat";
00242     char ftype, mtype[10], *resp;
00243     int retc, xt_nlink;
00244     long xt_uid, xt_gid, atime, ctime, mtime, xt_blksize, xt_blocks;
00245     long long xt_size;
00246     XrdOucStream *sfd;
00247 
00248     // Make sure the path is not too long.
00249     //
00250     if (strlen(path) > MAXPATHLEN)
00251        {OssEroute.Emsg(epname, "mss path too long - ", path);
00252         return -ENAMETOOLONG;
00253        }
00254 
00255     // Issue the command. This may be an immediate exists a or full statx.
00256     //
00257     if (!buff) return MSS_Xeq(0, ENOENT, (isMSSC ? "statx" : "exists"), path);
00258     if ((retc = MSS_Xeq(&sfd, ENOENT, "statx", path))) return retc;
00259 
00260     // Read in the results.
00261     //
00262     if ( !(resp = sfd ->GetLine()))
00263        return OssEroute.Emsg(epname,-XRDOSS_E8012,"process ",path);
00264 
00265     // Extract data from the response.
00266     //
00267     sscanf(resp, "%c %9s %d %ld %ld %ld %ld %ld %lld %ld %ld", &ftype, mtype,
00268            &xt_nlink, &xt_uid, &xt_gid, &atime, &ctime, &mtime,
00269            &xt_size, &xt_blksize, &xt_blocks);
00270 
00271     // Set the stat buffer, appropriately.
00272     //
00273     memset( (char *)buff, 0, sizeof(struct stat) );
00274     buff->st_nlink = static_cast<nlink_t>(xt_nlink);
00275     buff->st_uid   = static_cast<uid_t>(xt_uid);
00276     buff->st_gid   = static_cast<gid_t>(xt_gid);
00277     buff->st_atime = static_cast<time_t>(atime);
00278     buff->st_ctime = static_cast<time_t>(ctime);
00279     buff->st_mtime = static_cast<time_t>(mtime);
00280     buff->st_size  = static_cast<off_t>(xt_size);
00281     buff->st_blksize=static_cast<long>(xt_blksize);
00282 #ifdef __macos__
00283     buff->st_blocks =                      xt_blocks;
00284 #else
00285     buff->st_blocks =static_cast<blkcnt_t>(xt_blocks);
00286 #endif
00287 
00288     if (ftype == 'd') buff->st_mode |=  S_IFDIR;
00289        else if (ftype == 'l') buff->st_mode |= S_IFLNK;
00290                else buff->st_mode |= S_IFREG;
00291 
00292     buff->st_mode |= tranmode(&mtype[0]) << 6;
00293     buff->st_mode |= tranmode(&mtype[3]) << 3;
00294     buff->st_mode |= tranmode(&mtype[6]);
00295 
00296     delete sfd;
00297     return 0;
00298 }
00299 
00300 int XrdOssSys::tranmode(char *mode) {
00301     int mbits = 0;
00302     if (mode[0] == 'r') mbits |= S_IROTH;
00303     if (mode[1] == 'w') mbits |= S_IWOTH;
00304     if (mode[2] == 'x') mbits |= S_IXOTH;
00305     return mbits;
00306 }
00307 
00308 /******************************************************************************/
00309 /*                                r e m o v e                                 */
00310 /******************************************************************************/
00311 
00312 /*
00313   Function: Delete a file from the namespace and release it's data storage.
00314 
00315   Input:    path      - Is the fully qualified name of the file to be removed.
00316 
00317   Output:   Returns 0 upon success and -errno upon failure.
00318 */
00319 int XrdOssSys::MSS_Unlink(const char *path) {
00320     const char *epname = "MSS_Unlink";
00321 
00322     // Make sure the path is not too long.
00323     //
00324     if (strlen(path) > MAXPATHLEN)
00325        {OssEroute.Emsg(epname, "mss path too long - ", path);
00326         return -ENAMETOOLONG;
00327        }
00328 
00329     // Remove the file in Mass Store System.
00330     //
00331     return MSS_Xeq(0, ENOENT, "rm", path);
00332 }
00333 
00334 /******************************************************************************/
00335 /*                                r e n a m e                                 */
00336 /******************************************************************************/
00337 
00338 /*
00339   Function: Renames a file with name 'old_name' to 'new_name'.
00340 
00341   Input:    old_name  - Is the fully qualified name of the file to be renamed.
00342             new_name  - Is the fully qualified name that the file is to have.
00343 
00344   Output:   Returns 0 upon success and -errno upon failure.
00345 */
00346 int XrdOssSys::MSS_Rename(const char *oldname, const char *newname) {
00347     const char *epname = "MSS_Rename";
00348 
00349     // Make sure the path is not too long.
00350     //
00351     if (strlen(oldname) > MAXPATHLEN
00352     ||  strlen(newname) > MAXPATHLEN)
00353        {OssEroute.Emsg(epname,"mss path too long - ", oldname, newname);
00354         return -ENAMETOOLONG;
00355        }
00356 
00357     // Rename the file in Mass Store System
00358     //
00359     return MSS_Xeq(0, 0, "mv", oldname, newname);
00360 }
00361 
00362 /******************************************************************************/
00363 /*                     P R I V A T E    S E C T I O N                         */
00364 /******************************************************************************/
00365 /******************************************************************************/
00366 /*                               M S S _ X e q                                */
00367 /******************************************************************************/
00368 
00369 int XrdOssSys::MSS_Xeq(XrdOucStream **xfd, int okerr, 
00370                        const char *cmd, const char *arg1, const char *arg2)
00371 {
00372     EPNAME("MSS_Xeq")
00373     static int NoResp = 0;
00374     char *resp;
00375     int retc;
00376     XrdOucStream *sp;
00377 
00378 // If we have no gateway command, return an error
00379 //
00380    if (!RSSProg) return -XRDOSS_E8013;
00381 
00382 // Allocate a stream for this command
00383 //
00384    if (!(sp = new XrdOucStream(&OssEroute)))
00385       return OssEroute.Emsg("MSS_Xeq",-ENOMEM,"create stream for",RSSCmd);
00386 
00387 // Run the command
00388 //
00389    DEBUG("Invoking '" <<RSSCmd <<' ' <<cmd <<' ' <<(arg1 ? arg1 : "")
00390                       <<' ' <<(arg2 ? arg2 : ""));
00391    if ((retc = RSSProg->Run(sp, cmd, arg1, arg2)))
00392       {delete sp; return NegVal(retc);}
00393 
00394 // Wait for data to appear. We do this to avoid hanging up and chewing through
00395 // all of the threads while clients retry the requests with a new connection.
00396 //
00397    if ((retc = sp->Wait4Data(RSSTout)))
00398       {if (retc < 0)
00399           {if (!(0xff & NoResp++))
00400                OssEroute.Emsg("MSS_Xeq", -ETIMEDOUT, "execute", cmd);
00401            retc = ETIMEDOUT;
00402           }
00403        delete sp; return NegVal(retc);
00404       }
00405 
00406 // Read back the first record. The first records must be the return code
00407 // from the command followed by any output. Make sure that this is the case.
00408 //
00409    if ( !(resp = sp->GetLine()) ) retc = XRDOSS_E8023;
00410       else
00411       {DEBUG("received '" <<resp <<"'");
00412        if (sscanf(resp, "%d", &retc) <= 0) retc = XRDOSS_E8024;
00413       }
00414    if (retc)
00415       {if (retc != -okerr)
00416           OssEroute.Emsg("MSS_Xeq", NegVal(retc), "execute", cmd);
00417        delete sp;
00418        return NegVal(retc);
00419       }
00420 
00421 // If the caller wants the stream pointer; return it. Otherwise close it.
00422 //
00423    if (xfd) *xfd = sp;
00424       else delete sp;
00425    return 0;
00426 }

Generated on Tue Jul 5 14:46:47 2011 for ROOT_528-00b_version by  doxygen 1.5.1