XRootD
XrdOssCreate.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s C r e a t e . c c */
4 /* */
5 /* (c) 2003 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 /******************************************************************************/
32 /* i n c l u d e s */
33 /******************************************************************************/
34 
35 #include <unistd.h>
36 #include <cerrno>
37 #include <fcntl.h>
38 #include <strings.h>
39 #include <cstdio>
40 #include <utime.h>
41 #include <sys/file.h>
42 #include <sys/stat.h>
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #if defined(__solaris__) || defined(AIX)
46 #include <sys/vnode.h>
47 #endif
48 
49 #include "XrdFrc/XrdFrcXAttr.hh"
50 #include "XrdOss/XrdOssApi.hh"
51 #include "XrdOss/XrdOssCache.hh"
52 #include "XrdOss/XrdOssConfig.hh"
53 #include "XrdOss/XrdOssCopy.hh"
54 #include "XrdOss/XrdOssError.hh"
55 #include "XrdOss/XrdOssOpaque.hh"
56 #include "XrdOss/XrdOssPath.hh"
57 #include "XrdOss/XrdOssSpace.hh"
58 #include "XrdOss/XrdOssTrace.hh"
59 #include "XrdOuc/XrdOuca2x.hh"
60 #include "XrdOuc/XrdOucEnv.hh"
61 #include "XrdOuc/XrdOucExport.hh"
62 #include "XrdOuc/XrdOucUtils.hh"
63 #include "XrdOuc/XrdOucXAttr.hh"
64 #include "XrdSys/XrdSysError.hh"
65 #include "XrdSys/XrdSysHeaders.hh"
66 #include "XrdSys/XrdSysPlatform.hh"
67 
68 /******************************************************************************/
69 /* E r r o r R o u t i n g O b j e c t */
70 /******************************************************************************/
71 
72 extern XrdSysError OssEroute;
73 
74 extern XrdSysTrace OssTrace;
75 
76 extern XrdOssSys *XrdOssSS;
77 
78 /******************************************************************************/
79 /* L o c a l C l a s s e s */
80 /******************************************************************************/
81 
83  {public:
84  unsigned long long pOpts;
85  const char *Path;
86  const char *LFN;
87  mode_t Amode;
88  int cOpts;
89  XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
90  : Path(path), LFN(lfn), Amode(amode), cOpts(opts) {}
92  };
93 
94 /******************************************************************************/
95 /* c r e a t e */
96 /******************************************************************************/
97 
98 /*
99  Function: Create a file named `path' with 'file_mode' access mode bits set.
100 
101  Input: path - The fully qualified name of the file to create.
102  access_mode - The Posix access mode bits to be assigned to the file.
103  These bits correspond to the standard Unix permission
104  bits (e.g., 744 == "rwxr--r--").
105  env - Environmental information.
106  opts - Set as follows:
107  XRDOSS_mkpath - create dir path if it does not exist.
108  XRDOSS_new - the file must not already exist.
109  x00000000 - x are standard open flags (<<8)
110 
111  Output: Returns XRDOSS_OK upon success; (-errno) otherwise.
112 */
113 int XrdOssSys::Create(const char *tident, const char *path, mode_t access_mode,
114  XrdOucEnv &env, int Opts)
115 {
116  EPNAME("Create")
117  const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
118  char local_path[MAXPATHLEN+1], *p, pc;
119  local_path[0] = '\0';
120  unsigned long long remotefs;
121  int isLink = 0, Missing = 1, retc = 0, datfd;
122  XrdOssCreateInfo crInfo(local_path, path, access_mode, Opts);
123  struct stat buf;
124 
125 // Get options associated with this path and check if it's r/w
126 //
127  remotefs = Check_RO(Create, crInfo.pOpts, path, "create");
128 
129 // Generate the actual local path for this file.
130 //
131  if ((retc = GenLocalPath(path, local_path))) return retc;
132 
133 // Determine the state of the file. We will need this information as we go on.
134 //
135  if ((Missing = lstat(local_path, &buf))) retc = errno;
136  else {if ((isLink = ((buf.st_mode & S_IFMT) == S_IFLNK)))
137  {if (stat(local_path, &buf))
138  {if (errno != ENOENT) return -errno;
139  OssEroute.Emsg("Create","removing dangling link",local_path);
140  if (unlink(local_path)) retc = errno;
141  Missing = 1; isLink = 0;
142  }
143  }
144  }
145  if (retc && retc != ENOENT) return -retc;
146 
147 // At this point, creation requests may need to be routed via the stagecmd.
148 // This is done if the file/link do not exist. Otherwise, we drop through.
149 //
150  if (StageCreate && Missing)
151  return XrdOssSS->Stage(tident, path, env, Opts>>8,
152  access_mode, crInfo.pOpts);
153 
154 // The file must not exist if it's declared "new". Otherwise, reuse the space.
155 // SetFattr() alaways closes the provided file descriptor!
156 //
157  if (!Missing)
158  {if (Opts & XRDOSS_new) return -EEXIST;
159  if ((buf.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
160  do {datfd = open(local_path, Opts>>8, access_mode);}
161  while(datfd < 0 && errno == EINTR);
162  if (datfd < 0) return -errno;
163  if ((retc = SetFattr(crInfo, datfd, buf.st_mtime))) return retc;
164  if (Opts>>8 & O_TRUNC && buf.st_size)
165  {off_t theSize = buf.st_size;
166  if (isLink) {buf.st_mode = (buf.st_mode & ~S_IFMT) | S_IFLNK;
167  XrdOssCache::Adjust(local_path, -theSize, &buf);
168  }
169  }
170  return 0;
171  }
172 
173 // If the path is to be created, make sure the path exists at this point
174 //
175  if ((Opts & XRDOSS_mkpath) && (p = rindex(local_path, '/')))
176  {p++; pc = *p; *p = '\0';
177  XrdOucUtils::makePath(local_path, AMode);
178  *p = pc;
179  }
180 
181 // If this is a staging filesystem then we have lots more work to do.
182 //
183  if (remotefs)
184  {char remote_path[MAXPATHLEN+1];
185 
186  // Generate the remote path for this file
187  //
188  if ((retc = GenRemotePath(path,remote_path))) return retc;
189 
190  // Create the file in remote system unless not wanted so
191  //
192  if (crInfo.pOpts & XRDEXP_RCREATE)
193  {if ((retc = MSS_Create(remote_path, access_mode, env)) < 0)
194  {DEBUG("rc" <<retc <<" mode=" <<Xrd::oct1 <<access_mode
195  <<" remote path=" <<remote_path);
196  return retc;
197  }
198  } else if (!(crInfo.pOpts & XRDEXP_NOCHECK))
199  {if (!(retc = MSS_Stat(remote_path))) return -EEXIST;
200  else if (retc != -ENOENT) return retc;
201  }
202  }
203 
204 // Created file in the extended cache or the local name space
205 //
206  if (XrdOssCache::fsfirst && !(crInfo.pOpts & XRDEXP_INPLACE))
207  retc = Alloc_Cache(crInfo, env);
208  else retc = Alloc_Local(crInfo, env);
209 
210 // If successful then check if xattrs were actually set
211 //
212  if (retc == XrdOssOK && crInfo.cOpts & XRDOSS_setnoxa)
213  {XrdOucPList *plP = RPList.About(path);
214  if (plP) plP->Set(plP->Flag() | XRDEXP_NOXATTR);
215  }
216 
217 // All done.
218 //
219  return retc;
220 }
221 
222 /******************************************************************************/
223 /* P r i v a t e M e t h o d s */
224 /******************************************************************************/
225 /******************************************************************************/
226 /* A l l o c _ C a c h e */
227 /******************************************************************************/
228 
230 {
231  EPNAME("Alloc_Cache")
232  int datfd, rc;
233  const char *spName;
234  char pbuff[MAXPATHLEN+1], cgbuff[XrdOssSpace::minSNbsz], *tmp;
235  XrdOssCache::allocInfo aInfo(crInfo.Path, pbuff, sizeof(pbuff));
236 
237 // Grab the suggested size from the environment
238 //
239  if ((tmp = env.Get(OSS_ASIZE))
240  && XrdOuca2x::a2sz(OssEroute,"invalid asize",tmp,&aInfo.cgSize,0))
241  return -XRDOSS_E8018;
242 
243 // Determine the space we should use for this allocation
244 //
245  spName = env.Get(OSS_CGROUP);
246  if (!spName || (SPList.NotEmpty() && SPList.Default() == spAssign))
247  {XrdOucPList *pl = SPList.About(crInfo.LFN);
248  if (pl && (!spName || pl->Attr() == spAssign)) spName = pl->Name();
249  }
250 
251 // Get the correct cache group and partition path
252 //
253  if ((aInfo.cgPath=XrdOssCache::Parse(spName,cgbuff,sizeof(cgbuff))))
254  aInfo.cgPlen = strlen(aInfo.cgPath);
255 
256 // Allocate space in the cache.
257 //
258  aInfo.cgName = cgbuff;
259  aInfo.aMode = crInfo.Amode;
260  if ((datfd = XrdOssCache::Alloc(aInfo)) < 0) return datfd;
261 
262 // Set the pfn as the extended attribute if we are in new mode
263 //
264  if (!(crInfo.pOpts & XRDEXP_NOXATTR)
265  && (rc = XrdSysFAttr::Xat->Set(XrdFrcXAttrPfn::Name(), crInfo.Path,
266  strlen(crInfo.Path)+1, pbuff, datfd)))
267  {close(datfd); return rc;}
268 
269 // Set extended attributes for this newly created file if allowed to do so.
270 // SetFattr() alaways closes the provided file descriptor!
271 //
272  if ((rc = SetFattr(crInfo, datfd, 1))) return rc;
273 
274 // Now create a symbolic link to the target
275 //
276  if ((symlink(pbuff, crInfo.Path) && errno != EEXIST)
277  || unlink(crInfo.Path) || symlink(pbuff, crInfo.Path))
278  {rc = -errno; unlink(pbuff);}
279 
280 // All done
281 //
282  DEBUG(aInfo.cgName <<" cache for " <<pbuff);
283  return rc;
284 }
285 
286 /******************************************************************************/
287 /* A l l o c _ L o c a l */
288 /******************************************************************************/
289 
291 {
292  int datfd, rc;
293 
294 // Simply open the file in the local filesystem, creating it if need be.
295 //
296  do {datfd = open(crInfo.Path, O_RDWR|O_CREAT|O_TRUNC, crInfo.Amode);}
297  while(datfd < 0 && errno == EINTR);
298  if (datfd < 0) return -errno;
299 
300 // Set extended attributes for this newly created file if allowed to do so.
301 // SetFattr() alaways closes the provided file descriptor!
302 //
303  if ((rc = SetFattr(crInfo, datfd, 1))) return rc;
304 
305 // All done
306 //
307  return XrdOssOK;
308 }
309 
310 /******************************************************************************/
311 /* S e t F a t t r */
312 /******************************************************************************/
313 
314 int XrdOssSys::SetFattr(XrdOssCreateInfo &crInfo, int fd, time_t mtime)
315 {
316  class fdCloser
317  {public:
318  const char *Path;
319  int theFD;
320  int Done(int rc) {if (rc) unlink(Path); return rc;}
321  fdCloser(const char *pn, int fd) : Path(pn), theFD(fd) {}
322  ~fdCloser() {close(theFD);}
323  } Act(crInfo.Path, fd);
324 
326  int rc;
327 
328 // Check if we need or can record the create time
329 //
330  if (!(XRDEXP_MIGPRG & crInfo.pOpts)
331  || (crInfo.pOpts & XRDEXP_NOXATTR)) return Act.Done(0);
332 
333 // Set copy time
334 //
335  crX.Attr.cpyTime = static_cast<long long>(mtime);
336  rc = crX.Set(crInfo.Path, fd);
337 
338 // Check if extended attribute were set and indicate whether it is supported
339 //
340  if (rc == -ENOTSUP) {rc = 0; crInfo.cOpts |= XRDOSS_setnoxa;}
341  return Act.Done(rc);
342 }
#define tident
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define spAssign
Definition: XrdOssApi.hh:250
#define Check_RO(act, flags, path, opname)
Definition: XrdOssApi.hh:387
XrdSysTrace OssTrace
XrdOssSys * XrdOssSS
Definition: XrdOssApi.cc:77
XrdSysError OssEroute
#define XRDOSS_E8018
Definition: XrdOssError.hh:52
#define OSS_ASIZE
Definition: XrdOssOpaque.hh:37
#define OSS_CGROUP
Definition: XrdOssOpaque.hh:38
#define XrdOssOK
Definition: XrdOss.hh:50
#define XRDOSS_setnoxa
Definition: XrdOss.hh:471
#define XRDOSS_new
Definition: XrdOss.hh:467
#define XRDOSS_mkpath
Definition: XrdOss.hh:466
#define XRDEXP_INPLACE
Definition: XrdOucExport.hh:66
#define XRDEXP_NOCHECK
Definition: XrdOucExport.hh:50
#define XRDEXP_RCREATE
Definition: XrdOucExport.hh:48
#define XRDEXP_NOXATTR
Definition: XrdOucExport.hh:64
#define XRDEXP_MIGPRG
Definition: XrdOucExport.hh:86
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int lstat(const char *path, struct stat *buf)
int unlink(const char *path)
#define close(a)
Definition: XrdPosix.hh:43
XrdOucString Path
struct myOpts opts
long long cpyTime
Definition: XrdFrcXAttr.hh:55
static const char * Name()
Definition: XrdFrcXAttr.hh:184
static int Alloc(allocInfo &aInfo)
Definition: XrdOssCache.cc:492
static char * Parse(const char *token, char *cbuff, int cblen)
Definition: XrdOssCache.cc:814
static XrdOssCache_FS * fsfirst
Definition: XrdOssCache.hh:269
static void Adjust(dev_t devid, off_t size)
Definition: XrdOssCache.cc:397
const char * Path
Definition: XrdOssCreate.cc:85
const char * LFN
Definition: XrdOssCreate.cc:86
unsigned long long pOpts
Definition: XrdOssCreate.cc:84
XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
Definition: XrdOssCreate.cc:89
static const int minSNbsz
Definition: XrdOssSpace.hh:45
int GenRemotePath(const char *, char *)
Definition: XrdOssApi.cc:249
int StageCreate
Definition: XrdOssApi.hh:223
XrdOucPListAnchor SPList
Definition: XrdOssApi.hh:249
virtual int Stage(const char *, const char *, XrdOucEnv &, int, mode_t, unsigned long long)
Definition: XrdOssStage.cc:110
int SetFattr(XrdOssCreateInfo &crInfo, int datfd, time_t mtime)
int Alloc_Cache(XrdOssCreateInfo &, XrdOucEnv &)
virtual int Create(const char *, const char *, mode_t, XrdOucEnv &, int opts=0)
int GenLocalPath(const char *, char *)
Definition: XrdOssApi.cc:232
int MSS_Stat(const char *, struct stat *buff=0)
Definition: XrdOssMSS.cc:253
int MSS_Create(const char *path, mode_t, XrdOucEnv &)
Definition: XrdOssMSS.cc:206
XrdOucPListAnchor RPList
Definition: XrdOssApi.hh:257
int Alloc_Local(XrdOssCreateInfo &, XrdOucEnv &)
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
XrdOucPList * About(const char *pathname)
Definition: XrdOucPList.hh:92
void Default(unsigned long long x)
Definition: XrdOucPList.hh:101
void Set(int aval)
Definition: XrdOucPList.hh:51
unsigned long long Flag()
Definition: XrdOucPList.hh:42
const char * Name()
Definition: XrdOucPList.hh:43
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:917
int Set(const char *Path, int fd=-1)
Definition: XrdOucXAttr.hh:139
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition: XrdOuca2x.cc:257
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static XrdSysXAttr * Xat
Definition: XrdSysFAttr.hh:51
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0
int Opts
Definition: XrdMpxStats.cc:58
@ oct1
Definition: XrdSysTrace.hh:42