XRootD
Loading...
Searching...
No Matches
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
54
55#include "XrdCks/XrdCksXAttr.hh"
56#include "XrdOuc/XrdOucXAttr.hh"
57
58void 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
84int 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
118int 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 */
138char 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
162int 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
#define close(a)
Definition XrdPosix.hh:48
#define fstat(a, b)
Definition XrdPosix.hh:62
#define open
Definition XrdPosix.hh:76
#define stat(a, b)
Definition XrdPosix.hh:101
#define read(a, b, c)
Definition XrdPosix.hh:82
#define N
int main(int argc, char *argv[])
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)
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)