XRootD
Loading...
Searching...
No Matches
XrdOssAt.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O s s A t . c c */
4/* */
5/* (c) 2020 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 <cerrno>
32#include <fcntl.h>
33#include <string>
34#include <sys/param.h>
35#include <sys/stat.h>
36
37#include "XrdOss/XrdOss.hh"
38#include "XrdOss/XrdOssApi.hh"
39#include "XrdOss/XrdOssAt.hh"
40#include "XrdOss/XrdOssCache.hh"
41#include "XrdOss/XrdOssError.hh"
42#include "XrdOss/XrdOssPath.hh"
43#include "XrdSys/XrdSysError.hh"
44#include "XrdSys/XrdSysFD.hh"
46
47/******************************************************************************/
48/* E x t e r n a l O b j e c t s */
49/******************************************************************************/
50
52
53/******************************************************************************/
54/* L o c a l D e f i n e s */
55/******************************************************************************/
56
57// Common prologue fo each public method
58//
59#ifdef HAVE_FSTATAT
60#define BOILER_PLATE(fd, dfObj) \
61 {if (!(dfObj.DFType() & XrdOssDF::DF_isDir)) return -ENOTDIR;\
62 if (!path || *path == '/') return -XRDOSS_E8027;\
63 if ((fd = dfObj.getFD()) < 0) return -XRDOSS_E8002;\
64 }
65#else
66#define BOILER_PLATE(dfObj,fd) return -ENOTSUP;
67#endif
68
69// Open the target
70//
71#ifdef O_CLOEXEC
72#define OPEN_AT(dst, dfd, p, f)\
73 dst = openat(dfd, p, f|O_CLOEXEC);\
74 if (dst < 0) return -errno;
75#else
76#define OPEN_AT(dst, dfd, p, f)\
77 dst = openat(dfd, p, f); \
78 if (dst >= 0) fcntl(dst, F_SETFD, FD_CLOEXEC);\
79 else return -errno
80#endif
81
82namespace
83{
84class openHelper
85 {public:
86 int FD;
87 openHelper() : FD(-1) {}
88 ~openHelper() {if (FD >= 0) close(FD);}
89 };
90}
91
92/******************************************************************************/
93/* O p e n d i r */
94/******************************************************************************/
95
96int XrdOssAt::Opendir(XrdOssDF &atDir, const char *path, XrdOucEnv &env,
97 XrdOssDF *&ossDF)
98{
99 openHelper hOpen;
100 DIR *dirP;
101 int dirFD;
102
103// Standard boilerplate
104//
105 BOILER_PLATE(dirFD, atDir);
106
107// Open the target
108//
109 OPEN_AT(hOpen.FD, dirFD, path, O_RDONLY);
110
111// Create a new dir entry from this FD
112//
113 dirP = fdopendir(hOpen.FD);
114 if (!dirP) return (errno ? -errno : -ENOMSG);
115
116// Finally return a new directory object
117//
118 ossDF = new XrdOssDir(atDir.getTID(), dirP);
119 hOpen.FD = -1;
120 return 0;
121}
122
123/******************************************************************************/
124/* O p e n R O */
125/******************************************************************************/
126
127int XrdOssAt::OpenRO(XrdOssDF &atDir, const char *path, XrdOucEnv &env,
128 XrdOssDF *&ossDF)
129{
130 openHelper hOpen;
131 int dirFD;
132
133// Standard boilerplate
134//
135 BOILER_PLATE(dirFD, atDir);
136
137// Open the target
138//
139 OPEN_AT(hOpen.FD, dirFD, path, O_RDONLY);
140
141// Return a new file object
142//
143 ossDF = new XrdOssFile(atDir.getTID(), hOpen.FD);
144 hOpen.FD = -1;
145 return 0;
146}
147
148/******************************************************************************/
149/* R e m d i r */
150/******************************************************************************/
151
152int XrdOssAt::Remdir(XrdOssDF &atDir, const char *path)
153{
154 int dirFD;
155
156// Standard boilerplate
157//
158 BOILER_PLATE(dirFD, atDir);
159
160// Effect the removal
161//
162 if (unlinkat(dirFD, path, AT_REMOVEDIR)) return -errno;
163
164// All done
165//
166 return 0;
167}
168
169/******************************************************************************/
170/* S t a t */
171/******************************************************************************/
172
173int XrdOssAt::Stat(XrdOssDF &atDir, const char *path, struct stat &buf,
174 int opts)
175{
176 int dirFD;
177
178// Standard boilerplate
179//
180 BOILER_PLATE(dirFD, atDir);
181
182// Do the stat call
183//
184 if (fstatat(dirFD, path, &buf, 0)) return -errno;
185
186// Check if we need to provide dev info
187//
189
190// All done
191//
192 return 0;
193}
194
195/******************************************************************************/
196/* U n l i n k */
197/******************************************************************************/
198
199int XrdOssAt::Unlink(XrdOssDF &atDir, const char *path)
200{
201 struct stat Stat;
202 int dirFD;
203
204// Standard boilerplate
205//
206 BOILER_PLATE(dirFD, atDir);
207
208// This could be a symlink or an actual file but not a directory.
209//
210 if (fstatat(dirFD, path, &Stat, AT_SYMLINK_NOFOLLOW))
211 return (errno == ENOENT ? 0 : -errno);
212 if ((Stat.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
213
214// If this is not a symlink then we can delete it directly
215//
216 if ((Stat.st_mode & S_IFMT) != S_IFLNK)
217 {if (unlinkat(dirFD, path, 0)) return -errno;
218 if (Stat.st_size)
219 XrdOssCache::Adjust(Stat.st_dev, -Stat.st_size);
220 return 0;
221 }
222
223// Get the target of this link
224//
225 char lnkbuff[MAXPATHLEN+64];
226 int lnklen, retc;
227 if ((lnklen = readlinkat(dirFD, path, lnkbuff, sizeof(lnkbuff)-1)) < 0)
228 return -errno;
229
230// If the underlying file exists, remove it
231//
232 lnkbuff[lnklen] = '\0';
233 if (stat(lnkbuff, &Stat)) Stat.st_size = 0;
234 else if (unlink(lnkbuff) && errno != ENOENT)
235 {retc = -errno;
236 OssEroute.Emsg("Unlink",retc,"unlink symlink target",lnkbuff);
237 return -retc;
238 }
239
240// Adjust the size based on what kind of data cache we are using.
241//
242 if (Stat.st_size)
243 {char *lP = lnkbuff+lnklen-1;
244 if (*lP == XrdOssPath::xChar)
246 XrdOssCache::Adjust(lnkbuff, -Stat.st_size);
247 }
248 else XrdOssCache::Adjust(Stat.st_dev, -Stat.st_size);
249 }
250
251// Effect the removal of the actual symlink
252//
253 if (unlinkat(dirFD, path, 0)) return -errno;
254
255// All done
256//
257 return 0;
258}
XrdSysError OssEroute
#define BOILER_PLATE(dfObj, fd)
Definition XrdOssAt.cc:66
#define OPEN_AT(dst, dfd, p, f)
Definition XrdOssAt.cc:76
#define close(a)
Definition XrdPosix.hh:43
#define unlink(a)
Definition XrdPosix.hh:108
#define stat(a, b)
Definition XrdPosix.hh:96
struct myOpts opts
int OpenRO(XrdOssDF &atDir, const char *path, XrdOucEnv &env, XrdOssDF *&ossDF)
Definition XrdOssAt.cc:127
int Opendir(XrdOssDF &atDir, const char *path, XrdOucEnv &env, XrdOssDF *&ossDF)
Definition XrdOssAt.cc:96
static const int At_dInfo
Definition XrdOssAt.hh:115
int Unlink(XrdOssDF &atDir, const char *path)
Definition XrdOssAt.cc:199
int Stat(XrdOssDF &atDir, const char *path, struct stat &buf, int opts=0)
Definition XrdOssAt.cc:173
int Remdir(XrdOssDF &atDir, const char *path)
Definition XrdOssAt.cc:152
static void DevInfo(struct stat &buf, bool limits=false)
static void Adjust(dev_t devid, off_t size)
virtual const char * getTID()
Definition XrdOss.hh:434
static void Trim2Base(char *eP)
static const char xChar
Definition XrdOssPath.hh:47