XRootD
Loading...
Searching...
No Matches
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"
53#include "XrdOss/XrdOssCopy.hh"
54#include "XrdOss/XrdOssError.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"
62#include "XrdOuc/XrdOucUtils.hh"
63#include "XrdOuc/XrdOucXAttr.hh"
64#include "XrdSys/XrdSysError.hh"
67
68/******************************************************************************/
69/* E r r o r R o u t i n g O b j e c t */
70/******************************************************************************/
71
73
75
76extern 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*/
113int 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
314int 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)
#define EPNAME(x)
XrdSysError OssEroute
XrdOssSys * XrdOssSS
Definition XrdOssApi.cc:77
#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
#define OSS_ASIZE
#define OSS_CGROUP
#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
#define XRDEXP_NOCHECK
#define XRDEXP_RCREATE
#define XRDEXP_NOXATTR
#define XRDEXP_MIGPRG
#define close(a)
Definition XrdPosix.hh:48
#define open
Definition XrdPosix.hh:76
#define unlink(a)
Definition XrdPosix.hh:113
#define stat(a, b)
Definition XrdPosix.hh:101
XrdOucString Path
bool Create
struct myOpts opts
static const char * Name()
static int Alloc(allocInfo &aInfo)
static char * Parse(const char *token, char *cbuff, int cblen)
static XrdOssCache_FS * fsfirst
static void Adjust(dev_t devid, off_t size)
const char * Path
const char * LFN
unsigned long long pOpts
XrdOssCreateInfo(const char *path, const char *lfn, mode_t amode, int opts)
static const int minSNbsz
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)
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
void Default(unsigned long long x)
XrdOucPList * About(const char *pathname)
void Set(int aval)
const char * Name()
unsigned long long Flag()
static int makePath(char *path, mode_t mode, bool reset=false)
int Set(const char *Path, int fd=-1)
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)
static XrdSysXAttr * Xat
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0