XRootD
XrdDigFS.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d D i g F S . c c */
4 /* */
5 /* (c) 2013 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 <sys/types.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <memory.h>
35 #include <cstring>
36 #include <cstdio>
37 #include <cstdlib>
38 #include <sys/param.h>
39 #include <sys/stat.h>
40 
41 #include "XrdVersion.hh"
42 
43 #include "XrdOuc/XrdOucStream.hh"
44 
45 #include "XrdSys/XrdSysE2T.hh"
46 #include "XrdSys/XrdSysError.hh"
47 #include "XrdSys/XrdSysHeaders.hh"
48 #include "XrdSys/XrdSysLogger.hh"
49 #include "XrdSys/XrdSysPthread.hh"
51 #include "XrdSfs/XrdSfsAio.hh"
52 
53 #include "XrdDig/XrdDigConfig.hh"
54 #include "XrdDig/XrdDigFS.hh"
55 
56 #ifdef AIX
57 #include <sys/mode.h>
58 #endif
59 
60 /******************************************************************************/
61 /* L o c a l D e f i n e s */
62 /******************************************************************************/
63 
64 #ifdef __linux__
65 #define IS_PROC(x) !strncmp(x+SFS_LCLPLEN, "proc", 4) \
66  && (*(x+SFS_LCLPLEN+4) == '\0'||*(x+SFS_LCLPLEN+4) == '/')
67 #endif
68 
69 /******************************************************************************/
70 /* G l o b a l O b j e c t s */
71 /******************************************************************************/
72 
73 namespace XrdDig
74 {
76 
77  extern XrdDigConfig Config;
78 };
79 
80 using namespace XrdDig;
81 
82 /******************************************************************************/
83 /* U n i x F i l e S y s t e m I n t e r f a c e */
84 /******************************************************************************/
85 
86 class XrdDigUFS
87 {
88 public:
89 
90 static int Close(int fd) {return close(fd);}
91 
92 static int Open(const char *path, int oflag) {return open(path, oflag);}
93 
94 static int Statfd(int fd, struct stat *buf) {return fstat(fd, buf);}
95 
96 static int Statfn(const char *fn, struct stat *buf) {return stat(fn, buf);}
97 
98 static int Statlk(const char *fn, struct stat *buf) {return lstat(fn, buf);}
99 };
100 
101 /******************************************************************************/
102 /* X r d D i g G e t F S */
103 /******************************************************************************/
104 
106  XrdSysLogger *lp,
107  const char *cFN,
108  const char *parms)
109 {
110  static XrdSysError Eroute(lp, "XrdDig");
111  static XrdDigFS myFS;
112  bool isOK;
113 
114  Eroute.Say("Copr. 2013 Stanford University/SLAC dig file system");
115  eDest = &Eroute;
116 
117 // Configure
118 //
119  eDest->Say("++++++ DigFS initialization started.");
120  isOK = Config.Configure(cFN, parms);
121  eDest->Say("------ DigFS initialization ",(isOK ? "completed." : "failed."));
122 
123 // All done
124 //
125  return (isOK ? &myFS : 0);
126 }
127 
128 /******************************************************************************/
129 /* D i r e c t o r y O b j e c t I n t e r f a c e s */
130 /******************************************************************************/
131 /******************************************************************************/
132 /* o p e n */
133 /******************************************************************************/
134 
135 int XrdDigDirectory::open(const char *dir_path, // In
136  const XrdSecClientName *client, // In
137  const char *info) // In
138 /*
139  Function: Open the directory `path' and prepare for reading.
140 
141  Input: path - The fully qualified name of the directory to open.
142  cred - Authentication credentials, if any.
143  info - Opaque information, if any.
144 
145  Output: Returns SFS_OK upon success, otherwise SFS_ERROR.
146 */
147 {
148  static const char *epname = "opendir";
149  int retc;
150 
151 // Verify that this object is not already associated with an open directory
152 //
153  if (dh || isBase) return XrdDigFS::Emsg(epname, error, EADDRINUSE,
154  "open directory", dir_path);
155 
156 // Check if we are trying to open the root to list it
157 //
158  if (!strcmp(dir_path, SFS_LCLPRFX) || !strcmp(dir_path, SFS_LCLPRFY))
159  {isBase = true;
160  if ((dirFD = Config.GenAccess(client, dirent_full.aEnt, aESZ)) < 0)
161  return XrdDigFS::Emsg(epname,error,EACCES,"open directory",dir_path);
162  ateof = dirFD == 0;
163  return SFS_OK;
164  }
165 
166 // Authorize this open and get actual file name to open
167 //
168  if ( (retc = XrdDigFS::Validate(dir_path))
169  || !(fname = Config.GenPath(retc, client, "opendir",
170  dir_path+SFS_LCLPLEN, XrdDigConfig::isDir)))
171  return XrdDigFS::Emsg(epname,error,retc,"open directory",dir_path);
172 
173 // Set up values for this directory object
174 //
175  ateof = false;
176 
177 // Open the directory and get it's id
178 //
179  if (!(dh = opendir(fname)))
180  {if (fname) {free(fname); fname = 0;}
181  return XrdDigFS::Emsg(epname,error,errno,"open directory",dir_path);
182  }
183 
184 // Check if this is a reference to /proc (Linux only)
185 //
186 #ifdef __linux__
187  if (IS_PROC(dir_path))
188  {noTag = *(dir_path+SFS_LCLPLEN+4) == 0
189  || !strcmp(dir_path+SFS_LCLPLEN+4, "/");
190  isProc = true;
191  dirFD = dirfd(dh);
192  }
193 #endif
194 
195 // All done
196 //
197  return SFS_OK;
198 }
199 
200 /******************************************************************************/
201 /* n e x t E n t r y */
202 /******************************************************************************/
203 
205 /*
206  Function: Read the next directory entry.
207 
208  Input: None.
209 
210  Output: Upon success, returns the contents of the next directory entry as
211  a null terminated string. Returns a null pointer upon EOF or an
212  error. To differentiate the two cases, getErrorInfo will return
213  0 upon EOF and an actual error code (i.e., not 0) on error.
214 */
215 {
216  static const char *epname = "nextEntry";
217  static const int wMask = ~(S_IWUSR | S_IWGRP | S_IWOTH);
218  struct dirent *rp;
219  int retc;
220 
221 // Check for base listing
222 //
223  if (isBase)
224  {if (dirFD > 0) return dirent_full.aEnt[--dirFD];
225  ateof = true;
226  return (const char *)0;
227  }
228 
229 // Lock the direcrtory and do any required tracing
230 //
231  if (!dh)
232  {XrdDigFS::Emsg(epname,error,EBADF,"read directory",fname);
233  return (const char *)0;
234  }
235 
236 // Check if we are at EOF (once there we stay there)
237 //
238  if (ateof) return (const char *)0;
239 
240 // Read the next directory entry
241 //
242 #if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
243 do{errno = 0;
244  rp = readdir(dh);
245  if (!rp)
246  {if (!(retc = errno)) {ateof = 1; error.clear();}
247  else XrdDigFS::Emsg(epname,error,retc,"read directory",fname);
248  d_pnt->d_name[0] = '\0';
249  return (const char *)0;
250  }
251 #else
252 do{if ((retc = readdir_r(dh, d_pnt, &rp)))
253  {XrdDigFS::Emsg(epname,error,retc,"read directory",fname);
254  d_pnt->d_name[0] = '\0';
255  return (const char *)0;
256  }
257 
258 // Check if we have reached end of file
259 //
260  if (!rp || !d_pnt->d_name[0])
261  {ateof = true;
262  error.clear();
263  return (const char *)0;
264  }
265 #endif
266 
267 // If autostat wanted, do so here
268 //
269  if (sBuff)
270  {
271 #ifdef HAVE_FSTATAT
272  int sFlags = (isProc ? AT_SYMLINK_NOFOLLOW : 0);
273  if (fstatat(dirFD, rp->d_name, sBuff, sFlags)) continue;
274  sBuff->st_mode = (sBuff->st_mode & wMask) | S_IRUSR;
275 #else
276  char dPath[2048];
277  snprintf(dPath, sizeof(dPath), "%s%s", fname, rp->d_name);
278  if (stat(dPath, sBuff)) continue;
279  sBuff->st_mode = (sBuff->st_mode & wMask) | S_IRUSR;
280 #endif
281  }
282 
283 // We want to extend the directory entry information with symlink information
284 // if this is a symlink. This is only done for /proc (Linux only)
285 //
286 #ifdef __linux__
287  if (isProc)
288  {struct stat Stat, *sP = (sBuff ? sBuff : &Stat);
289  char *dP;
290  int n, rc;
291  rc = (sBuff ? 0:fstatat(dirFD,rp->d_name,&Stat,AT_SYMLINK_NOFOLLOW));
292  if (!rc && !noTag && S_ISLNK(sP->st_mode))
293  {n = strlen(rp->d_name);
294  dP = rp->d_name + n + 4;
295  n = sizeof(dirent_full.nbf) - (n + 8);
296  if ((n = readlinkat(dirFD,rp->d_name,dP,n)) < 0) strcpy(dP,"?");
297  else *(dP+n) = 0;
298  memcpy(dP-4, " -> ", 4);
299  }
300  }
301 #endif
302 
303 // Return the actual entry
304 //
305  return (const char *)(rp->d_name);
306  } while(1);
307  return 0; // Keep compiler happy
308 }
309 
310 /******************************************************************************/
311 /* c l o s e */
312 /******************************************************************************/
313 
315 /*
316  Function: Close the directory object.
317 
318  Input: cred - Authentication credentials, if any.
319 
320  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
321 */
322 {
323  static const char *epname = "closedir";
324 
325 // Release the handle
326 //
327  sBuff = 0;
328  if (dh && closedir(dh))
329  {XrdDigFS::Emsg(epname, error, errno, "close directory", fname);
330  return SFS_ERROR;
331  }
332 
333 // Do some clean-up
334 //
335  if (fname) {free(fname); fname = 0;}
336  dh = (DIR *)0;
337  isProc = isBase = false;
338  return SFS_OK;
339 }
340 
341 /******************************************************************************/
342 /* F i l e O b j e c t I n t e r f a c e s */
343 /******************************************************************************/
344 /******************************************************************************/
345 /* o p e n */
346 /******************************************************************************/
347 
348 int XrdDigFile::open(const char *path, // In
349  XrdSfsFileOpenMode open_mode, // In
350  mode_t Mode, // In
351  const XrdSecClientName *client, // In
352  const char *info) // In
353 /*
354  Function: Open the file `path' in the mode indicated by `open_mode'.
355 
356  Input: path - The fully qualified name of the file to open.
357  open_mode - One of the following flag values:
358  SFS_O_RDONLY - Open file for reading (only allowed)
359  Mode - Ignored.
360  client - Authentication credentials, if any.
361  info - Opaque information to be used as seen fit.
362 
363  Output: Returns SFS_OK upon success, otherwise SFS_ERROR is returned.
364 */
365 {
366  static const char *epname = "open";
367  int retc;
368  struct stat buf;
369 
370 // Verify that this object is not already associated with an open file
371 //
372  if (oh >= 0)
373  return XrdDigFS::Emsg(epname,error,EADDRINUSE,"open file",path);
374 
375 // Allow only opens in readonly mode
376 //
377  open_mode &= (SFS_O_RDONLY | SFS_O_WRONLY | SFS_O_RDWR | SFS_O_CREAT);
378  if (open_mode && open_mode != SFS_O_RDONLY)
379  return XrdDigFS::Emsg(epname,error,EROFS,"open file",path);
380 
381 // Authorize this open and get actual file name to open
382 //
383  if ( (retc = XrdDigFS::Validate(path))
384  || !(fname = Config.GenPath(retc, client, "open",
386  return XrdDigFS::Emsg(epname,error,retc,"open file",path);
387 
388 // Prohibit opening of a symlink in /proc (linux only) and memory
389 //
390 #ifdef __linux__
391  if (IS_PROC(path))
392  {struct stat Stat;
393  if (XrdDigUFS::Statlk(fname, &Stat)) retc = errno;
394  else if (!S_ISREG(Stat.st_mode)) retc = EPERM;
395  else retc = 0;
396  if (!retc && strstr(fname, "/mem")) retc = EACCES;
397  if (retc)
398  {free(fname);
399  return XrdDigFS::Emsg(epname, error, retc, "open proc file", path);
400  }
401  isProc = true;
402  }
403 #endif
404 
405 
406 // Open the file and make sure it is a file
407 //
408  if ((oh = XrdDigUFS::Open(fname, O_RDONLY)) >= 0)
409  {do {retc = XrdDigUFS::Statfd(oh, &buf);} while(retc && errno == EINTR);
410  if (!retc && !(buf.st_mode & S_IFREG))
411  {XrdDigUFS::Close(oh);
412  oh = (buf.st_mode & S_IFDIR ? -EISDIR : -ENOTBLK);
413  }
414  } else oh = -errno;
415 
416 // All done.
417 //
418  if (oh >= 0) return SFS_OK;
419  if (fname) {free(fname); fname = 0;}
420  return XrdDigFS::Emsg(epname,error,oh,"open file",path);
421 }
422 
423 /******************************************************************************/
424 /* c l o s e */
425 /******************************************************************************/
426 
428 /*
429  Function: Close the file object.
430 
431  Input: None
432 
433  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
434 */
435 {
436  static const char *epname = "close";
437 
438 // Release the handle and return
439 //
440  if (oh >= 0 && XrdDigUFS::Close(oh))
441  return XrdDigFS::Emsg(epname, error, errno, "close", fname);
442  oh = -1;
443  if (fname) {free(fname); fname = 0;}
444  return SFS_OK;
445 }
446 
447 /******************************************************************************/
448 /* f c t l */
449 /******************************************************************************/
450 
451 int XrdDigFile::fctl(const int cmd,
452  const char *args,
453  XrdOucErrInfo &out_error)
454 {
455 // See if we can do this
456 //
457  if (cmd == SFS_FCTL_GETFD)
458  {out_error.setErrCode(isProc ? -1 : oh);
459  return SFS_OK;
460  }
461 
462 // We don't support this
463 //
464  out_error.setErrInfo(ENOTSUP, "fctl operation not supported");
465  return SFS_ERROR;
466 }
467 
468 /******************************************************************************/
469 /* r e a d */
470 /******************************************************************************/
471 
473  char *buff, // Out
474  XrdSfsXferSize blen) // In
475 /*
476  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
477  number of bytes read.
478 
479  Input: offset - The absolute byte offset at which to start the read.
480  buff - Address of the buffer in which to place the data.
481  blen - The size of the buffer. This is the maximum number
482  of bytes that will be read from 'fd'.
483 
484  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
485 */
486 {
487  static const char *epname = "read";
488  XrdSfsXferSize nbytes;
489 
490 // Make sure the offset is not too large
491 //
492 #if _FILE_OFFSET_BITS!=64
493  if (offset > 0x000000007fffffff)
494  return XrdDigFS::Emsg(epname, error, EFBIG, "read", fname);
495 #endif
496 
497 // Read the actual number of bytes
498 //
499  do { nbytes = pread(oh, (void *)buff, (size_t)blen, (off_t)offset); }
500  while(nbytes < 0 && errno == EINTR);
501 
502  if (nbytes < 0)
503  return XrdDigFS::Emsg(epname, error, errno, "read", fname);
504 
505 // Return number of bytes read
506 //
507  return nbytes;
508 }
509 
510 /******************************************************************************/
511 /* r e a d v */
512 /******************************************************************************/
513 
515  int readCount) // In
516 /*
517  Function: Perform all the reads specified in the readV vector.
518 
519  Input: readV - A description of the reads to perform; includes the
520  absolute offset, the size of the read, and the buffer
521  to place the data into.
522  readCount - The size of the readV vector.
523 
524  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
525  If the number of bytes read is less than requested, it is considered
526  an error.
527 */
528 {
529  static const char *epname = "readv";
530  XrdSfsXferSize nbytes = 0;
531  ssize_t curCount;
532  int i;
533 
534  for (i=0; i<int(readCount); i++)
535  {do {curCount = pread(oh, (void *)readV[i].data, (size_t)readV[i].size, (off_t)readV[i].offset);}
536  while(curCount < 0 && errno == EINTR);
537 
538  if (curCount != readV[i].size)
539  {if (curCount > 0) errno = ESPIPE;
540  return XrdDigFS::Emsg(epname, error, errno, "readv", fname);
541  }
542  nbytes += curCount;
543  }
544 
545  return nbytes;
546 }
547 
548 /******************************************************************************/
549 /* r e a d A I O */
550 /******************************************************************************/
551 
553 {
554 
555 // Execute this request in a synchronous fashion
556 //
557  aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
558  (char *)aiop->sfsAio.aio_buf,
560  aiop->doneRead();
561  return 0;
562 }
563 
564 /******************************************************************************/
565 /* s t a t */
566 /******************************************************************************/
567 
568 int XrdDigFile::stat(struct stat *buf) // Out
569 /*
570  Function: Return file status information
571 
572  Input: buf - The stat structiure to hold the results
573 
574  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
575 */
576 {
577  static const char *epname = "stat";
578  static const int wMask = ~(S_IWUSR | S_IWGRP | S_IWOTH);
579 
580 // Execute the function
581 //
582  if (XrdDigUFS::Statfd(oh, buf))
583  return XrdDigFS::Emsg(epname, error, errno, "stat", fname);
584 
585 // Fixup size when stat is issued into /proc (linux only would set isProc)
586 //
587  if (isProc && !buf->st_size && S_ISREG(buf->st_mode)) buf->st_size = 1048576;
588 
589 // Turn off write bits in the mode
590 //
591  buf->st_mode &= wMask;
592 
593 // All went well
594 //
595  return SFS_OK;
596 }
597 
598 /******************************************************************************/
599 /* F i l e S y s t e m O b j e c t I n t e r f a c e s */
600 /******************************************************************************/
601 /******************************************************************************/
602 /* E m s g */
603 /******************************************************************************/
604 
605 int XrdDigFS::Emsg(const char *pfx, // Message prefix value
606  XrdOucErrInfo &einfo, // Place to put text & error code
607  int ecode, // The error code
608  const char *op, // Operation being performed
609  const char *target) // The target (e.g., fname)
610 {
611  const char *etext;
612  char buffer[MAXPATHLEN+80];
613 
614 // Get the reason for the error
615 //
616  if (ecode < 0) ecode = -ecode;
617  etext = XrdSysE2T(ecode);
618 
619 // Format the error message
620 //
621  snprintf(buffer,sizeof(buffer),"Unable to %s %s; %s", op, target, etext);
622 
623 // Print it out if debugging is enabled
624 //
625 #ifndef NODEBUG
626  eDest->Emsg(pfx, buffer);
627 #endif
628 
629 // Place the error message in the error object and return
630 //
631  einfo.setErrInfo(ecode, buffer);
632 
633  return SFS_ERROR;
634 }
635 
636 /******************************************************************************/
637 /* e x i s t s */
638 /******************************************************************************/
639 
640 int XrdDigFS::exists(const char *path, // In
641  XrdSfsFileExistence &file_exists, // Out
642  XrdOucErrInfo &error, // Out
643  const XrdSecClientName *client, // In
644  const char *info) // In
645 /*
646  Function: Determine if file 'path' actually exists.
647 
648  Input: path - Is the fully qualified name of the file to be tested.
649  file_exists - Is the address of the variable to hold the status of
650  'path' when success is returned. The values may be:
651  XrdSfsFileExistsIsDirectory - file not found but path is valid.
652  XrdSfsFileExistsIsFile - file found.
653  XrdSfsFileExistsIsNo - neither file nor directory.
654  einfo - Error information object holding the details.
655  client - Authentication credentials, if any.
656  info - Opaque information, if any.
657 
658  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
659 
660  Notes: When failure occurs, 'file_exists' is not modified.
661 */
662 {
663  static const char *epname = "exists";
664  struct stat fstat;
665 
666 // Now try to find the file or directory
667 //
668  if (!XrdDigUFS::Statfn(path, &fstat))
669  { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
670  else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
671  else file_exists=XrdSfsFileExistNo;
672  return SFS_OK;
673  }
674  if (errno == ENOENT)
675  {file_exists=XrdSfsFileExistNo;
676  return SFS_OK;
677  }
678 
679 // An error occurred, return the error info
680 //
681  return XrdDigFS::Emsg(epname, error, errno, "locate", path);
682 }
683 
684 /******************************************************************************/
685 /* f s c t l */
686 /******************************************************************************/
687 
688 int XrdDigFS::fsctl(const int cmd,
689  const char *args,
690  XrdOucErrInfo &eInfo,
691  const XrdSecClientName *client)
692 /*
693  Function: Perform filesystem operations:
694 
695  Input: cmd - Operation command (currently supported):
696  SFS_FSCTL_LOCATE - locate file (always local)
697  arg - Command dependent argument:
698  - Locate: The path whose location is wanted
699  eInfo - Error/Response information structure.
700  client - Authentication credentials, if any.
701 
702  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
703 */
704 {
705 
706 // Process the LOCATE request. We only support "*/path" type of requests and
707 // if valid, we return ourselves as the location. Security is not applied here.
708 //
709  if ((cmd & SFS_FSCTL_CMD) == SFS_FSCTL_LOCATE)
710  {if ((*args == '*' && !(SFS_LCLROOT(args+1)))
711  || (*args == '/' && !(SFS_LCLROOT(args ))))
712  {eInfo.setErrInfo(EINVAL, "Invalid locate path");
713  return SFS_ERROR;
714  }
715 
716  Config.GetLocResp(eInfo, (cmd & SFS_O_HNAME));
717  return SFS_DATA;
718  }
719 
720 // We don't support anything else
721 //
722  eInfo.setErrInfo(ENOTSUP, "Operation not supported.");
723  return SFS_ERROR;
724 }
725 
726 /******************************************************************************/
727 /* g e t V e r s i o n */
728 /******************************************************************************/
729 
730 const char *XrdDigFS::getVersion() {return XrdVERSION;}
731 
732 /******************************************************************************/
733 /* Private: R e j e c t */
734 /******************************************************************************/
735 
736 int XrdDigFS::Reject(const char *op, const char *trg, XrdOucErrInfo &eInfo)
737 {
738  return XrdDigFS::Emsg("Inspect", eInfo, EROFS, op, trg);
739 }
740 
741 /******************************************************************************/
742 /* s t a t */
743 /******************************************************************************/
744 
745 int XrdDigFS::stat(const char *path, // In
746  struct stat *buf, // Out
747  XrdOucErrInfo &error, // Out
748  const XrdSecClientName *client, // In
749  const char *info) // In
750 /*
751  Function: Get info on 'path'.
752 
753  Input: path - Is the fully qualified name of the file to be tested.
754  buf - The stat structiure to hold the results
755  error - Error information object holding the details.
756  client - Authentication credentials, if any.
757  info - Opaque information, if any.
758 
759  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
760 */
761 {
762  static const char *epname = "stat";
763  static const int wMask = ~(S_IWUSR | S_IWGRP | S_IWOTH);
764  char *fname;
765  int retc;
766 
767 // Check if we are trying to stat the root
768 //
769  if (!strcmp(path, SFS_LCLPRFX) || !strcmp(path, SFS_LCLPRFY))
770  {const char *auth;
771  if (Config.GenAccess(client, &auth, 1) < 0)
772  return XrdDigFS::Emsg(epname,error,EACCES,"stat directory",path);
774  return SFS_OK;
775  }
776 
777 // Authorize and get the correct fname to stat
778 //
779  if ((retc = Validate(path))
780  || !(fname = Config.GenPath(retc, client, "stat", path+SFS_LCLPLEN)))
781  return XrdDigFS::Emsg(epname,error,retc,"stat",path);
782 
783 // Fixup filename when stat is issued into /proc (linux only)
784 //
785 #ifdef __linux__
786  char *myLink;
787  if ((myLink = strstr(fname, " -> "))) *myLink = 0;
788 #endif
789 
790 // Execute the function
791 //
792  if (XrdDigUFS::Statfn(fname, buf))
793  {retc = errno;
794  free(fname);
795  return XrdDigFS::Emsg(epname, error, retc, "stat", path);
796  }
797 
798 // Turn off write bits in the mode
799 //
800  buf->st_mode &= wMask;
801 
802 // All went well
803 //
804  free(fname);
805  return SFS_OK;
806 }
807 
808 /******************************************************************************/
809 /* V a l i d a t e */
810 /******************************************************************************/
811 
812 int XrdDigFS::Validate(const char *path)
813 {
814 // Make sure this is our path and is legal
815 //
816  return (SFS_LCLPATH(path) && *(path+SFS_LCLPLEN) ? 0 : EPERM);
817 }
struct stat Stat
Definition: XrdCks.cc:49
XrdSfsFileSystem * XrdDigGetFS(XrdSfsFileSystem *native_fs, XrdSysLogger *lp, const char *cFN, const char *parms)
Definition: XrdDigFS.cc:105
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
int stat(const char *path, struct stat *buf)
struct dirent * readdir(DIR *dirp)
int open(const char *path, int oflag,...)
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
int fstat(int fildes, struct stat *buf)
int lstat(const char *path, struct stat *buf)
int closedir(DIR *dirp)
ssize_t read(int fildes, void *buf, size_t nbyte)
DIR * opendir(const char *path)
#define close(a)
Definition: XrdPosix.hh:43
#define XrdSecClientName
int Mode
off_t aio_offset
Definition: XrdSfsAio.hh:49
size_t aio_nbytes
Definition: XrdSfsAio.hh:48
void * aio_buf
Definition: XrdSfsAio.hh:47
#define SFS_LCLPRFY
#define SFS_O_HNAME
#define SFS_DATA
#define SFS_ERROR
XrdSfsFileExistence
@ XrdSfsFileExistIsFile
@ XrdSfsFileExistNo
@ XrdSfsFileExistIsDirectory
#define SFS_LCLROOT(x)
#define SFS_FSCTL_CMD
#define SFS_O_RDONLY
#define SFS_LCLPRFX
#define SFS_O_WRONLY
#define SFS_FCTL_GETFD
#define SFS_O_CREAT
#define SFS_FSCTL_LOCATE
#define SFS_LCLPLEN
#define SFS_O_RDWR
int XrdSfsFileOpenMode
#define SFS_OK
long long XrdSfsFileOffset
#define SFS_LCLPATH(x)
int XrdSfsXferSize
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
#define dirfd(x)
int GenAccess(const XrdSecEntity *client, const char *aList[], int aMax)
char * GenPath(int &rc, const XrdSecEntity *client, const char *opname, const char *lfn, pType lfnType=isAny)
static void StatRoot(struct stat *sP)
void GetLocResp(XrdOucErrInfo &eInfo, bool nameok)
bool Configure(const char *cFN, const char *parms)
Definition: XrdDigConfig.cc:97
const char * nextEntry()
Definition: XrdDigFS.cc:204
int open(const char *dirName, const XrdSecClientName *client=0, const char *opaque=0)
Definition: XrdDigFS.cc:135
const char * getVersion()
Definition: XrdDigFS.cc:730
int fsctl(const int cmd, const char *args, XrdOucErrInfo &out_error, const XrdSecClientName *client=0)
Definition: XrdDigFS.cc:688
int exists(const char *fileName, XrdSfsFileExistence &exists_flag, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
Definition: XrdDigFS.cc:640
static int Validate(const char *)
Definition: XrdDigFS.cc:812
static int Emsg(const char *, XrdOucErrInfo &, int, const char *x, const char *y="")
Definition: XrdDigFS.cc:605
int stat(const char *Name, struct stat *buf, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
Definition: XrdDigFS.cc:745
int open(const char *fileName, XrdSfsFileOpenMode openMode, mode_t createMode, const XrdSecClientName *client=0, const char *opaque=0)
Definition: XrdDigFS.cc:348
int stat(struct stat *buf)
Definition: XrdDigFS.cc:568
int read(XrdSfsFileOffset fileOffset, XrdSfsXferSize preread_sz)
Definition: XrdDigFS.hh:120
int close()
Definition: XrdDigFS.cc:427
XrdSfsXferSize readv(XrdOucIOVec *readV, int readCount)
Definition: XrdDigFS.cc:514
virtual int fctl(const int cmd, const char *args, XrdOucErrInfo &eInfo)=0
static int Close(int fd)
Definition: XrdDigFS.cc:90
static int Statfd(int fd, struct stat *buf)
Definition: XrdDigFS.cc:94
static int Statlk(const char *fn, struct stat *buf)
Definition: XrdDigFS.cc:98
static int Statfn(const char *fn, struct stat *buf)
Definition: XrdDigFS.cc:96
static int Open(const char *path, int oflag)
Definition: XrdDigFS.cc:92
int setErrInfo(int code, const char *emsg)
int setErrCode(int code)
ssize_t Result
Definition: XrdSfsAio.hh:65
virtual void doneRead()=0
struct aiocb sfsAio
Definition: XrdSfsAio.hh:62
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
XrdSysError * eDest
Definition: XrdDigConfig.cc:68
XrdDigConfig Config
Definition: XrdDigConfig.cc:72