XRootD
Loading...
Searching...
No Matches
XrdOfsFAttr.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d O f s F A t t r . c c */
4/* */
5/* (c) 2018 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Deprtment of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#include "XrdOfs/XrdOfs.hh"
31#include "XrdOfs/XrdOfsTrace.hh"
33
34#include "XrdOss/XrdOss.hh"
35
36#include "XrdOuc/XrdOucEnv.hh"
38
40
41#include "XrdSfs/XrdSfsFAttr.hh"
42#include "XrdSfs/XrdSfsFlags.hh"
44
45#include "XrdSys/XrdSysFAttr.hh"
46
47/******************************************************************************/
48/* E r r o r R o u t i n g O b j e c t */
49/******************************************************************************/
50
52
53/******************************************************************************/
54/* F i l e S y s t e m O b j e c t */
55/******************************************************************************/
56
57extern XrdOfs* XrdOfsFS;
58
59/******************************************************************************/
60/* S t o r a g e S y s t e m O b j e c t */
61/******************************************************************************/
62
63extern XrdOss *XrdOfsOss;
64
65/******************************************************************************/
66/* L o c a l F u n c t i o n s a n d O b j e c t s */
67/******************************************************************************/
68
69namespace
70{
71XrdSysMutex faMutex;
72
73static const int faSize = 8192-sizeof(XrdSfsFABuff);
74}
75
76/******************************************************************************/
77/* G e t F A B u f f */
78/******************************************************************************/
79
80namespace
81{
82bool GetFABuff(XrdSfsFACtl &faCtl, int sz=0)
83{
84 XrdSfsFABuff *fabP = (XrdSfsFABuff *)malloc(sz + sizeof(XrdSfsFABuff));
85
86// Check if we allocate a buffer
87//
88 if (!fabP) return false;
89
90// Setup the buffer
91//
92 fabP->next = faCtl.fabP;
93 faCtl.fabP = fabP;
94 fabP->dlen = sz;
95 return true;
96}
97}
98
99/******************************************************************************/
100/* G e t F A V a l */
101/******************************************************************************/
102
103namespace
104{
105bool GetFAVal(XrdSfsFACtl &faCtl, char *&bP, int &bL, unsigned int k)
106{
107 int rc;
108
109// Get the attribute value
110//
111 rc = XrdSysFAttr::Xat->Get(faCtl.info[k].Name, bP, bL, faCtl.pfnP);
112
113// If all went well, record the value and update incoming information
114//
115 if (rc >= 0)
116 {faCtl.info[k].faRC = 0;
117 faCtl.info[k].Value = bP;
118 faCtl.info[k].VLen = rc;
119 bP += rc; bL -= rc;
120 return true;
121 }
122
123// Check for any error other than buffer too small
124//
125 if (rc != -ERANGE)
126 {faCtl.info[k].faRC = -rc;
127 return true;
128 }
129
130// Buffer is too small, tell the caller to recover
131//
132 return false;
133}
134}
135
136/******************************************************************************/
137/* G u l p F A V a l */
138/******************************************************************************/
139
140namespace
141{
142bool GulpFAVal(XrdSfsFACtl &faCtl, char *&bP, int &bL, unsigned int k)
143{
144 XrdSysMutexHelper mHelper(faMutex);
145 char *bzP = 0;
146 int n = 0;
147
148// Get the size of the attribute value
149//
150 if (!GetFAVal(faCtl, bzP, n, k))
151 {faCtl.info[k].faRC = ERANGE;
152 faCtl.info[k].VLen = 0;
153 return true;
154 }
155
156// Allocate a new buffer to hold this and possible some more values
157//
158 n = faCtl.info[k].VLen;
159 faCtl.info[k].VLen = 0;
160 if (n < faSize/2) n = faSize;
161 if (!GetFABuff(faCtl, n)) return false;
162
163// Now fetch the variable in a right sized buffer
164//
165 bP = faCtl.fabP->data;
166 bL = faCtl.fabP->dlen;
167 if (!GetFAVal(faCtl, bP, bL, k)) faCtl.info[k].faRC = ERANGE;
168 else {bP += faCtl.info[k].VLen;
169 bL -= faCtl.info[k].VLen;
170 }
171 return true;
172}
173}
174
175/******************************************************************************/
176/* S e t N o M e m */
177/******************************************************************************/
178
179namespace
180{
181int SetNoMem(XrdSfsFACtl &faCtl, unsigned int iX)
182{
183
184// Set no memory error for remaining attributes
185//
186 for (unsigned int i = iX; i < faCtl.iNum; i++) faCtl.info[i].faRC = ENOMEM;
187 return SFS_OK;
188}
189}
190
191/******************************************************************************/
192/* F A t t r */
193/******************************************************************************/
194
196 XrdOucErrInfo &einfo,
197 const XrdSecEntity *client)
198{
199 EPNAME("FAttr");
200 const char *tident = einfo.getErrUser();
201 char pfnbuff[MAXPATHLEN+8];
202 const char *accType;
203 long long xOpts;
204
205 struct faArgs {const char *name; int fArg; Access_Operation aop;};
206
207 static faArgs faTab[] = {{ "del fattr", SFS_O_RDWR, AOP_Update}, // del
208 { "get fattr", 0, AOP_Read}, // get
209 {"list fattr", 0, AOP_Read}, // list
210 { "set fattr", SFS_O_RDWR, AOP_Update} // set
211 };
212 static const int faNum = sizeof(faTab)/sizeof(struct faArgs);
213
214 int rc;
215
216// Check if we need only return support information
217//
218 if (!faReq)
219 {XrdOucEnv *envP = einfo.getEnv();
220 ZTRACE(fsctl, "FAttr req=info");
221 if (!envP || !usxMaxNsz)
222 {einfo.setErrInfo(ENOTSUP, "Not supported.");
223 return SFS_ERROR;
224 }
225 envP->PutInt("usxMaxNsz", usxMaxNsz);
226 envP->PutInt("usxMaxVsz", usxMaxVsz);
227 return SFS_OK;
228 }
229
230// Setup for to perform attribute functions
231//
232 XrdSfsFACtl &faCtl = *faReq;
233 XrdOucEnv FAttr_Env(faCtl.pcgi,0,client);
234
235// Make sure request code is valid (we also set some options)
236//
237 if (faCtl.rqst > faNum)
238 return Emsg(epname, einfo, EINVAL, "process fattrs", faCtl.path);
239 accType = faTab[faCtl.rqst].name;
240
241// Trace this call
242//
243 ZTRACE(fsctl, "FAttr " <<accType <<' ' <<faCtl.path);
244
245// Extract the export options if we can
246//
247 xOpts = (ossRPList ? ossRPList->Find(faCtl.path) : 0);
248
249// Perform authrorization and redirection if required
250//
251 if (faCtl.opts & XrdSfsFACtl::accChk)
252 {int luFlag = faTab[faCtl.rqst].fArg;
253 Access_Operation aOP = faTab[faCtl.rqst].aop;
254
255 AUTHORIZE(client, 0, aOP, accType ,faCtl.path, einfo);
256
257 if (Finder && Finder->isRemote()
258 && (rc = Finder->Locate(einfo, faCtl.path, luFlag, &FAttr_Env)))
259 return fsError(einfo, rc);
260
261 if (aOP == AOP_Update && xOpts & XRDEXP_NOTRW)
262 return Emsg(epname, einfo, EROFS, accType, faCtl.path);
263 }
264
265// If this is a proxy server then hand this request to the storage system
266// as it will need to be executed elsewhere.
267//
268 if (OssIsProxy)
269 {faCtl.envP = &FAttr_Env;
270 rc = XrdOfsOss->FSctl(XRDOSS_FSCTLFA, 0, (const char *)&faCtl);
271 if (rc) return XrdOfsFS->Emsg(epname, einfo, rc, accType, faCtl.path);
272 return SFS_OK;
273 }
274
275// Make sure we can use xattrs on the path
276//
277 if (xOpts & XRDEXP_NOXATTR)
278 return XrdOfsFS->Emsg(epname, einfo, EPERM, accType, faCtl.path);
279
280// Convert the lfn to a pfn for actual calls to the attribute processor
281//
282 faCtl.pfnP = XrdOfsOss->Lfn2Pfn(faCtl.path, pfnbuff, sizeof(pfnbuff), rc);
283 if (!faCtl.pfnP) return XrdOfsFS->Emsg(epname,einfo,rc,accType,faCtl.path);
284
285// Fan out for processing this on the local file system
286//
287 switch(faCtl.rqst)
288 {case XrdSfsFACtl::faDel:
289 return ctlFADel(faCtl, FAttr_Env, einfo);
290 break;
292 return ctlFAGet(faCtl, FAttr_Env, einfo);
293 break;
295 return ctlFALst(faCtl, FAttr_Env, einfo);
296 break;
298 return ctlFASet(faCtl, FAttr_Env, einfo);
299 break;
300 default: break;
301 }
302
303// The request code is not one we understand
304//
305 return XrdOfsFS->Emsg(epname, einfo, EINVAL, "process fattrs", faCtl.path);
306}
307
308/******************************************************************************/
309/* c t l F A D e l */
310/******************************************************************************/
311
312int XrdOfs::ctlFADel(XrdSfsFACtl &faCtl, XrdOucEnv &faEnv, XrdOucErrInfo &einfo)
313{
314
315// Delete each variable
316//
317 for (unsigned int i = 0; i < faCtl.iNum; i++)
318 faCtl.info[i].faRC = XrdSysFAttr::Xat->Del(faCtl.info[i].Name,faCtl.pfnP);
319
320// All done
321//
322 return SFS_OK;
323}
324
325/******************************************************************************/
326/* c t l F A L s t */
327/******************************************************************************/
328
329int XrdOfs::ctlFALst(XrdSfsFACtl &faCtl, XrdOucEnv &faEnv, XrdOucErrInfo &einfo)
330{
331 EPNAME("ctlFALst");
332 XrdSysXAttr::AList *alP, *aEnt;
333 char *nP, *bP;
334 int bL, rc, pfLen, iX = 0, faSize = 0, fvSize = 0;
335 bool getMsz = (faCtl.opts & XrdSfsFACtl::retvsz) == XrdSfsFACtl::retvsz;
336 bool getVal = (faCtl.opts & XrdSfsFACtl::retval) == XrdSfsFACtl::retval;
337 bool xPlode = (faCtl.opts & XrdSfsFACtl::xplode) != 0;
338
339// Get all of the attribute names
340//
341 rc = XrdSysFAttr::Xat->List(&alP, faCtl.pfnP, -1, getMsz);
342 if (rc < 0) return Emsg(epname, einfo, -rc, "list fattrs", faCtl.path);
343
344// Count up attributes
345//
346 faCtl.info = 0;
347 faCtl.iNum = 0;
348 pfLen = (*faCtl.nPfx ? sizeof(faCtl.nPfx) : 0);
349 aEnt = alP;
350 while(aEnt)
351 {if (aEnt->Nlen)
352 {if (!pfLen || !strncmp(faCtl.nPfx, aEnt->Name, pfLen))
353 {faCtl.iNum++;
354 faSize += aEnt->Nlen - pfLen + 1;
355 } else aEnt->Nlen = 0;
356 }
357 aEnt = aEnt->Next;
358 }
359
360// If there are no attributes of interest, we are done.
361//
362 if (!faCtl.iNum) return SFS_OK;
363
364// Allocate sufficient memory to hold the complete list
365//
366 if (!GetFABuff(faCtl, faSize))
367 {XrdSysFAttr::Xat->Free(alP);
368 return Emsg(epname, einfo, ENOMEM, "list fattrs", faCtl.path);
369 }
370
371// Allocate an info vector if caller wants this exploded
372//
373 if (xPlode) faCtl.info = new XrdSfsFAInfo[faCtl.iNum];
374 else faCtl.info = 0;
375
376// Copy over the names
377//
378 nP = faCtl.fabP->data;
379 aEnt = alP;
380 while(aEnt)
381 {if (aEnt->Nlen)
382 {strcpy(nP, aEnt->Name+pfLen);
383 if (xPlode)
384 {faCtl.info[iX].Name = nP;
385 faCtl.info[iX].NLen = aEnt->Nlen - pfLen;
386 faCtl.info[iX].VLen = aEnt->Vlen;
387 if (getVal && aEnt->Vlen) faCtl.info[iX].Value = aEnt->Name;
388 fvSize += aEnt->Vlen;
389 iX++;
390 }
391 nP += aEnt->Nlen-pfLen+1;
392 }
393 aEnt = aEnt->Next;
394 }
395
396// If we don't need to return values, we are done
397//
398 if (!getVal)
399 {XrdSysFAttr::Xat->Free(alP);
400 return SFS_OK;
401 }
402
403// Allocate a buffer to hold all of the values
404//
405 if (!GetFABuff(faCtl, fvSize))
406 {XrdSysFAttr::Xat->Free(alP);
407 return SetNoMem(faCtl, 0);
408 }
409
410// Setup to retrieve attributes
411//
412 bP = faCtl.fabP->data;
413 bL = faCtl.fabP->dlen;
414
415// Retrieve the attribute values
416//
417 for (unsigned int i = 0; i < faCtl.iNum; i++)
418 {if (faCtl.info[i].VLen)
419 {nP = faCtl.info[i].Name;
420 faCtl.info[i].Name = faCtl.info[i].Value;
421 faCtl.info[i].Value = 0;
422 if (!GetFAVal(faCtl, bP, bL, i) && !GulpFAVal(faCtl, bP, bL, i))
423 {XrdSysFAttr::Xat->Free(alP);
424 return SetNoMem(faCtl, i);
425 }
426 faCtl.info[i].Name = nP;
427 }
428 }
429
430// Free up the buffer list and return success
431//
433 return SFS_OK;
434}
435
436/******************************************************************************/
437/* c t l F A G e t */
438/******************************************************************************/
439
440int XrdOfs::ctlFAGet(XrdSfsFACtl &faCtl, XrdOucEnv &faEnv, XrdOucErrInfo &einfo)
441{
442 char *bP;
443 int bL;
444
445// Allocate the initial buffer. We make it big enough to, hopefully get all
446// of the attributes, though we may have to reallocate.
447//
448 if (!GetFABuff(faCtl, faSize)) return SetNoMem(faCtl, 0);
449
450// Setup to retrieve attributes
451//
452 bP = faCtl.fabP->data;
453 bL = faCtl.fabP->dlen;
454
455// Get each variable. Unfortunately, we need to allocate a buffer for each
456// one as we don't know the size.
457//
458 for (unsigned int i = 0; i < faCtl.iNum; i++)
459 {if (bL < 8)
460 {if (!GetFABuff(faCtl, faSize)) return SetNoMem(faCtl, i);
461 bP = faCtl.fabP->data;
462 bL = faCtl.fabP->dlen;
463 }
464
465 if (!GetFAVal(faCtl, bP, bL, i) && !GulpFAVal(faCtl, bP, bL, i))
466 return SetNoMem(faCtl, i);
467 }
468
469 return SFS_OK;
470}
471
472/******************************************************************************/
473/* c t l F A S e t */
474/******************************************************************************/
475
476int XrdOfs::ctlFASet(XrdSfsFACtl &faCtl, XrdOucEnv &faEnv, XrdOucErrInfo &einfo)
477{
478 int isNew = (faCtl.opts & XrdSfsFACtl::newAtr) != 0;
479
480// Lock this code if we are replacing variables
481//
482 if (!isNew) faMutex.Lock();
483
484// Set each variable
485//
486 for (unsigned int i = 0; i < faCtl.iNum; i++)
487 faCtl.info[i].faRC = XrdSysFAttr::Xat->Set(faCtl.info[i].Name,
488 faCtl.info[i].Value,
489 faCtl.info[i].VLen,
490 faCtl.pfnP, -1, isNew);
491
492// Unlock the mutex if we locked it
493//
494 if (!isNew) faMutex.UnLock();
495
496// All done
497 return SFS_OK;
498}
Access_Operation
The following are supported operations.
@ AOP_Update
open() r/w or append
@ AOP_Read
open() r/o, prepare()
#define tident
#define EPNAME(x)
#define ZTRACE(act, x)
XrdOss * XrdOfsOss
Definition XrdOfs.cc:163
XrdSysTrace OfsTrace
XrdOfs * XrdOfsFS
Definition XrdOfsFS.cc:47
#define AUTHORIZE(usr, env, optype, action, pathp, edata)
XrdOss * XrdOfsOss
Definition XrdOfs.cc:163
XrdOfs * XrdOfsFS
Definition XrdOfsFS.cc:47
#define XRDOSS_FSCTLFA
Definition XrdOss.hh:492
#define XRDEXP_NOTRW
#define XRDEXP_NOXATTR
char data[4]
Start of data.
int dlen
Data Length in subsequent buffer.
XrdSfsFABuff * next
#define SFS_ERROR
#define SFS_O_RDWR
#define SFS_OK
virtual int isRemote()
virtual int Locate(XrdOucErrInfo &Resp, const char *path, int flags, XrdOucEnv *Info=0)=0
XrdCmsClient * Finder
Definition XrdOfs.hh:429
int FAttr(XrdSfsFACtl *faReq, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)
int fsctl(const int cmd, const char *args, XrdOucErrInfo &out_error, const XrdSecEntity *client=0)
static int Emsg(const char *, XrdOucErrInfo &, int, const char *x, XrdOfsHandle *hP)
Definition XrdOfs.cc:2513
static int fsError(XrdOucErrInfo &myError, int rc)
Definition XrdOfs.cc:2621
virtual int FSctl(int cmd, int alen, const char *args, char **resp=0)
Definition XrdOss.cc:66
virtual int Lfn2Pfn(const char *Path, char *buff, int blen)
Definition XrdOss.hh:873
void PutInt(const char *varname, long value)
Definition XrdOucEnv.cc:250
const char * getErrUser()
XrdOucEnv * getEnv()
int setErrInfo(int code, const char *emsg)
unsigned long long Find(const char *pathname)
static XrdSysXAttr * Xat
char Name[1]
Start of the name (size of struct is dynamic)
int Vlen
The length of the attribute value;.
virtual int List(AList **aPL, const char *Path, int fd=-1, int getSz=0)=0
virtual int Get(const char *Aname, void *Aval, int Avsz, const char *Path, int fd=-1)=0
virtual int Set(const char *Aname, const void *Aval, int Avsz, const char *Path, int fd=-1, int isNew=0)=0
int Nlen
The length of the attribute name that follows.
virtual void Free(AList *aPL)=0
virtual int Del(const char *Aname, const char *Path, int fd=-1)=0
AList * Next
-> next element.
char nPfx[2]
The namespace being used.
XrdSfsFABuff * fabP
-> Additional memory that was allocated
static const int retval
Above plus return actual attr value.
const char * pfnP
The file path to act on (physical)
const char * path
The file path to act on (logical)
unsigned char rqst
Type of file attribute request (see below)
const char * pcgi
Opaque information (null if none)
static const int accChk
Perform access check.
static const int retvsz
Above plus return size of attr value.
static const int xplode
Construct an info vec from faList.
static const int newAtr
For set the attribute must not exist.
XrdOucEnv * envP
Optional environmental information.
XrdSfsFAInfo * info
Pointer to attribute information.
unsigned char opts
Request options (see below)
unsigned short iNum
Number of info entries.
char * Name
Variable name.
int VLen
Variable value length (aligned)
char * Value
Variable value.
short NLen
Length of name not including null byte.
int faRC
Action return code for this element.