Xrdadler32.cc

Go to the documentation of this file.
00001 /************************************************************************/
00002 /* Xrdadler32.cc                                                        */
00003 /*                                                                      */
00004 /* Auther: Wei Yang                                                     */
00005 /* SLAC National Accelerator Laboratory / Stanford University, 2009     */
00006 /*                                                                      */
00007 /* Calculating Adler32 checksum of a local unix file (including stdin)  */
00008 /* and file on a remote xrootd data server. Support using XROOTD_VMP.   */
00009 /************************************************************************/
00010 
00011 //   $Id: Xrdadler32.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 const char *Xrdadler32CVSID = "$Id: Xrdadler32.cc 35287 2010-09-14 21:19:35Z ganis $";
00014 
00015 #define _FILE_OFFSET_BITS 64
00016 
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <unistd.h>
00023 #include <fcntl.h>
00024 #include <errno.h>
00025 #ifdef __linux__
00026   #include <sys/xattr.h>
00027 #endif
00028 #include <zlib.h>
00029 
00030 #include "XrdPosix/XrdPosixExtern.hh"
00031 #include "XrdPosix/XrdPosixXrootd.hh"
00032 #include "XrdClient/XrdClientUrlInfo.hh"
00033 #include "XrdClient/XrdClientConst.hh"
00034 #include "XrdClient/XrdClient.hh"
00035 #include "XrdClient/XrdClientEnv.hh"
00036 #include "XrdClient/XrdClientAdmin.hh"
00037 #include "XrdOuc/XrdOucString.hh"
00038 
00039 void fSetXattrAdler32(int fd, const char* attr, const char *value)
00040 {
00041     struct stat st;
00042     char mtime[12], attr_val[25];
00043     int rc;
00044     
00045     rc = fstat(fd, &st);
00046     if (rc < 0 || strlen(value) != 8) 
00047         return; 
00048     else
00049         sprintf(mtime, "%ld", st.st_mtime);
00050 
00051     strcpy(attr_val, value);
00052     strcat(attr_val, ":"); 
00053     strcat(attr_val, mtime);
00054 
00055 #if defined(__linux__)
00056     rc = fsetxattr(fd, attr, attr_val, strlen(attr_val), 0x0);
00057 #elif defined(__solaris__)
00058     int attrfd;
00059     attrfd = openat(fd, attr, O_XATTR|O_CREAT|O_TRUNC|O_WRONLY); 
00060     if (attrfd < 0) return;
00061 
00062     rc = write(attrfd, attr_val, strlen(attr_val));
00063 /*
00064    Solaris extended attributes are files in orthogonal namespace.
00065    Their permission wont' change according to real files.
00066  */
00067     fchmod(attrfd, S_IRWXU|S_IRGRP|S_IROTH);
00068     close(attrfd);
00069 #endif
00070     return;
00071 }
00072 
00073 int fGetXattrAdler32(int fd, const char* attr, char *value)
00074 {
00075     struct stat st;
00076     char mtime[12], attr_val[25], *p;
00077     int rc;
00078 
00079     rc = fstat(fd, &st);
00080     if (rc < 0)
00081         return(0);
00082     else
00083         sprintf(mtime, "%ld", st.st_mtime);
00084 
00085 
00086 #if defined(__linux__)
00087     rc = fgetxattr(fd, attr, attr_val, 25);
00088 #elif defined(__solaris__)
00089     int attrfd;
00090     attrfd = openat(fd, attr, O_XATTR|O_RDONLY);
00091     if (attrfd < 0) return(0);
00092 
00093     rc = read(attrfd, attr_val, 25);
00094     close(attrfd);
00095 #else
00096     return(0);
00097 #endif
00098 
00099     if (rc == -1 || attr_val[8] != ':') return(0);
00100     attr_val[8] = '\0';
00101     attr_val[rc] = '\0';
00102     p = attr_val + 9;
00103      
00104     if (strcmp(p, mtime)) return(0);
00105 
00106     strcpy(value, attr_val);
00107     return(strlen(value));
00108 }
00109 
00110 /* get the actual root url pointing to the data server */
00111 char get_current_url(const char *oldurl, char *newurl)
00112 {
00113     bool stat;
00114     long id, flags, modtime;
00115     long long size;
00116     XrdOucString url(oldurl);
00117 
00118     XrdClientAdmin *adm = new XrdClientAdmin(url.c_str());
00119     if (adm->Connect())
00120     {
00121         XrdClientUrlInfo u(url);
00122 
00123         stat = adm->Stat((char *)u.File.c_str(), id, size, flags, modtime);
00124         if (stat && adm->GetCurrentUrl().IsValid())
00125         {
00126             strcpy(newurl, adm->GetCurrentUrl().GetUrl().c_str());
00127             delete adm;
00128             return 1;
00129         }
00130     }
00131     delete adm;
00132     return 0;
00133 }
00134 
00135 /* the rooturl should point to the data server, not redirector */
00136 char getchksum(const char *rooturl, char *chksum) 
00137 {
00138     XrdOucString url(rooturl);
00139     char *sum = 0, *ptb, *pte;
00140     long sumlen; 
00141     int  pte_ptb;
00142 
00143     XrdClientAdmin *adm = new XrdClientAdmin(url.c_str());
00144     if (adm->Connect()) 
00145     {
00146         XrdClientUrlInfo u(url);
00147         sumlen = adm->GetChecksum((kXR_char *)u.File.c_str(), (kXR_char**) &sum);
00148         pte = ptb = sum;
00149         if (sumlen != 0)
00150         {
00151             ptb = strchr(sum, ' ');
00152             ptb++;
00153             pte = strchr(ptb, ' ');
00154             if (pte == NULL) pte = &sum[sumlen];
00155         }
00156         pte_ptb = pte - ptb;
00157         strncpy(chksum, ptb, pte_ptb);
00158         chksum[pte_ptb] = '\0';
00159         free(sum);
00160         delete adm;
00161         return pte_ptb;  /* 0 means sever doesn't implement a checksum */
00162     }
00163     else
00164         return -1;
00165 }
00166 
00167 #define N 64*1024  /* reading block size */
00168 
00169 int main(int argc, char *argv[])
00170 {
00171     char path[2048], chksum[128], buf[N], adler_str[9];
00172     const char attr[] = "user.checksum.adler32";
00173     struct stat stbuf;
00174     int fd, len, rc;
00175     uLong adler;
00176     adler = adler32(0L, Z_NULL, 0);
00177 
00178     if (argc == 2 && ! strcmp(argv[1], "-h"))
00179     {
00180         printf("Usage: %s file. Calculating adler32 checksum of a given file.\n", argv[0]);
00181         printf("A file can be local file, stdin (if omitted), or root URL (including via XROOTD_VMP)\n");
00182         return 0;
00183     }
00184 
00185     path[0] = '\0';
00186     if (argc > 1)  /* trying to convert to root URL */
00187     {
00188         if (!strncmp(argv[1], "root://", 7))
00189             strcpy(path, argv[1]);
00190         else  
00191             XrdPosix_URL(argv[1], path, sizeof(path));
00192     }
00193     if (argc == 1 || path[0] == '\0')
00194     {                        /* this is a local file */
00195         if (argc > 1) 
00196         {
00197             strcpy(path, argv[1]);
00198             rc = stat(path, &stbuf);        
00199             if (rc != 0 || ! S_ISREG(stbuf.st_mode) ||
00200                 (fd = open(path,O_RDONLY)) < 0) 
00201             {
00202                 printf("Error_accessing %s\n", path);
00203                 return 1;
00204             }
00205             else  /* see if the adler32 is saved in attribute already */
00206                 if (fGetXattrAdler32(fd, attr, adler_str) == 8)
00207                 {
00208                     printf("%s %s\n", adler_str, path);
00209                     return 0;
00210                 }
00211         }
00212         else 
00213         {
00214             fd = STDIN_FILENO;
00215             strcpy(path, "-");
00216         }
00217         while ( (len = read(fd, buf, N)) > 0 )
00218             adler = adler32(adler, (const Bytef*)buf, len);
00219 
00220         if (fd != STDIN_FILENO) 
00221         {   /* try saving adler32 to attribute before close() */
00222             sprintf(adler_str, "%08lx", adler);
00223             fSetXattrAdler32(fd, attr, adler_str);
00224             close(fd);
00225         }
00226         printf("%08lx %s\n", adler, path);
00227         return 0;
00228     }
00229     else
00230     {                       /* this is a Xrootd file */
00231         EnvPutInt(NAME_DEBUG, -1);
00232         if (!get_current_url(path, path))
00233         {
00234             printf("Error_accessing: %s\n", argv[1]);
00235             return 1;
00236         }
00237 
00238         if (getchksum(path, chksum) > 0) 
00239         {                   /* server implements checksum */
00240              printf("%s %s\n", chksum, argv[1]);
00241              return (strcmp(chksum, "Error_accessing:") ? 0 : 1);
00242         }
00243         else
00244         {                   /* need to read the file and calculate */
00245             EnvPutInt(NAME_READAHEADSIZE, N);
00246             EnvPutInt(NAME_READCACHESIZE, 2*N);
00247             rc = XrdPosixXrootd::Stat(path, &stbuf);
00248             if (rc != 0 || ! S_ISREG(stbuf.st_mode) ||
00249                 (fd = XrdPosixXrootd::Open(path, O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
00250             {
00251                 printf("Error_accessing: %s\n", argv[1]);
00252                 return 1;
00253             }
00254             while ( (len = XrdPosixXrootd::Read(fd, buf, N)) > 0 )
00255                 adler = adler32(adler, (const Bytef*)buf, len);
00256 
00257             XrdPosixXrootd::Close(fd);
00258             printf("%08lx %s\n", adler, argv[1]);
00259             return 0;
00260         }
00261     }
00262 }

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