XRootD
Loading...
Searching...
No Matches
XrdOssArcZipFile.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O s s A r c Z i p F i l e . h h */
4/* */
5/* (c) 2024 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky 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#include <errno.h>
32#include <fcntl.h>
33#include <string.h>
34#include <unistd.h>
35#include <sys/stat.h>
36
37#include <zip.h>
38
39#include "XrdOss/XrdOss.hh"
41#include "XrdOuc/XrdOucEnv.hh"
43#include "XrdSys/XrdSysError.hh"
44#include "XrdSys/XrdSysFD.hh"
45
46/******************************************************************************/
47/* G l o b a l O b j e c t s */
48/******************************************************************************/
49
50namespace XrdOssArcGlobals
51{
52extern XrdSysError Elog;
53}
54using namespace XrdOssArcGlobals;
55
56/******************************************************************************/
57/* C o n s t r u c t o r */
58/******************************************************************************/
59
60XrdOssArcZipFile::XrdOssArcZipFile(const char* path, int &rc)
61{
62 XrdOucEnv zipEnv;
63 int zFD, zrc;
64
65// Try to open the file. We only support read mode.
66//
67 if ((zFD = XrdSysFD_Open(path, O_RDONLY)) < 0)
68 {rc = -errno;
69 return;
70 }
71
72// Get the stat information for the archive now using the retrned FD as
73// as attaching the FD to a zipfile "destroys" the original FD.
74//
75 if (fstat(zFD, &zFStat)) memset(&zFStat, 0, sizeof(zFStat));
76
77// Record path
78//
79 zPath = strdup(path);
80
81// Convert open to archive open
82//
83 if ((zFile = zip_fdopen(zFD, ZIP_CHECKCONS, &zrc)) == 0)
84 {rc = zip2syserr("fdopen", zrc);
85 close(zFD);
86 return;
87 }
88}
89
90/******************************************************************************/
91/* D e s t r u c t o r */
92/******************************************************************************/
93
95{
96// If we have an open subfile, close it
97//
98 if (zSubFile) Close();
99
100// Close the archive itself
101//
102 if (zFile)
103 {if (zip_close(zFile))
104 {zipEmsg("close", zip_get_error(zFile));
105 zip_discard(zFile);
106 }
107 zFile = 0;
108 }
109
110// Free up any storage
111//
112 if (zPath) free(zPath);
113}
114
115/******************************************************************************/
116/* C l o s e */
117/******************************************************************************/
118
120{
121 int zrc = 0;
122
123// Close the member subfile if it is open
124//
125 if (zSubFile)
126 {if ((zrc = zip_fclose(zSubFile))) zrc = zip2syserr("close member", zrc);
127 zSubFile = 0;
128 }
129
130// Remove all vestigaes of this subfile
131//
132 if (zMember) {free(zMember); zMember = 0;}
133
134// All done
135//
136 return zrc;
137}
138
139/******************************************************************************/
140/* O p e n */
141/******************************************************************************/
142
143int XrdOssArcZipFile::Open(const char* member)
144{
145 int rc;
146
147// Make sure we have an open archive here
148//
149 if (zFile == 0) return -EBADF;
150
151// If an archive member is alreaddy open then close it
152//
153 if (zSubFile)
154 {if ((rc = zip_fclose(zSubFile))) zip2syserr("close", rc, true);
155 free(zMember);
156 zMember = 0;
157 zSubFile = 0;
158 }
159
160// Set member name we are handling
161//
162 if (zMember) free(zMember);
163 zMember = strdup(member);
164
165// Open the archive member
166//
167 zSubFile = zip_fopen(zFile, zMember, 0);
168 if (zSubFile == 0) return zip2syserr("open", zip_get_error(zFile));
169
170// We should check if this is a compressed archive as ther can onl be read
171// sequentially. However, that is not supported until v 10.1 and the current
172// rpms available at 1.7. So, we punt on this and assume it not compressed and
173// is seekable. Note that compressed files are not seekable.
174//
175// zSeek = zip_file_is_seekable(zSubFile) == 1;
176 zSeek = true;
177 zOffset = 0;
178
179// All done
180//
181 return 0;
182}
183
184/******************************************************************************/
185/* R e a d */
186/******************************************************************************/
187
188ssize_t XrdOssArcZipFile::Read(void *buff, off_t offset, size_t blen)
189{
190// Make sure this file is actually open
191//
192 if (zSubFile == 0) return -EBADF;
193 if (!blen) return 0;
194
195// If this file does not support seeks, return a seek error if a seek wanted
196//
197 if (offset != zOffset)
198 {if (!zSeek) return -ESPIPE;
199 if (zip_fseek(zSubFile, offset, SEEK_SET))
200 return zip2syserr("seek into", zip_file_get_error(zSubFile));
201 zEOF = false;
202 }
203
204// Check if we have reached EOF
205//
206 if (zEOF) return 0;
207
208// Perform the read
209//
210 zip_int64_t ret = zip_fread(zSubFile, buff, blen);
211 if (ret < 0)
212 return zip2syserr("read", zip_file_get_error(zSubFile));
213
214// Update offset and check for EOF
215//
216 zOffset += ret;
217 if (ret < (zip_int64_t)blen) zEOF = true;
218 return ret;
219}
220
221/******************************************************************************/
222/* S t a t */
223/******************************************************************************/
224
226{
227 zip_stat_t zStat;
228
229// Make sure this file is actually open
230//
231 if (zSubFile == 0) return -EBADF;
232
233// Iniialize the stat buffer
234//
235 memcpy(&buf, &zFStat, sizeof(struct stat));
236
237// Clear the stat structures
238//
239 zip_stat_init(&zStat);
240
241// Get information
242//
243 if (zip_stat(zFile, zMember, 0, &zStat) < 0)
244 return zip2syserr("stat", zip_get_error(zFile));
245
246// Copy the relevant information
247//
248 if (zStat.valid & ZIP_STAT_INDEX) buf.st_ino = zStat.index;
249 if (zStat.valid & ZIP_STAT_SIZE) buf.st_size = zStat.size;
250
251// All done
252//
253 return 0;
254}
255
256/******************************************************************************/
257
258int XrdOssArcZipFile::Stat(const char* mName, struct stat& buf)
259{
260 zip_stat_t zStat;
261
262// Iniialize the stat buffer
263//
264 memcpy(&buf, &zFStat, sizeof(struct stat));
265
266// Clear the stat structures
267//
268 zip_stat_init(&zStat);
269
270// Get information
271//
272 if (zip_stat(zFile, mName, 0, &zStat) < 0)
273 return zip2syserr("stat", zip_get_error(zFile));
274
275// Copy the relevant information
276//
277 if (zStat.valid & ZIP_STAT_INDEX) buf.st_ino = zStat.index;
278 if (zStat.valid & ZIP_STAT_SIZE) buf.st_size = zStat.size;
279
280// All done
281//
282 return 0;
283}
284
285/******************************************************************************/
286/* z i p E m s g */
287/******************************************************************************/
288
289void XrdOssArcZipFile::zipEmsg(const char *what, zip_error_t* zerr)
290{
291 XrdOucString target(zPath, 280);
292
293// Create target name
294//
295 target += '[';
296 if (zMember) target += zMember;
297 target += "];";
298
299// Create starting error message
300//
301 char eText[80];
302 snprintf(eText, sizeof(eText), "unable to %s", what);
303
304// Issue message
305//
306 Elog.Emsg("ZipFile", eText, target.c_str(), zip_error_strerror(zerr));
307}
308
309/******************************************************************************/
310/* Private: z i p 2 s y s e r r */
311/******************************************************************************/
312
313int XrdOssArcZipFile::zip2syserr(const char *what, zip_error_t* zerr, bool msg)
314{
315 int retc = zip_error_code_zip(zerr);
316 if (retc != ZIP_ER_OK)
317 {switch(retc)
318 {case ZIP_ER_CRC: retc = EILSEQ; break;
319 case ZIP_ER_EXISTS: retc = EEXIST; break;
320 case ZIP_ER_INCONS: retc = ENOEXEC; break;
321 case ZIP_ER_INUSE: retc = EBUSY; break;
322 case ZIP_ER_INVAL: retc = EINVAL; break;
323 case ZIP_ER_MEMORY: retc = ENOMEM; break;
324 case ZIP_ER_NOENT: retc = ENOENT; break;
325 case ZIP_ER_NOZIP: retc = ENOTBLK; break;
326 case ZIP_ER_OPNOTSUPP: retc = EOPNOTSUPP; break;
327 case ZIP_ER_RDONLY: retc = EROFS; break;
328 case ZIP_ER_READ: retc = EIO; break;
329 case ZIP_ER_SEEK: retc = ESPIPE; break;
330 case ZIP_ER_WRITE: retc = EIO; break;
331 default: retc = EDOM; break;
332 }
333 } else {
334 retc = zip_error_code_system(zerr);
335 if (retc == 0) retc = ENOMSG;
336 else if (retc < 0) retc = -retc;
337 }
338 if (msg) zipEmsg(what, zerr);
339 zip_error_fini(zerr);
340 return -retc;
341}
342
343int XrdOssArcZipFile::zip2syserr(const char *what, int zrc, bool msg)
344{
345 zip_error_t zerr;
346 zip_error_init_with_code(&zerr, zrc);
347 return zip2syserr(what, &zerr, msg);
348}
zip_error zip_error_t
#define close(a)
Definition XrdPosix.hh:48
#define fstat(a, b)
Definition XrdPosix.hh:62
#define stat(a, b)
Definition XrdPosix.hh:101
int Stat(struct stat &buf)
XrdOssArcZipFile(const char *path, int &rc)
ssize_t Read(void *buff, off_t offset, size_t blen)
int Open(const char *member)
XrdSysError Elog(0, "OssArc_")