XRootD
Xrdadler32.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d a d l e r 3 2 . c c */
4 /* */
5 /* (c) 2009 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Wei Yang for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 /************************************************************************/
32 /* Calculating Adler32 checksum of a local unix file (including stdin) */
33 /* and file on a remote xrootd data server. Support using XROOTD_VMP. */
34 /************************************************************************/
35 
36 #define _FILE_OFFSET_BITS 64
37 
38 #include <cstdio>
39 #include <cstdlib>
40 #include <cstring>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <fcntl.h>
45 #include <cerrno>
46 #if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
47  #include <sys/xattr.h>
48 #endif
49 #include <zlib.h>
50 
53 #include "XrdOuc/XrdOucString.hh"
54 
55 #include "XrdCks/XrdCksXAttr.hh"
56 #include "XrdOuc/XrdOucXAttr.hh"
57 
58 void fSetXattrAdler32(const char *path, int fd, const char* attr, char *value)
59 {
61  struct stat st;
62 
63  if (fstat(fd, &st) || strlen(value) != 8) return;
64 
65  if (!xCS.Attr.Cks.Set("adler32") || !xCS.Attr.Cks.Set(value,8)) return;
66 
67  xCS.Attr.Cks.fmTime = static_cast<long long>(st.st_mtime);
68  xCS.Attr.Cks.csTime = static_cast<int>(time(0) - st.st_mtime);
69 
70  xCS.Set("", fd);
71 
72 // Remove any old attribute at this point
73 //
74 #if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
75  fremovexattr(fd, attr);
76 #elif defined(__solaris__)
77  int attrfd;
78  attrfd = openat(fd, attr, O_XATTR|O_RDONLY);
79  if (attrfd >= 0)
80  {unlinkat(attrfd, attr, 0); close(attrfd);}
81 #endif
82 }
83 
84 int fGetXattrAdler32(int fd, const char* attr, char *value)
85 {
86  struct stat st;
87  char mtime[12], attr_val[25], *p;
88  int rc;
89 
90  if (fstat(fd, &st)) return 0;
91  sprintf(mtime, "%lld", (long long) st.st_mtime);
92 
93 #if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
94  rc = fgetxattr(fd, attr, attr_val, 25);
95 #elif defined(__solaris__)
96  int attrfd;
97  attrfd = openat(fd, attr, O_XATTR|O_RDONLY);
98  if (attrfd < 0) return(0);
99 
100  rc = read(attrfd, attr_val, 25);
101  close(attrfd);
102 #else
103  return(0);
104 #endif
105 
106  if (rc == -1 || attr_val[8] != ':') return(0);
107  attr_val[8] = '\0';
108  attr_val[rc] = '\0';
109  p = attr_val + 9;
110 
111  if (strcmp(p, mtime)) return(0);
112 
113  strcpy(value, attr_val);
114 
115  return(strlen(value));
116 }
117 
118 int fGetXattrAdler32(const char *path, int fd, const char* attr, char *value)
119 {
121  struct stat st;
122 
123  if (!xCS.Attr.Cks.Set("adler32") || xCS.Get(path, fd) <= 0
124  || strcmp(xCS.Attr.Cks.Name, "adler32"))
125  {int rc = fGetXattrAdler32(fd, attr, value);
126  if (rc == 8) fSetXattrAdler32(path, fd, attr, value);
127  return rc;
128  }
129 
130  if (fstat(fd, &st)
131  || xCS.Attr.Cks.fmTime != static_cast<long long>(st.st_mtime)) return 0;
132 
133  xCS.Attr.Cks.Get(value, 9);
134  return 8;
135 }
136 
137 /* the rooturl should point to the data server, not redirector */
138 char getchksum(const char *rooturl, char *chksum)
139 {
140  char csBuff[256];
141  int csLen;
142 
143 // Obtain the checksum (this is the default checksum)
144 //
145  csLen = XrdPosixXrootd::Getxattr(rooturl, "xroot.cksum",
146  csBuff, sizeof(csBuff));
147  if (csLen < 0) return -1;
148  if (csLen == 0) return 0; // Server doesn't have the checksum
149 
150 // Verify that the checksum returned is "adler32"
151 //
152  if (strncmp("adler32 ", csBuff, 8)) return 0;
153 
154 // Return the checksum value (this is really bad code)
155 //
156  strcpy(chksum, csBuff+8);
157  return strlen(csBuff+8);
158 }
159 
160 #define N 1024*1024 /* reading block size */
161 
162 int main(int argc, char *argv[])
163 {
164  char path[2048], chksum[128], buf[N], adler_str[9];
165  const char attr[] = "user.checksum.adler32";
166  struct stat stbuf;
167  int fd, len, rc;
168  uLong adler;
169  adler = adler32(0L, Z_NULL, 0);
170 
171  if (argc == 2 && ! strcmp(argv[1], "-h"))
172  {
173  printf("Usage: %s file. Calculating adler32 checksum of a given file.\n", argv[0]);
174  printf("A file can be local file, stdin (if omitted), or root URL (including via XROOTD_VMP)\n");
175  return 0;
176  }
177 
178  path[0] = '\0';
179  if (argc > 1) /* trying to convert to root URL */
180  {
181  if (!strncmp(argv[1], "root://", 7))
182  strcpy(path, argv[1]);
183  else {XrdPosixXrootPath xrdPath;
184  xrdPath.URL(argv[1], path, sizeof(path));
185  }
186  }
187  if (argc == 1 || path[0] == '\0')
188  { /* this is a local file */
189  if (argc > 1)
190  {
191  strcpy(path, argv[1]);
192  if ((fd = open(path, O_RDONLY)) < 0 || fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode))
193  {
194  if (fd != -1)
195  close(fd);
196  printf("Error opening %s: %s\n", path, strerror(errno));
197  return 1;
198  }
199  else /* see if the adler32 is saved in attribute already */
200  if (fGetXattrAdler32(path, fd, attr, adler_str) == 8)
201  {
202  printf("%s %s\n", adler_str, path);
203  return 0;
204  }
205  }
206  else
207  {
208  fd = STDIN_FILENO;
209  strcpy(path, "-");
210  }
211  while ( (len = read(fd, buf, N)) > 0 )
212  adler = adler32(adler, (const Bytef*)buf, len);
213 
214  if (fd != STDIN_FILENO)
215  { /* try saving adler32 to attribute before close() */
216  sprintf(adler_str, "%08lx", adler);
217  fSetXattrAdler32(path, fd, attr, adler_str);
218  close(fd);
219  }
220  printf("%08lx %s\n", adler, path);
221  return 0;
222  }
223  else
224  { /* this is a Xrootd file */
225  if (getchksum(path, chksum) > 0)
226  { /* server implements checksum */
227  printf("%s %s\n", chksum, argv[1]);
228  return (strcmp(chksum, "Error_accessing:") ? 0 : 1);
229  }
230  else
231  { /* need to read the file and calculate */
232  XrdPosixXrootd myPFS(-8, 8, 1);
233  rc = XrdPosixXrootd::Stat(path, &stbuf);
234  if (rc != 0 || ! S_ISREG(stbuf.st_mode) ||
235  (fd = XrdPosixXrootd::Open(path, O_RDONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
236  {
237  printf("Error_accessing: %s\n", argv[1]);
238  return 1;
239  }
241  off_t totbytes = 0;
242  while ( totbytes < stbuf.st_size && (len = XrdPosixXrootd::Read(fd, buf, N)) > 0 )
243  {
244  adler = adler32(adler,
245  (const Bytef*)buf,
246  (len < (stbuf.st_size - totbytes)? len : stbuf.st_size - totbytes ));
247  totbytes += len;
248  }
249 
251  printf("%08lx %s\n", adler, argv[1]);
252  return 0;
253  }
254  }
255 }
XrdOucXAttr< XrdCksXAttr > xCS
Definition: XrdCks.cc:48
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fstat(int fildes, struct stat *buf)
ssize_t read(int fildes, void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
#define N
Definition: Xrdadler32.cc:160
int main(int argc, char *argv[])
Definition: Xrdadler32.cc:162
void fSetXattrAdler32(const char *path, int fd, const char *attr, char *value)
Definition: Xrdadler32.cc:58
int fGetXattrAdler32(int fd, const char *attr, char *value)
Definition: Xrdadler32.cc:84
char getchksum(const char *rooturl, char *chksum)
Definition: Xrdadler32.cc:138
char * URL(const char *path, char *buff, int blen)
POSIX interface to XRootD with some extensions, as noted.
static int Stat(const char *path, struct stat *buf)
Stat() conforms to POSIX.1-2001 stat()
static int Close(int fildes)
Close() conforms to POSIX.1-2001 close()
static long long Getxattr(const char *path, const char *name, void *value, unsigned long long size)
static ssize_t Read(int fildes, void *buf, size_t nbyte)
Read() conforms to POSIX.1-2001 read()
static int Open(const char *path, int oflag, mode_t mode=0, XrdPosixCallBack *cbP=0)