XRootD
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"
45 #include "XrdSys/XrdSysPlatform.hh"
46 
47 /******************************************************************************/
48 /* E x t e r n a l O b j e c t s */
49 /******************************************************************************/
50 
51 extern XrdSysError OssEroute;
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 
82 namespace
83 {
84 class 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 
96 int 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 
127 int 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 
152 int 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 
173 int 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 //
188  if (opts & At_dInfo) XrdOssCache::DevInfo(buf);
189 
190 // All done
191 //
192  return 0;
193 }
194 
195 /******************************************************************************/
196 /* U n l i n k */
197 /******************************************************************************/
198 
199 int 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 }
#define BOILER_PLATE(dfObj, fd)
Definition: XrdOssAt.cc:66
XrdSysError OssEroute
#define OPEN_AT(dst, dfd, p, f)
Definition: XrdOssAt.cc:76
int stat(const char *path, struct stat *buf)
int unlink(const char *path)
#define close(a)
Definition: XrdPosix.hh:43
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:117
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)
Definition: XrdOssCache.cc:583
static void Adjust(dev_t devid, off_t size)
Definition: XrdOssCache.cc:397
virtual const char * getTID()
Definition: XrdOss.hh:434
static void Trim2Base(char *eP)
Definition: XrdOssPath.cc:304
static const char xChar
Definition: XrdOssPath.hh:47
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95