XRootD
XrdOfs.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O f s . c c */
4 /* */
5 /* (c) 2004 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 <unistd.h>
31 #include <dirent.h>
32 #include <cerrno>
33 #include <fcntl.h>
34 #include <memory.h>
35 #include <cstring>
36 #include <cstdio>
37 #include <ctime>
38 #include <netdb.h>
39 #include <cstdlib>
40 #include <memory>
41 #include <sys/param.h>
42 #include <sys/stat.h>
43 #include <sys/time.h>
44 #include <sys/types.h>
45 
46 #include "XProtocol/XProtocol.hh"
47 
48 #include "XrdCks/XrdCks.hh"
49 #include "XrdCks/XrdCksConfig.hh"
50 #include "XrdCks/XrdCksData.hh"
51 
52 #include "XrdNet/XrdNetAddr.hh"
53 #include "XrdNet/XrdNetIF.hh"
54 #include "XrdNet/XrdNetUtils.hh"
55 
56 #include "XrdOfs/XrdOfs.hh"
57 #include "XrdOfs/XrdOfsChkPnt.hh"
58 #include "XrdOfs/XrdOfsConfigCP.hh"
59 #include "XrdOfs/XrdOfsEvs.hh"
60 #include "XrdOfs/XrdOfsHandle.hh"
61 #include "XrdOfs/XrdOfsPoscq.hh"
62 #include "XrdOfs/XrdOfsPrepare.hh"
63 #include "XrdOfs/XrdOfsTrace.hh"
64 #include "XrdOfs/XrdOfsSecurity.hh"
65 #include "XrdOfs/XrdOfsStats.hh"
66 #include "XrdOfs/XrdOfsTPC.hh"
67 
68 #include "XrdCms/XrdCmsClient.hh"
69 
70 #include "XrdOss/XrdOss.hh"
71 
72 #include "XrdSys/XrdSysError.hh"
73 #include "XrdSys/XrdSysHeaders.hh"
74 #include "XrdSys/XrdSysLogger.hh"
75 #include "XrdSys/XrdSysPlatform.hh"
76 #include "XrdSys/XrdSysPthread.hh"
77 #include "XrdSys/XrdSysRAtomic.hh"
78 
79 #include "XrdOuc/XrdOuca2x.hh"
80 #include "XrdOuc/XrdOucEnv.hh"
81 #include "XrdOuc/XrdOucERoute.hh"
82 #include "XrdOuc/XrdOucLock.hh"
83 #include "XrdOuc/XrdOucMsubs.hh"
85 #include "XrdOuc/XrdOucTList.hh"
86 #include "XrdOuc/XrdOucTPC.hh"
87 #include "XrdSec/XrdSecEntity.hh"
89 #include "XrdSfs/XrdSfsAio.hh"
90 #include "XrdSfs/XrdSfsFlags.hh"
92 
93 #ifdef AIX
94 #include <sys/mode.h>
95 #endif
96 
97 #ifndef O_DIRECT
98 #define O_DIRECT 0
99 #endif
100 
101 /******************************************************************************/
102 /* E r r o r R o u t i n g O b j e c t */
103 /******************************************************************************/
104 
106 
108 
109 /******************************************************************************/
110 /* S t a t i s t i c a l D a t a O b j e c t */
111 /******************************************************************************/
112 
114 
115 /******************************************************************************/
116 /* L o c a l F u n c t i o n s */
117 /******************************************************************************/
118 
119 namespace
120 {
121 bool VerPgw(const char *buf, ssize_t off, size_t len, const uint32_t* csv,
122  XrdOfsHandle *oh, XrdOucErrInfo &error)
123 {
124  EPNAME("VerPgw");
125  XrdOucPgrwUtils::dataInfo dInfo(buf, csv, off, len);
126  off_t badoff;
127  int badlen;
128 
129 // Verify incoming checksums
130 //
131  if (!XrdOucPgrwUtils::csVer(dInfo, badoff, badlen))
132  {char eMsg[512];
133  int n;
134  n = snprintf(eMsg, sizeof(eMsg), "Checksum error at offset %lld.", (long long) badoff);
135  error.setErrInfo(EDOM, eMsg);
136  eMsg[n-1] = 0;
137  OfsEroute.Emsg(epname, eMsg, "aborted pgwrite to", oh->Name());
138  return false;
139  }
140  return true;
141 }
142 }
143 
144 /******************************************************************************/
145 /* S t a t i c O b j e c t s */
146 /******************************************************************************/
147 
148 XrdOfsHandle *XrdOfs::dummyHandle;
149 
150 int XrdOfs::MaxDelay = 60;
151 int XrdOfs::OSSDelay = 30;
152 
153 /******************************************************************************/
154 /* F i l e S y s t e m O b j e c t */
155 /******************************************************************************/
156 
157 extern XrdOfs* XrdOfsFS;
158 
159 /******************************************************************************/
160 /* S t o r a g e S y s t e m O b j e c t */
161 /******************************************************************************/
162 
164 
165 /******************************************************************************/
166 /* X r d O f s C o n s t r u c t o r */
167 /*****************************************************************************/
168 
169 XrdOfs::XrdOfs() : dMask{0000,0775}, fMask{0000,0775}, // Legacy
170  tpcRdrHost{}, tpcRdrPort{}
171 {
172  const char *bp;
173 
174 // Establish defaults
175 //
176  ofsConfig = 0;
177  FSctl_PC = 0;
178  FSctl_PI = 0;
179  Authorization = 0;
180  Finder = 0;
181  Balancer = 0;
182  evsObject = 0;
183  ossRPList = 0;
184  myRole = strdup("server");
185  OssIsProxy = 0;
186  ossRW =' ';
187  ossFeatures = 0;
188 
189 // Obtain port number we will be using. Note that the constructor must occur
190 // after the port number is known (i.e., this cannot be a global static).
191 //
192  myPort = (bp = getenv("XRDPORT")) ? strtol(bp, (char **)NULL, 10) : 0;
193 
194 // Defaults for POSC
195 //
196  poscQ = 0;
197  poscLog = 0;
198  poscHold= 10*60;
199  poscAuto= 0;
200  poscSync= 1;
201 
202 // Set the configuration file name and dummy handle
203 //
204  ConfigFN = 0;
205  XrdOfsHandle::Alloc(&dummyHandle);
206 
207 // Set checksum pointers
208 //
209  Cks = 0;
210  CksPfn = true;
211  CksRdr = true;
212 
213 // Prepare handling
214 //
215  prepHandler = 0;
216  prepAuth = true;
217 
218 // Eextended attribute limits
219 //
220  usxMaxNsz = kXR_faMaxNlen;
221  usxMaxVsz = kXR_faMaxVlen;
222 
223 // Other options
224 //
225  DirRdr = false;
226  reProxy = false;
227  OssHasPGrw= false;
228  tryXERT = false;
229 }
230 
231 /******************************************************************************/
232 /* */
233 /* 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 */
234 /* */
235 /******************************************************************************/
236 /******************************************************************************/
237 /* o p e n */
238 /******************************************************************************/
239 
240 int XrdOfsDirectory::open(const char *dir_path, // In
241  const XrdSecEntity *client, // In
242  const char *info) // In
243 /*
244  Function: Open the directory `path' and prepare for reading.
245 
246  Input: path - The fully qualified name of the directory to open.
247  client - Authentication credentials, if any.
248  info - Opaque information to be used as seen fit.
249 
250  Output: Returns SFS_OK upon success, otherwise SFS_ERROR.
251 
252  Notes: 1. The code here assumes that directory file descriptors are never
253  shared. Hence, no locks need to be obtained. It works out that
254  lock overhead is worse than have a duplicate file descriptor for
255  very short durations.
256 */
257 {
258  EPNAME("opendir");
259  static const int od_mode = SFS_O_RDONLY|SFS_O_META;
260  XrdOucEnv Open_Env(info,0,client);
261  int retc;
262 
263 // Trace entry
264 //
265  XTRACE(opendir, dir_path, "");
266 
267 // Verify that this object is not already associated with an open directory
268 //
269  if (dp) return
270  XrdOfsFS->Emsg(epname, error, EADDRINUSE, "open directory", dir_path);
271 
272 // Apply security, as needed
273 //
274  AUTHORIZE(client,&Open_Env,AOP_Readdir,"open directory",dir_path,error);
275 
276 // Find out where we should open this directory
277 //
278  if (XrdOfsFS->DirRdr && XrdOfsFS->Finder && XrdOfsFS->Finder->isRemote()
279  && (retc = XrdOfsFS->Finder->Locate(error, dir_path, od_mode, &Open_Env)))
280  return XrdOfsFS->fsError(error, retc);
281 
282 // Open the directory and allocate a handle for it
283 //
284  if (!(dp = XrdOfsOss->newDir(tident))) retc = -ENOMEM;
285  else if (!(retc = dp->Opendir(dir_path, Open_Env)))
286  {fname = strdup(dir_path);
287  return SFS_OK;
288  }
289 
290 // Handle extended error information
291 //
292  std::string eText;
293  const char* etP = 0;
294  if (dp && XrdOfsFS->tryXERT)
295  {if (dp->getErrMsg(eText)) etP = eText.c_str();
296  delete dp; dp = 0;
297  }
298 
299 // Encountered an error
300 //
301  return XrdOfsFS->Emsg(epname, error, retc, "open directory", dir_path, etP);
302 }
303 
304 /******************************************************************************/
305 /* n e x t E n t r y */
306 /******************************************************************************/
307 
309 /*
310  Function: Read the next directory entry.
311 
312  Input: n/a
313 
314  Output: Upon success, returns the contents of the next directory entry as
315  a null terminated string. Returns a null pointer upon EOF or an
316  error. To differentiate the two cases, getErrorInfo will return
317  0 upon EOF and an actual error code (i.e., not 0) on error.
318 
319  Notes: 1. The code here assumes that idle directory file descriptors are
320  *not* closed. This needs to be the case because we need to return
321  non-duplicate directory entries. Anyway, the xrootd readdir protocol
322  is handled internally so directories should never be idle.
323  2. The code here assumes that directory file descriptors are never
324  shared. Hence, no locks need to be obtained. It works out that
325  lock overhead is worse than have a duplicate file descriptor for
326  very short durations.
327 */
328 {
329  EPNAME("readdir");
330  int retc;
331 
332 // Check if this directory is actually open
333 //
334  if (!dp) {XrdOfsFS->Emsg(epname, error, EBADF, "read directory");
335  return 0;
336  }
337 
338 // Check if we are at EOF (once there we stay there)
339 //
340  if (atEOF) return 0;
341 
342 // Read the next directory entry
343 //
344  if ((retc = dp->Readdir(dname, sizeof(dname))) < 0)
345  {std::string eText;
346  const char* etP = 0;
347  if (XrdOfsFS->tryXERT && dp->getErrMsg(eText)) etP = eText.c_str();
348  XrdOfsFS->Emsg(epname, error, retc, "read directory", fname, etP);
349  return 0;
350  }
351 
352 // Check if we have reached end of file
353 //
354  if (!*dname)
355  {atEOF = 1;
356  error.clear();
357  XTRACE(readdir, fname, "<eof>");
358  return 0;
359  }
360 
361 // Return the actual entry
362 //
364  return (const char *)(dname);
365 }
366 
367 /******************************************************************************/
368 /* c l o s e */
369 /******************************************************************************/
370 
372 /*
373  Function: Close the directory object.
374 
375  Input: n/a
376 
377  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
378 
379  Notes: 1. The code here assumes that directory file descriptors are never
380  shared. Hence, no locks need to be obtained. It works out that
381  lock overhead is worse than have a duplicate file descriptor for
382  very short durations.
383 */
384 {
385  EPNAME("closedir");
386  int retc;
387 
388 // Check if this directory is actually open
389 //
390  if (!dp) {XrdOfsFS->Emsg(epname, error, EBADF, "close directory");
391  return SFS_ERROR;
392  }
393  XTRACE(closedir, fname, "");
394 
395 // Close this directory
396 //
397  if ((retc = dp->Close()))
398  {std::string eText;
399  const char* etP = 0;
400  if (XrdOfsFS->tryXERT && dp->getErrMsg(eText)) etP = eText.c_str();
401  retc = XrdOfsFS->Emsg(epname, error, retc, "close", fname, etP);
402  } else retc = SFS_OK;
403 
404 // All done
405 //
406  delete dp;
407  dp = 0;
408  free(fname);
409  fname = 0;
410  return retc;
411 }
412 
413 /******************************************************************************/
414 /* a u t o S t a t */
415 /******************************************************************************/
416 
418 /*
419  Function: Set stat buffer to automaticaly return stat information
420 
421  Input: Pointer to stat buffer which will be filled in on each
422  nextEntry() and represent stat information for that entry.
423 
424  Output: Upon success, returns zero. Upon error returns SFS_ERROR and sets
425  the error object to contain the reason.
426 
427  Notes: 1. If autoStat() is not supported he caller will need to follow up
428  with a manual stat() call for the full path, a slow and tedious
429  process. The autoStat function significantly reduces overhead by
430  automatically providing stat information for the entry read.
431 */
432 {
433  EPNAME("autoStat");
434  int retc;
435 
436 // Check if this directory is actually open
437 //
438  if (!dp) {XrdOfsFS->Emsg(epname, error, EBADF, "autostat directory");
439  return SFS_ERROR;
440  }
441 
442 // Set the stat buffer in the storage system directory but don't complain.
443 //
444  if ((retc = dp->StatRet(buf))) return retc;
445  return SFS_OK;
446 }
447 
448 /******************************************************************************/
449 /* */
450 /* F i l e O b j e c t I n t e r f a c e s */
451 /* */
452 /******************************************************************************/
453 /******************************************************************************/
454 /* X r d O f s F i l e C o n s t r u c t o r */
455 /******************************************************************************/
456 
457 XrdOfsFile::XrdOfsFile(XrdOucErrInfo &eInfo, const char *user)
458  : XrdSfsFile(eInfo), tident(user ? user : ""),
459  oh(XrdOfs::dummyHandle), myTPC(0), myCKP(0),
460  dorawio(0), viaDel(0), ckpBad(false) {}
461 
462 /******************************************************************************/
463 /* o p e n */
464 /******************************************************************************/
465 
466 int XrdOfsFile::open(const char *path, // In
467  XrdSfsFileOpenMode open_mode, // In
468  mode_t Mode, // In
469  const XrdSecEntity *client, // In
470  const char *info) // In
471 /*
472  Function: Open the file `path' in the mode indicated by `open_mode'.
473 
474  Input: path - The fully qualified name of the file to open.
475  open_mode - One of the following flag values:
476  SFS_O_RDONLY - Open file for reading.
477  SFS_O_WRONLY - Open file for writing.
478  SFS_O_RDWR - Open file for update
479  SFS_O_NOTPC - Disallow TPC opens
480  SFS_O_REPLICA- Open file for replication
481  SFS_O_CREAT - Create the file open in RW mode
482  SFS_O_CREATAT- As above but with colocation.
483  SFS_O_TRUNC - Trunc the file open in RW mode
484  SFS_O_POSC - Presist file on successful close
485  SFS_O_SEQIO - Primarily sequential I/O (e.g. xrdcp)
486  Mode - The Posix access mode bits to be assigned to the file.
487  These bits correspond to the standard Unix permission
488  bits (e.g., 744 == "rwxr--r--"). Additionally, Mode
489  may contain SFS_O_MKPTH to force creation of the full
490  directory path if it does not exist. This parameter is
491  ignored unless open_mode = SFS_O_CREAT.
492  client - Authentication credentials, if any.
493  info - Opaque information to be used as seen fit.
494 
495  Output: Returns SFS_OK upon success, otherwise SFS_ERROR is returned.
496 */
497 {
498  EPNAME("open");
499  static const int crMask = (SFS_O_CREAT | SFS_O_TRUNC);
500  static const int opMask = (SFS_O_RDONLY | SFS_O_WRONLY | SFS_O_RDWR);
501 
502  struct OpenHelper
503  {const char *Path;
504  XrdOfsHandle *hP;
505  XrdOssDF *fP;
506  int poscNum;
507 
508  int OK() {hP = 0; fP = 0; poscNum = 0; return SFS_OK;}
509 
510  OpenHelper(const char *path)
511  : Path(path), hP(0), fP(0), poscNum(0) {}
512 
513  ~OpenHelper()
514  {int retc;
515  if (hP) hP->Retire(retc);
516  if (fP) delete fP;
517  if (poscNum > 0) XrdOfsFS->poscQ->Del(Path, poscNum, 1);
518  }
519  } oP(path);
520 
521  mode_t theMode = (Mode | XrdOfsFS->fMask[0]) & XrdOfsFS->fMask[1];
522  const char *tpcKey;
523  int retc, isPosc = 0, crOpts = 0, isRW = 0, open_flag = 0;
524  int find_flag = open_mode & (SFS_O_NOWAIT | SFS_O_RESET | SFS_O_MULTIW);
525  XrdOucEnv Open_Env(info,0,client);
526 
527 // Trace entry
528 //
529  ZTRACE(open, Xrd::hex1 <<open_mode <<"-" <<Xrd::oct1 <<Mode <<" ("
530  <<Xrd::oct1 <<theMode <<") fn=" <<path);
531 
532 // Verify that this object is not already associated with an open file
533 //
534  XrdOfsFS->ocMutex.Lock();
535  if (oh != XrdOfs::dummyHandle)
536  {XrdOfsFS->ocMutex.UnLock();
537  return XrdOfsFS->Emsg(epname,error,EADDRINUSE,"open file",path);
538  }
539  XrdOfsFS->ocMutex.UnLock();
540 
541 // Handle the open mode options
542 //
543  if (open_mode & crMask)
544  {crOpts = (Mode & SFS_O_MKPTH ? XRDOSS_mkpath : 0);
545  if (XrdOfsFS->poscQ && ((open_mode & SFS_O_POSC) ||
546  XrdOfsFS->poscAuto || Open_Env.Get("ofs.posc")))
547  {isPosc = 1; isRW = XrdOfsHandle::opPC;}
548  else isRW = XrdOfsHandle::opRW;
549  if (open_mode & SFS_O_CREAT)
550  {open_flag = O_RDWR | O_CREAT | O_EXCL;
551  find_flag |= SFS_O_RDWR | SFS_O_CREAT | (open_mode & SFS_O_REPLICA);
552  crOpts |= XRDOSS_new;
553  } else {
554  open_flag |= O_RDWR | O_CREAT | O_TRUNC;
555  find_flag |= SFS_O_RDWR | SFS_O_TRUNC;
556  }
557  }
558  else
559  switch(open_mode & opMask)
560  {case SFS_O_RDONLY: open_flag = O_RDONLY; find_flag |= SFS_O_RDONLY;
561  break;
562  case SFS_O_WRONLY: open_flag = O_WRONLY; find_flag |= SFS_O_WRONLY;
563  isRW = XrdOfsHandle::opRW;
564  if (XrdOfsFS->poscQ && ((open_mode & SFS_O_POSC) ||
565  Open_Env.Get("ofs.posc"))) oP.poscNum = -1;
566  break;
567  case SFS_O_RDWR: open_flag = O_RDWR; find_flag |= SFS_O_RDWR;
568  isRW = XrdOfsHandle::opRW;
569  if (XrdOfsFS->poscQ && ((open_mode & SFS_O_POSC) ||
570  Open_Env.Get("ofs.posc"))) oP.poscNum = -1;
571  break;
572  default: open_flag = O_RDONLY; find_flag |= SFS_O_RDONLY;
573  break;
574  }
575 
576 // Preset TPC handling
577 //
578  tpcKey = Open_Env.Get(XrdOucTPC::tpcKey);
579 
580 // Check if we will be redirecting the tpc request
581 //
582  if (tpcKey && isRW && (XrdOfsFS->Options & XrdOfs::RdrTPC))
583  {const char *dOn = Open_Env.Get(XrdOucTPC::tpcDlgOn);
584  int k = ((dOn && *dOn == '1') || strcmp(tpcKey, "delegate") ? 1 : 0);
585  if (XrdOfsFS->tpcRdrHost[k])
587  return SFS_REDIRECT;
588  }
589  }
590 
591 // If we have a finder object, use it to direct the client. The final
592 // destination will apply the security that is needed
593 //
594  if (XrdOfsFS->Finder && (retc = XrdOfsFS->Finder->Locate(error, path,
595  find_flag, &Open_Env)))
596  return XrdOfsFS->fsError(error, retc);
597 
598 // Preset TPC handling and if not allowed, complain
599 //
600  if (tpcKey && (open_mode & SFS_O_NOTPC))
601  return XrdOfsFS->Emsg(epname, error, EPROTOTYPE, "tpc", path,
602  "+TPC prohibited due to security configuration");
603 
604 // Create the file if so requested o/w try to attach the file
605 //
606  if (open_flag & O_CREAT)
607  {// Apply security, as needed
608  //
609  // If we aren't requesting O_EXCL, one needs AOP_Create
610  bool overwrite_permitted = true;
611  if (!(open_flag & O_EXCL))
612  {if (client && XrdOfsFS->Authorization &&
613  !XrdOfsFS->Authorization->Access(client, path, AOP_Create, &Open_Env))
614  { // We don't have the ability to create a file without O_EXCL. If we have AOP_Excl_Create,
615  // then manipulate the open flags and see if we're successful with it.
616  AUTHORIZE(client,&Open_Env,AOP_Excl_Create,"create",path,error);
617  overwrite_permitted = false;
618  open_flag |= O_EXCL;
619  open_flag &= ~O_TRUNC;
620  }
621  }
622  // If we are in O_EXCL mode, then we accept either AOP_Excl_Create or AOP_Create
623  else if (client && XrdOfsFS->Authorization &&
624  !XrdOfsFS->Authorization->Access(client, path, AOP_Create, &Open_Env))
625  {AUTHORIZE(client,&Open_Env,AOP_Excl_Create,"create",path,error);
626  // In this case, we don't have AOP_Create but we do have AOP_Excl_Create; note that
627  // overwrites are not permitted (this is later used to correct an error code).
628  overwrite_permitted = false;
629  }
630 
631  OOIDENTENV(client, Open_Env);
632 
633  // For ephemeral file, we must enter the file into the queue
634  //
635  if (isPosc)
636  {bool isNew = (open_mode & SFS_O_TRUNC) == 0;
637  if ((oP.poscNum = XrdOfsFS->poscQ->Add(tident, path, isNew)) < 0)
638  return XrdOfsFS->Emsg(epname, error, oP.poscNum, "pcreate", path,
639  "+ofs_open: failed to enter file into posc queue");
640  }
641 
642  // If placement information is present provide a hint to the oss plugin
643  //
644  if ((open_mode & ~SFS_O_CREAT) & SFS_O_CREATAT) crOpts |= XRDOSS_coloc;
645 
646  // Create the file. If ENOTSUP is returned, promote the creation to
647  // the subsequent open. This is to accomodate proxy support.
648  //
649  if ((retc = XrdOfsOss->Create(tident, path, theMode, Open_Env,
650  ((open_flag << 8) | crOpts))))
651  {if (retc > 0) return XrdOfsFS->Stall(error, retc, path);
652  if (retc == -EINPROGRESS)
654  return XrdOfsFS->fsError(error, SFS_STARTED);
655  }
656  if (retc != -ENOTSUP)
657  {// If we tried to overwrite an existing file but do not have the AOP_Create
658  // privilege, then ensure we generate a 'permission denied' instead of 'exists'
659  if ((open_flag & O_EXCL) && retc == -EEXIST && !overwrite_permitted)
660  {retc = -EACCES;}
661  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Removed(path);
662  return XrdOfsFS->Emsg(epname, error, retc, "create", path);
663  }
664  } else {
665  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Added(path, isPosc);
666  open_flag = O_RDWR|O_TRUNC;
667  if (XrdOfsFS->evsObject
668  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Create))
669  {XrdOfsEvsInfo evInfo(tident,path,info,&Open_Env,Mode);
670  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Create, evInfo);
671  }
672  }
673 
674  } else {
675 
676  // Apply security, as needed
677  //
678  if (tpcKey && !isRW)
679  {XrdOfsTPC::Facts Args(client, &error, &Open_Env, tpcKey, path);
680  if ((retc = XrdOfsTPC::Authorize(&myTPC, Args))) return retc;
681  } else {AUTHORIZE(client, &Open_Env, (isRW?AOP_Update:AOP_Read),
682  "open", path, error);
683  }
684  OOIDENTENV(client, Open_Env);
685  }
686 
687 // Get a handle for this file.
688 //
689  if ((retc = XrdOfsHandle::Alloc(path, isRW, &oP.hP)))
690  {if (retc > 0) return XrdOfsFS->Stall(error, retc, path);
691  return XrdOfsFS->Emsg(epname, error, retc, "attach", path);
692  }
693 
694 // If this is a third party copy and we are the destination, then validate
695 // specification at this point and setup to transfer. Note that if the
696 // call fails and auto removal is enabled, the file we created will be deleted.
697 //
698  if (tpcKey && isRW)
699  {char pfnbuff[MAXPATHLEN+8]; const char *pfnP;
700  if (!(pfnP = XrdOfsOss->Lfn2Pfn(path, pfnbuff, MAXPATHLEN, retc)))
701  return XrdOfsFS->Emsg(epname, error, retc, "open", path,
702  "+ofs_open: mapping tpc target lfn to pfn failed");
703  XrdOfsTPC::Facts Args(client, &error, &Open_Env, tpcKey, path, pfnP);
704  if ((retc = XrdOfsTPC::Validate(&myTPC, Args))) return retc;
705  }
706 
707 // Assign/transfer posc ownership. We may need to delay the client if the
708 // file create ownership does not match and this is not a create request.
709 //
710  if (oP.hP->isRW == XrdOfsHandle::opPC)
711  {if (!isRW) return XrdOfsFS->Stall(error, -1, path);
712  if ((retc = oP.hP->PoscSet(tident, oP.poscNum, theMode)))
713  {if (retc > 0) XrdOfsFS->poscQ->Del(path, retc);
714  else return XrdOfsFS->Emsg(epname, error, retc, "access", path,
715  "+ofs_open: posc mode initiation failed");
716  }
717  }
718 
719 // If this is a previously existing handle, we are almost done. If this is
720 // the target of a third party copy request, fail it now. We don't support
721 // multiple writers in tpc mode (this should really never happen).
722 //
723  if (!(oP.hP->Inactive()))
724  {dorawio = (oh->isCompressed && open_mode & SFS_O_RAWIO ? 1 : 0);
725  if (tpcKey && isRW)
726  return XrdOfsFS->Emsg(epname, error, EALREADY, "tpc", path,
727  "+ofs_open: this tpc is already in progress");
728  XrdOfsFS->ocMutex.Lock(); oh = oP.hP; XrdOfsFS->ocMutex.UnLock();
729  FTRACE(open, "attach use=" <<oh->Usage());
730  if (oP.poscNum > 0) XrdOfsFS->poscQ->Commit(path, oP.poscNum);
731  oP.hP->UnLock();
734  if (oP.poscNum > 0) OfsStats.Data.numOpenP++;
736  return oP.OK();
737  }
738 
739 // Get a storage system object
740 //
741  if (!(oP.fP = XrdOfsOss->newFile(tident)))
742  return XrdOfsFS->Emsg(epname, error, ENOMEM, "open", path);
743 
744 // We need to make special provisions for proxy servers in the presence of
745 // the TPC option and possibly cache as it's handled differently in this case.
746 //
747  if (XrdOfsFS->OssIsProxy)
748  {if (myTPC) open_flag |= O_NOFOLLOW;
749  if (error.getUCap() & XrdOucEI::uUrlOK &&
750  error.getUCap() & XrdOucEI::uLclF) open_flag |= O_DIRECT;
751  }
752 
753 // Open the file
754 //
755  if ((retc = oP.fP->Open(path, open_flag, theMode, Open_Env)))
756  {if (retc > 0) return XrdOfsFS->Stall(error, retc, path);
757  if (retc == -EINPROGRESS)
759  return XrdOfsFS->fsError(error, SFS_STARTED);
760  }
761  if (retc == -ETXTBSY) return XrdOfsFS->Stall(error, -1, path);
762  if (retc == -EDESTADDRREQ)
763  {char *url = Open_Env.Get("FileURL");
764  if (url) {error.setErrInfo(-1, url); return SFS_REDIRECT;}
765  }
766  if (XrdOfsFS->Balancer && retc == -ENOENT)
767  XrdOfsFS->Balancer->Removed(path);
768  const char* etP = 0;
769  std::string eText;
770  if (XrdOfsFS->tryXERT && oP.fP->getErrMsg(eText)) etP = eText.c_str();
771  return XrdOfsFS->Emsg(epname, error, retc, "open", path, etP);
772  }
773 
774 // Verify that we can actually use this file
775 //
776  if (oP.poscNum > 0)
777  {if ((retc = oP.fP->Fchmod(static_cast<mode_t>(theMode|XRDSFS_POSCPEND))))
778  return XrdOfsFS->Emsg(epname, error, retc, "fchmod", path,
779  "+ofs_open: POSC file designation failed");
780  XrdOfsFS->poscQ->Commit(path, oP.poscNum);
781  }
782 
783 // Set compression values and activate the handle
784 //
785  if (oP.fP->isCompressed() > 0)
786  {oP.hP->isCompressed = 1;
787  dorawio = (open_mode & SFS_O_RAWIO ? 1 : 0);
788  }
789  oP.hP->Activate(oP.fP);
790  oP.hP->UnLock();
791 
792 // If this is being opened for sequential I/O advise the filesystem about it.
793 //
794 #if defined(__linux__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
795  if (!(XrdOfsFS->OssIsProxy) && open_mode & SFS_O_SEQIO)
796  {static RAtomic_int fadFails(0);
797  int theFD = oP.fP->getFD();
798  if (theFD >= 0 && fadFails < 4096)
799  if (posix_fadvise(theFD, 0, 0, POSIX_FADV_SEQUENTIAL) < 0)
800  {OfsEroute.Emsg(epname, errno, "fadvise for sequential I/O.");
801  fadFails++;
802  }
803  }
804 #endif
805 
806 // Send an open event if we must
807 //
808  if (XrdOfsFS->evsObject)
809  {XrdOfsEvs::Event theEvent = (isRW ? XrdOfsEvs::Openw : XrdOfsEvs::Openr);
810  if (XrdOfsFS->evsObject->Enabled(theEvent))
811  {XrdOfsEvsInfo evInfo(tident, path, info, &Open_Env);
812  XrdOfsFS->evsObject->Notify(theEvent, evInfo);
813  }
814  }
815 
816 // Maintain statistics
817 //
820  if (oP.poscNum > 0) OfsStats.Data.numOpenP++;
822 
823 // All done
824 //
825  XrdOfsFS->ocMutex.Lock(); oh = oP.hP; XrdOfsFS->ocMutex.UnLock();
826  return oP.OK();
827 }
828 
829 /******************************************************************************/
830 /* C l o n e */
831 /******************************************************************************/
832 /*
833  Function: Clone the file object from another file object.
834 
835  Input: n/a
836 
837  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
838 */
839 
841 {
842  EPNAME("Clone");
843  XrdOfsFile& ofsFile = static_cast<XrdOfsFile&>(srcFile);
844  int rc = oh->Select().Clone(ofsFile.oh->Select());
845 
846  if (rc < 0)
847  {char etxt[4096];
848  snprintf(etxt,sizeof(etxt),"%s from %s",oh->Name(),ofsFile.oh->Name());
849  return XrdOfsFS->Emsg(epname, error, rc, "clone", etxt);
850  }
851 
852  return SFS_OK;
853 }
854 
855 /******************************************************************************/
856 
857 int XrdOfsFile::Clone(const std::vector<XrdOucCloneSeg> &cVec)
858 {
859  EPNAME("Clone");
860  int rc = oh->Select().Clone(cVec);
861 
862  if (rc < 0)
863  {char etxt[4096];
864  snprintf(etxt,sizeof(etxt),"%s from file ranges",oh->Name());
865  return XrdOfsFS->Emsg(epname, error, rc, "clone", etxt);
866  }
867 
868  return SFS_OK;
869 }
870 
871 /******************************************************************************/
872 /* c l o s e */
873 /******************************************************************************/
874 
875 int XrdOfsFile::close() // In
876 /*
877  Function: Close the file object.
878 
879  Input: n/a
880 
881  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
882 */
883 {
884  EPNAME("close");
885 
886  class CloseFH : public XrdOfsHanCB
887  {public: void Retired(XrdOfsHandle *hP) {XrdOfsFS->Unpersist(hP);}};
888  static XrdOfsHanCB *hCB = static_cast<XrdOfsHanCB *>(new CloseFH);
889 
890  XrdOfsHandle *hP;
891  int poscNum, retc, cRetc = 0;
892  short theMode;
893 
894 // Trace the call
895 //
896  FTRACE(close, "use=" <<oh->Usage()); // Unreliable trace, no origin lock
897 
898 // Verify the handle (we briefly maintain a global lock)
899 //
900  XrdOfsFS->ocMutex.Lock();
901  if (oh == XrdOfs::dummyHandle)
902  {XrdOfsFS->ocMutex.UnLock(); return SFS_OK;}
903  if ((oh->Inactive()))
904  {XrdOfsFS->ocMutex.UnLock();
905  return XrdOfsFS->Emsg(epname, error, EBADF, "close file");
906  }
907  hP = oh; oh = XrdOfs::dummyHandle;
908  XrdOfsFS->ocMutex.UnLock();
909  hP->Lock();
910 
911 // Delete the tpc object, if any
912 //
913  if (myTPC) {myTPC->Del(); myTPC = 0;}
914 
915 // Maintain statistics
916 //
918  if (!(hP->isRW)) OfsStats.Data.numOpenR--;
919  else {OfsStats.Data.numOpenW--;
921  }
923 
924 // If this file was tagged as a POSC then we need to make sure it will persist
925 // Note that we unpersist the file immediately when it's inactive or if no hold
926 // time is allowed. Also, close events occur only for active handles. If the
927 // entry was via delete then we ignore the close return code as there is no
928 // one to handle it on the other side.
929 //
930  if ((poscNum = hP->PoscGet(theMode, !viaDel)))
931  {if (viaDel)
932  {if (hP->Inactive() || !XrdOfsFS->poscHold)
933  {XrdOfsFS->Unpersist(hP, !hP->Inactive()); hP->Retire(cRetc);}
934  else hP->Retire(hCB, XrdOfsFS->poscHold);
935  return SFS_OK;
936  }
937  if ((retc = hP->Select().Fchmod(theMode)))
938  XrdOfsFS->Emsg(epname, error, retc, "fchmod", hP->Name());
939  else {XrdOfsFS->poscQ->Del(hP->Name(), poscNum);
940  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Added(hP->Name());
941  }
942  }
943 
944 // Handle any oustanding checkpoint
945 //
946  if (myCKP)
947  {retc = myCKP->Restore();
948  if (retc) XrdOfsFS->Emsg(epname,error,retc,"restore chkpnt",hP->Name());
949  myCKP->Finished();
950  myCKP = 0;
951  }
952 
953 // We need to handle the cunudrum that an event may have to be sent upon
954 // the final close. However, that would cause the path name to be destroyed.
955 // So, we have two modes of logic where we copy out the pathname if a final
956 // close actually occurs. The path is not copied if it's not final and we
957 // don't bother with any of it if we need not generate an event.
958 //
959  if (XrdOfsFS->evsObject && tident
960  && XrdOfsFS->evsObject->Enabled(hP->isRW ? XrdOfsEvs::Closew
962  {long long FSize, *retsz;
963  char pathbuff[MAXPATHLEN+8];
964  XrdOfsEvs::Event theEvent;
965  if (hP->isRW) {theEvent = XrdOfsEvs::Closew; retsz = &FSize;}
966  else { theEvent = XrdOfsEvs::Closer; retsz = 0; FSize=0;}
967  if (!(hP->Retire(cRetc, retsz, pathbuff, sizeof(pathbuff))))
968  {XrdOfsEvsInfo evInfo(tident, pathbuff, "" , 0, 0, FSize);
969  XrdOfsFS->evsObject->Notify(theEvent, evInfo);
970  }
971  } else hP->Retire(cRetc);
972 
973 // All done
974 //
975  return (cRetc ? XrdOfsFS->Emsg(epname, error, cRetc, "close file") : SFS_OK);
976 }
977 
978 /******************************************************************************/
979 /* c h e c k p o i n t */
980 /******************************************************************************/
981 
982 int XrdOfsFile::checkpoint(XrdSfsFile::cpAct act, struct iov *range, int n)
983 {
984  EPNAME("chkpnt");
985  const char *ckpName;
986  int rc;
987  bool readok;
988 
989 // Make sure we are active
990 //
991  if (oh->Inactive()) return XrdOfsFS->Emsg(epname, error, EBADF,
992  "handle checkpoint", (const char *)0);
993 
994 // If checkpointing is disabled, the don't accept this request.
995 //
996  if (!XrdOfsConfigCP::Enabled) return XrdOfsFS->Emsg(epname, error, ENOTSUP,
997  "handle disabled checkpoint", (const char *)0);
998 
999 // If this checkpoint is bad then only a delete, query or restore is allowed.
1000 //
1001  if (ckpBad && (act == XrdSfsFile::cpTrunc || act == XrdSfsFile::cpWrite))
1002  return XrdOfsFS->Emsg(epname, error, EIDRM, "extend checkpoint "
1003  "(only delete or restore possible) for", oh->Name());
1004 
1005 // Handle the request
1006 //
1007  switch(act)
1008  {case XrdSfsFile::cpCreate:
1009  ckpName = "create checkpoint for";
1010  if ((rc = CreateCKP())) return rc;
1011  if ((rc = myCKP->Create())) {myCKP->Finished(); myCKP = 0;}
1012  break;
1013  case XrdSfsFile::cpDelete:
1014  ckpName = "delete checkpoint for";
1015  if (!myCKP) rc = ENOENT;
1016  else {rc = myCKP->Delete();
1017  myCKP->Finished();
1018  myCKP = 0;
1019  ckpBad = false;
1020  }
1021  break;
1022  case XrdSfsFile::cpQuery:
1023  ckpName = "query checkpoint for";
1024  if (!range || n <= 0)
1025  return XrdOfsFS->Emsg(epname, error, EINVAL,
1026  "query checkpoint limits for", oh->Name());
1027  rc = (myCKP ? myCKP->Query(*range) : ENOENT);
1028  break;
1029  case XrdSfsFile::cpRestore:
1030  ckpName = "restore checkpoint for";
1031  if (!myCKP) rc = ENOENT;
1032  else {if (!(rc = myCKP->Restore(&readok)))
1033  {myCKP->Finished();
1034  myCKP = 0;
1035  ckpBad = false;
1036  } else {
1037  if (!(oh->Select().DFType() & XrdOssDF::DF_isProxy))
1038  oh->Suppress((readok ? 0 : -EDOM));
1039  ckpBad = true;
1040  }
1041  }
1042  break;
1043  case XrdSfsFile::cpTrunc:
1044  ckpName = "checkpoint truncate";
1045  if (!range) rc = EINVAL;
1046  else if (!myCKP) rc = ENOENT;
1047  else if ((rc = myCKP->Truncate(range))) ckpBad = true;
1048  break;
1049  case XrdSfsFile::cpWrite:
1050  ckpName = "checkpoint write";
1051  if (!range || n <= 0) rc = EINVAL;
1052  else if (!myCKP) rc = ENOENT;
1053  else if ((rc = myCKP->Write(range, n))) ckpBad = true;
1054  break;
1055 
1056  default: return XrdOfsFS->Emsg(epname, error, EINVAL,
1057  "decode checkpoint request for", oh->Name());
1058  };
1059 
1060 // Complete as needed
1061 //
1062  if (rc) return XrdOfsFS->Emsg(epname, error, rc, ckpName, oh->Name());
1063 
1064 // Trace success and return
1065 //
1066  FTRACE(chkpnt, ckpName);
1067  return SFS_OK;
1068 }
1069 
1070 /******************************************************************************/
1071 /* Private: C r e a t e C K P */
1072 /******************************************************************************/
1073 
1074 int XrdOfsFile::CreateCKP()
1075 {
1076 
1077 // Verify that a checkpoint does not exist
1078 //
1079  if (myCKP) return XrdOfsFS->Emsg("CreateCKP", error, EEXIST,
1080  "create checkpoint for", oh->Name());
1081 
1082 // Verify that this file is open r/w mode
1083 //
1084  if (!(oh->isRW)) return XrdOfsFS->Emsg("CreateCKP", error, ENOTTY,
1085  "create checkpoint for R/O", oh->Name(),
1086  "+ofs_CreateCKP: file is not open in r/w mode");
1087 
1088 // POSC and checkpoints are mutally exclusive
1089 //
1090  if (oh->isRW == XrdOfsHandle::opPC)
1091  return XrdOfsFS->Emsg("CreateCKP", error, ENOTTY,
1092  "create checkpoint for POSC file", oh->Name(),
1093  "+ofs_CreateCKP: POSC file cannot be checkpointed");
1094 
1095 // Get a new checkpoint object
1096 //
1097  if (XrdOfsFS->OssIsProxy)
1098  {char *resp;
1099  int rc = oh->Select().Fctl(XrdOssDF::Fctl_ckpObj, 0, 0, &resp);
1100  if (rc) return XrdOfsFS->Emsg("CreateCKP", error, rc,
1101  "create proxy checkpoint");
1102  myCKP = (XrdOucChkPnt *)resp;
1103  } else myCKP = new XrdOfsChkPnt(oh->Select(), oh->Name());
1104 
1105 // All done
1106 //
1107  return 0;
1108 }
1109 
1110 /******************************************************************************/
1111 /* f c t l */
1112 /******************************************************************************/
1113 
1114 int XrdOfsFile::fctl(const int cmd,
1115  const char *args,
1116  XrdOucErrInfo &out_error)
1117 {
1118 // See if we can do this
1119 //
1120  if (cmd == SFS_FCTL_GETFD)
1121  {out_error.setErrCode(oh->Select().getFD());
1122  return SFS_OK;
1123  }
1124 
1125 // We don't support this
1126 //
1127  out_error.setErrInfo(ENOTSUP, "fctl operation not supported");
1128 
1129 // Return
1130 //
1131  return SFS_ERROR;
1132 }
1133 
1134 /******************************************************************************/
1135 
1136 int XrdOfsFile::fctl(const int cmd, int alen, const char *args,
1137  const XrdSecEntity *client)
1138 { // 12345678901234
1139  EPNAME("fctl");
1140  static const char *fctlArg = "ofs.tpc cancel";
1141  static const int fctlAsz = 15;
1142 
1143 // For QFINFO we simply pass it to the Oss layer
1144 //
1145  if (cmd == SFS_FCTL_QFINFO)
1146  {char* resp = 0;;
1147  int rc = oh->Select().Fctl(XrdOssDF::Fctl_QFinfo, alen, args, &resp);
1148  if (rc < 0)
1149  {if (resp) delete[] resp;
1150  return XrdOfsFS->Emsg(epname,error,rc,"fctl",oh,false,false);
1151  }
1152  if (resp)
1153  {if ((rc = strlen(resp)))
1154  {error.setErrInfo(rc, resp);
1155  delete[] resp;
1156  return SFS_DATA;
1157  }
1158  delete[] resp;
1159  }
1160  return SFS_OK;
1161  }
1162 
1163 // See if the is a tpc cancellation (the only thing we support here)
1164 //
1165  if (cmd != SFS_FCTL_SPEC1 || !args || alen < fctlAsz || strcmp(fctlArg,args))
1166  return XrdOfsFS->FSctl(*this, cmd, alen, args, client);
1167 
1168 // Check if we have a tpc operation in progress
1169 //
1170  if (!myTPC)
1171  {error.setErrInfo(ESRCH, "tpc operation not found");
1172  return SFS_ERROR;
1173  }
1174 
1175 // Cancel the tpc
1176 //
1177  myTPC->Del();
1178  myTPC = 0;
1179  return SFS_OK;
1180 }
1181 
1182 /******************************************************************************/
1183 /* p g R e a d */
1184 /******************************************************************************/
1185 
1187  char *buffer,
1188  XrdSfsXferSize rdlen,
1189  uint32_t *csvec,
1190  uint64_t opts)
1191 {
1192  EPNAME("pgRead");
1193  XrdSfsXferSize nbytes;
1194  uint64_t pgOpts;
1195 
1196 // If the oss plugin does not support pgRead and we doing rawio then simulate
1197 // the pgread. As this is relatively common we skip the vtable. This means
1198 // this class cannot be a inherited to override the read() method.
1199 //
1200  if (!XrdOfsFS->OssHasPGrw || dorawio)
1201  {if ((nbytes = XrdOfsFile::read(offset, buffer, rdlen)) > 0)
1202  XrdOucPgrwUtils::csCalc(buffer, offset, nbytes, csvec);
1203  return nbytes;
1204  }
1205 
1206 // Perform required tracing
1207 //
1208  FTRACE(read, rdlen <<"@" <<offset);
1209 
1210 // Make sure the offset is not too large
1211 //
1212 #if _FILE_OFFSET_BITS!=64
1213  if (offset > 0x000000007fffffff)
1214  return XrdOfsFS->Emsg(epname, error, EFBIG, "pgRead", oh->Name());
1215 #endif
1216 
1217 // Pass through any flags of interest
1218 //
1219  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1220  else pgOpts = 0;
1221 
1222 // Now read the actual number of bytes
1223 //
1224  nbytes = (XrdSfsXferSize)(oh->Select().pgRead((void *)buffer,
1225  (off_t)offset, (size_t)rdlen, csvec, pgOpts));
1226  if (nbytes < 0)
1227  return XrdOfsFS->Emsg(epname,error,(int)nbytes,"pgRead",oh,false,false);
1228 
1229 // Return number of bytes read
1230 //
1231  return nbytes;
1232 }
1233 
1234 /******************************************************************************/
1235 
1237 {
1238  EPNAME("aiopgread");
1239  uint64_t pgOpts;
1240  int rc;
1241 
1242 // If the oss plugin does not support pgRead or if we are doing rawio or the
1243 // file is compressed then revert to using a standard async read. Note that
1244 // the standard async read will generate checksums if a vector is present.
1245 // Note: we set cksVec in the request to nil to indicate simulation!
1246 //
1247  if (!XrdOfsFS->OssHasPGrw || dorawio || oh->isCompressed)
1248  {aioparm->cksVec = 0;
1249  return XrdOfsFile::read(aioparm);
1250  }
1251 
1252 // Perform required tracing
1253 //
1254  FTRACE(aio, aioparm->sfsAio.aio_nbytes <<"@" <<aioparm->sfsAio.aio_offset);
1255 
1256 // Make sure the offset is not too large
1257 //
1258 #if _FILE_OFFSET_BITS!=64
1259  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1260  return XrdOfsFS->Emsg(epname,error,-EFBIG,"pgRead",oh->Name(),0,false);
1261 #endif
1262 
1263 // Pass through any flags of interest
1264 //
1265  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1266  else pgOpts = 0;
1267 
1268 // Issue the read. Only true errors are returned here.
1269 //
1270  if ((rc = oh->Select().pgRead(aioparm, pgOpts)) < 0)
1271  return XrdOfsFS->Emsg(epname, error, rc, "pgRead", oh, false, false);
1272 
1273 // All done
1274 //
1275  return SFS_OK;
1276 }
1277 
1278 /******************************************************************************/
1279 /* p g W r i t e */
1280 /******************************************************************************/
1281 
1283  char *buffer,
1284  XrdSfsXferSize wrlen,
1285  uint32_t *csvec,
1286  uint64_t opts)
1287 {
1288  EPNAME("pgWrite");
1289  XrdSfsXferSize nbytes;
1290  uint64_t pgOpts;
1291 
1292 // If the oss plugin does not support pgWrite revert to using a standard write.
1293 //
1294  if (!XrdOfsFS->OssHasPGrw)
1295  {if ((opts & XrdSfsFile::Verify)
1296  && !VerPgw(buffer, offset, wrlen, csvec, oh, error)) return SFS_ERROR;
1297  return XrdOfsFile::write(offset, buffer, wrlen);
1298  }
1299 
1300 // Perform any required tracing
1301 //
1302  FTRACE(write, wrlen <<"@" <<offset);
1303 
1304 // Make sure the offset is not too large
1305 //
1306 #if _FILE_OFFSET_BITS!=64
1307  if (offset > 0x000000007fffffff)
1308  return XrdOfsFS->Emsg(epname, error, -EFBIG, "pgwrite", oh, true, false);
1309 #endif
1310 
1311 // Silly Castor stuff
1312 //
1313  if (XrdOfsFS->evsObject && !(oh->isChanged)
1314  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1315 
1316 // Pass through any flags of interest
1317 //
1318  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1319  else pgOpts = 0;
1320 
1321 // Write the requested bytes
1322 //
1323  oh->isPending = 1;
1324  nbytes = (XrdSfsXferSize)(oh->Select().pgWrite((void *)buffer,
1325  (off_t)offset, (size_t)wrlen, csvec, pgOpts));
1326  if (nbytes < 0)
1327  return XrdOfsFS->Emsg(epname,error,(int)nbytes,"pgwrite",oh,true,false);
1328 
1329 // Return number of bytes written
1330 //
1331  return nbytes;
1332 }
1333 
1334 /******************************************************************************/
1335 
1337 {
1338  EPNAME("aiopgWrite");
1339  uint64_t pgOpts;
1340  int rc;
1341 
1342 // If the oss plugin does not support pgWrite revert to using a standard write.
1343 //
1344  if (!XrdOfsFS->OssHasPGrw)
1345  {if ((opts & XrdSfsFile::Verify)
1346  && !VerPgw((char *)aioparm->sfsAio.aio_buf,
1347  aioparm->sfsAio.aio_offset,
1348  aioparm->sfsAio.aio_nbytes,
1349  aioparm->cksVec, oh, error)) return SFS_ERROR;
1350  return XrdOfsFile::write(aioparm);
1351  }
1352 
1353 // If this is a POSC file, we must convert the async call to a sync call as we
1354 // must trap any errors that unpersist the file. We can't do that via aio i/f.
1355 //
1356  if (oh->isRW == XrdOfsHandle::opPC)
1357  {aioparm->Result = XrdOfsFile::pgWrite(aioparm->sfsAio.aio_offset,
1358  (char *)aioparm->sfsAio.aio_buf,
1359  aioparm->sfsAio.aio_nbytes,
1360  aioparm->cksVec, opts);
1361  aioparm->doneWrite();
1362  return SFS_OK;
1363  }
1364 
1365 // Perform any required tracing
1366 //
1367  FTRACE(aio, aioparm->sfsAio.aio_nbytes <<"@" <<aioparm->sfsAio.aio_offset);
1368 
1369 // Make sure the offset is not too large
1370 //
1371 #if _FILE_OFFSET_BITS!=64
1372  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1373  return XrdOfsFS->Emsg(epname, error, -EFBIG, "pgwrite", oh, true, false);
1374 #endif
1375 
1376 // Silly Castor stuff
1377 //
1378  if (XrdOfsFS->evsObject && !(oh->isChanged)
1379  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1380 
1381 // Pass through any flags of interest
1382 //
1383  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1384  else pgOpts = 0;
1385 
1386 // Write the requested bytes
1387 //
1388  oh->isPending = 1;
1389  if ((rc = oh->Select().pgWrite(aioparm, pgOpts)) < 0)
1390  return XrdOfsFS->Emsg(epname, error, rc, "pgwrite", oh, true, false);
1391 
1392 // All done
1393 //
1394  return SFS_OK;
1395 }
1396 
1397 /******************************************************************************/
1398 /* r e a d */
1399 /******************************************************************************/
1400 
1402  XrdSfsXferSize blen) // In
1403 /*
1404  Function: Preread `blen' bytes at `offset'
1405 
1406  Input: offset - The absolute byte offset at which to start the read.
1407  blen - The amount to preread.
1408 
1409  Output: Returns SFS_OK upon success and SFS_ERROR o/w.
1410 */
1411 {
1412  EPNAME("read");
1413  int retc;
1414 
1415 // Perform required tracing
1416 //
1417  FTRACE(read, "preread " <<blen <<"@" <<offset);
1418 
1419 // Make sure the offset is not too large
1420 //
1421 #if _FILE_OFFSET_BITS!=64
1422  if (offset > 0x000000007fffffff)
1423  return XrdOfsFS->Emsg(epname,error,-EFBIG,"read",oh->Name(),0,false);
1424 #endif
1425 
1426 // Now preread the actual number of bytes
1427 //
1428  if ((retc = oh->Select().Read((off_t)offset, (size_t)blen)) < 0)
1429  return XrdOfsFS->Emsg(epname, error, (int)retc, "preread", oh, 0, false);
1430 
1431 // Return number of bytes read
1432 //
1433  return retc;
1434 }
1435 
1436 /******************************************************************************/
1437 /* r e a d */
1438 /******************************************************************************/
1439 
1441  char *buff, // Out
1442  XrdSfsXferSize blen) // In
1443 /*
1444  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
1445  number of bytes read.
1446 
1447  Input: offset - The absolute byte offset at which to start the read.
1448  buff - Address of the buffer in which to place the data.
1449  blen - The size of the buffer. This is the maximum number
1450  of bytes that will be read from 'fd'.
1451 
1452  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
1453 */
1454 {
1455  EPNAME("read");
1456  XrdSfsXferSize nbytes;
1457 
1458 // Perform required tracing
1459 //
1460  FTRACE(read, blen <<"@" <<offset);
1461 
1462 // Make sure the offset is not too large
1463 //
1464 #if _FILE_OFFSET_BITS!=64
1465  if (offset > 0x000000007fffffff)
1466  return XrdOfsFS->Emsg(epname,error,-EFBIG,"read",oh->Name(),0,false);
1467 #endif
1468 
1469 // Now read the actual number of bytes
1470 //
1471  nbytes = (dorawio ?
1472  (XrdSfsXferSize)(oh->Select().ReadRaw((void *)buff,
1473  (off_t)offset, (size_t)blen))
1474  : (XrdSfsXferSize)(oh->Select().Read((void *)buff,
1475  (off_t)offset, (size_t)blen)));
1476  if (nbytes < 0)
1477  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "read", oh, 0, false);
1478 
1479 // Return number of bytes read
1480 //
1481  return nbytes;
1482 }
1483 
1484 /******************************************************************************/
1485 /* r e a d v */
1486 /******************************************************************************/
1487 
1489  int readCount) // In
1490 /*
1491  Function: Perform all the reads specified in the readV vector.
1492 
1493  Input: readV - A description of the reads to perform; includes the
1494  absolute offset, the size of the read, and the buffer
1495  to place the data into.
1496  readCount - The size of the readV vector.
1497 
1498  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
1499  If the number of bytes read is less than requested, it is considered
1500  an error.
1501 */
1502 {
1503  EPNAME("readv");
1504 
1505  XrdSfsXferSize nbytes = oh->Select().ReadV(readV, readCount);
1506  if (nbytes < 0)
1507  return XrdOfsFS->Emsg(epname,error,(int)nbytes,"readv",oh,false,false);
1508 
1509  return nbytes;
1510 
1511 }
1512 
1513 /******************************************************************************/
1514 /* r e a d A I O */
1515 /******************************************************************************/
1516 
1517 /*
1518  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
1519  number of bytes read using asynchronous I/O, if possible.
1520 
1521  Output: Returns the 0 if successfullt queued, otherwise returns an error.
1522  The underlying implementation will convert the request to
1523  synchronous I/O is async mode is not possible.
1524 */
1525 
1527 {
1528  EPNAME("aioread");
1529  int rc;
1530 
1531 // Async mode for compressed files is not supported.
1532 //
1533  if (oh->isCompressed)
1534  {aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
1535  (char *)aiop->sfsAio.aio_buf,
1537  aiop->doneRead();
1538  return 0;
1539  }
1540 
1541 // Perform required tracing
1542 //
1543  FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
1544 
1545 // Make sure the offset is not too large
1546 //
1547 #if _FILE_OFFSET_BITS!=64
1548  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1549  return XrdOfsFS->Emsg(epname,error,-EFBIG,"read",oh->Name(),0,false);
1550 #endif
1551 
1552 // Issue the read. Only true errors are returned here.
1553 //
1554  if ((rc = oh->Select().Read(aiop)) < 0)
1555  return XrdOfsFS->Emsg(epname, error, rc, "read", oh, false, false);
1556 
1557 // All done
1558 //
1559  return SFS_OK;
1560 }
1561 
1562 /******************************************************************************/
1563 /* w r i t e */
1564 /******************************************************************************/
1565 
1567  const char *buff, // Out
1568  XrdSfsXferSize blen) // In
1569 /*
1570  Function: Write `blen' bytes at `offset' from 'buff' and return the actual
1571  number of bytes written.
1572 
1573  Input: offset - The absolute byte offset at which to start the write.
1574  buff - Address of the buffer from which to get the data.
1575  blen - The size of the buffer. This is the maximum number
1576  of bytes that will be written to 'fd'.
1577 
1578  Output: Returns the number of bytes written upon success and SFS_ERROR o/w.
1579 
1580  Notes: An error return may be delayed until the next write(), close(), or
1581  sync() call.
1582 */
1583 {
1584  EPNAME("write");
1585  XrdSfsXferSize nbytes;
1586 
1587 // Perform any required tracing
1588 //
1589  FTRACE(write, blen <<"@" <<offset);
1590 
1591 // Make sure the offset is not too large
1592 //
1593 #if _FILE_OFFSET_BITS!=64
1594  if (offset > 0x000000007fffffff)
1595  return XrdOfsFS->Emsg(epname,error,-EFBIG,"write",oh,true,false);
1596 #endif
1597 
1598 // Silly Castor stuff
1599 //
1600  if (XrdOfsFS->evsObject && !(oh->isChanged)
1601  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1602 
1603 // Write the requested bytes
1604 //
1605  oh->isPending = 1;
1606  nbytes = (XrdSfsXferSize)(oh->Select().Write((const void *)buff,
1607  (off_t)offset, (size_t)blen));
1608  if (nbytes < 0)
1609  return XrdOfsFS->Emsg(epname,error,(int)nbytes,"write",oh,true,false);
1610 
1611 // Return number of bytes written
1612 //
1613  return nbytes;
1614 }
1615 
1616 /******************************************************************************/
1617 /* w r i t e A I O */
1618 /******************************************************************************/
1619 
1620 // For now, this reverts to synchronous I/O
1621 //
1623 {
1624  EPNAME("aiowrite");
1625  int rc;
1626 
1627 // Perform any required tracing
1628 //
1629  FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
1630 
1631 // If this is a POSC file, we must convert the async call to a sync call as we
1632 // must trap any errors that unpersist the file. We can't do that via aio i/f.
1633 //
1634  if (oh->isRW == XrdOfsHandle::opPC)
1635  {aiop->Result = this->write(aiop->sfsAio.aio_offset,
1636  (const char *)aiop->sfsAio.aio_buf,
1637  aiop->sfsAio.aio_nbytes);
1638  aiop->doneWrite();
1639  return 0;
1640  }
1641 
1642 // Make sure the offset is not too large
1643 //
1644 #if _FILE_OFFSET_BITS!=64
1645  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1646  return XrdOfsFS->Emsg(epname, error, -EFBIG, "write", oh, true, false);
1647 #endif
1648 
1649 // Silly Castor stuff
1650 //
1651  if (XrdOfsFS->evsObject && !(oh->isChanged)
1652  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1653 
1654 // Write the requested bytes
1655 //
1656  oh->isPending = 1;
1657  if ((rc = oh->Select().Write(aiop)) < 0)
1658  return XrdOfsFS->Emsg(epname, error, rc, "write", oh, true, false);
1659 
1660 // All done
1661 //
1662  return SFS_OK;
1663 }
1664 
1665 /******************************************************************************/
1666 /* g e t M m a p */
1667 /******************************************************************************/
1668 
1669 int XrdOfsFile::getMmap(void **Addr, off_t &Size) // Out
1670 /*
1671  Function: Return memory mapping for file, if any.
1672 
1673  Output: Addr - Address of memory location
1674  Size - Size of the file or zero if not memory mapped.
1675  Returns SFS_OK upon success and SFS_ERROR upon failure.
1676 */
1677 {
1678 
1679 // Perform the function
1680 //
1681  Size = oh->Select().getMmap(Addr);
1682 
1683  return SFS_OK;
1684 }
1685 
1686 /******************************************************************************/
1687 /* s t a t */
1688 /******************************************************************************/
1689 
1690 int XrdOfsFile::stat(struct stat *buf) // Out
1691 /*
1692  Function: Return file status information
1693 
1694  Input: buf - The stat structiure to hold the results
1695 
1696  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1697 */
1698 {
1699  EPNAME("fstat");
1700  int retc;
1701 
1702 // Perform any required tracing
1703 //
1704  FTRACE(stat, "");
1705 
1706 // Perform the function
1707 //
1708  if ((retc = oh->Select().Fstat(buf)) < 0)
1709  return XrdOfsFS->Emsg(epname,error,retc,"get state for",oh);
1710 
1711  return SFS_OK;
1712 }
1713 
1714 /******************************************************************************/
1715 /* s y n c */
1716 /******************************************************************************/
1717 
1718 int XrdOfsFile::sync() // In
1719 /*
1720  Function: Commit all unwritten bytes to physical media.
1721 
1722  Input: n/a
1723 
1724  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1725 */
1726 {
1727  EPNAME("sync");
1728  int retc;
1729 
1730 // Perform any required tracing
1731 //
1732  FTRACE(sync, "");
1733 
1734 // If we have a tpc object hanging about, we need to dispatch that first
1735 //
1736  if (myTPC && (retc = myTPC->Sync(&error))) return retc;
1737 
1738 // We can test the pendio flag w/o a lock because the person doing this
1739 // sync must have done the previous write. Causality is the synchronizer.
1740 //
1741  if (!(oh->isPending)) return SFS_OK;
1742 
1743 // We can also skip the sync if the file is closed. However, we need a file
1744 // object lock in order to test the flag. We can also reset the PENDIO flag.
1745 //
1746  oh->Lock();
1747  oh->isPending = 0;
1748  oh->UnLock();
1749 
1750 // Perform the function
1751 //
1752  if ((retc = oh->Select().Fsync()))
1753  {oh->isPending = 1;
1754  return XrdOfsFS->Emsg(epname, error, retc, "synchronize", oh, true);
1755  }
1756 
1757 // Indicate all went well
1758 //
1759  return SFS_OK;
1760 }
1761 
1762 /******************************************************************************/
1763 /* s y n c A I O */
1764 /******************************************************************************/
1765 
1766 // For now, reverts to synchronous case. This must also be the case for POSC!
1767 //
1769 {
1770  aiop->Result = this->sync();
1771  aiop->doneWrite();
1772  return 0;
1773 }
1774 
1775 /******************************************************************************/
1776 /* t r u n c a t e */
1777 /******************************************************************************/
1778 
1780 /*
1781  Function: Set the length of the file object to 'flen' bytes.
1782 
1783  Input: flen - The new size of the file.
1784 
1785  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1786 
1787  Notes: If 'flen' is smaller than the current size of the file, the file
1788  is made smaller and the data past 'flen' is discarded. If 'flen'
1789  is larger than the current size of the file, a hole is created
1790  (i.e., the file is logically extended by filling the extra bytes
1791  with zeroes).
1792 */
1793 {
1794  EPNAME("trunc");
1795  int retc;
1796 
1797 // Lock the file handle and perform any tracing
1798 //
1799  FTRACE(truncate, "len=" <<flen);
1800 
1801 // Make sure the offset is not too large
1802 //
1803  if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
1804  return XrdOfsFS->Emsg(epname, error, EFBIG, "truncate", oh, true);
1805 
1806 // Silly Castor stuff
1807 //
1808  if (XrdOfsFS->evsObject && !(oh->isChanged)
1809  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1810 
1811 // Perform the function
1812 //
1813  oh->isPending = 1;
1814  if ((retc = oh->Select().Ftruncate(flen)))
1815  return XrdOfsFS->Emsg(epname, error, retc, "truncate", oh, true);
1816 
1817 // Indicate Success
1818 //
1819  return SFS_OK;
1820 }
1821 
1822 /******************************************************************************/
1823 /* g e t C X i n f o */
1824 /******************************************************************************/
1825 
1826 int XrdOfsFile::getCXinfo(char cxtype[4], int &cxrsz)
1827 /*
1828  Function: Set the length of the file object to 'flen' bytes.
1829 
1830  Input: n/a
1831 
1832  Output: cxtype - Compression algorithm code
1833  cxrsz - Compression region size
1834 
1835  Returns SFS_OK upon success and SFS_ERROR upon failure.
1836 */
1837 {
1838 
1839 // Copy out the info
1840 //
1841  cxrsz = oh->Select().isCompressed(cxtype);
1842  return SFS_OK;
1843 }
1844 
1845 /******************************************************************************/
1846 /* P r i v a t e F i l e M e t h o d s */
1847 /******************************************************************************/
1848 /******************************************************************************/
1849 /* protected G e n F W E v e n t */
1850 /******************************************************************************/
1851 
1852 void XrdOfsFile::GenFWEvent()
1853 {
1854  int first_write;
1855 
1856 // This silly code is to generate a 1st write event which slows things down
1857 // but is needed by the one and only Castor. What a big sigh!
1858 //
1859  oh->Lock();
1860  if ((first_write = !(oh->isChanged))) oh->isChanged = 1;
1861  oh->UnLock();
1862  if (first_write)
1863  {XrdOfsEvsInfo evInfo(tident, oh->Name());
1864  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Fwrite, evInfo);
1865  }
1866 }
1867 
1868 /******************************************************************************/
1869 /* */
1870 /* 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 */
1871 /* */
1872 /******************************************************************************/
1873 /******************************************************************************/
1874 /* c h k s u m */
1875 /******************************************************************************/
1876 
1877 int XrdOfs::chksum( csFunc Func, // In
1878  const char *csName, // In
1879  const char *Path, // In
1880  XrdOucErrInfo &einfo, // Out
1881  const XrdSecEntity *client, // In
1882  const char *opaque) // In
1883 /*
1884  Function: Compute and return file checksum.
1885 
1886  Input: Func - Function to be performed:
1887  csCalc - Return precomputed or computed checksum.
1888  csGet - Return precomputed checksum.
1889  csSize - Verify csName and get its size.
1890  Path - Pathname of file for csCalc and csSize.
1891  einfo - Error information object to hold error details.
1892  client - Authentication credentials, if any.
1893  opaque - Opaque information to be used as seen fit.
1894 
1895  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1896 */
1897 {
1898  EPNAME("chksum");
1899  XrdOucEnv cksEnv(opaque,0,client);
1900  XrdCksData cksData;
1901  const char *tident = einfo.getErrUser();
1902  char buff[MAXPATHLEN+8];
1903  int rc;
1904 
1905 // Check if we support checksumming
1906 //
1907  if (!Cks)
1908  {einfo.setErrInfo(ENOTSUP, "Checksums are not supported.");
1909  return SFS_ERROR;
1910  }
1911 
1912 // A csSize request is issued usually once to verify everything is working. We
1913 // take this opportunity to also verify the checksum name.
1914 //
1915  rc = cksData.Set(csName);
1916  if (!rc || Func == XrdSfsFileSystem::csSize)
1917  {if (rc && (rc = Cks->Size(csName)))
1918  {einfo.setErrCode(rc); return SFS_OK;}
1919  strcpy(buff, csName); strcat(buff, " checksum not supported.");
1920  einfo.setErrInfo(ENOTSUP, buff);
1921  return SFS_ERROR;
1922  }
1923 
1924 // Everything else requires a path
1925 //
1926  if (!Path)
1927  {strcpy(buff, csName);
1928  strcat(buff, " checksum path not specified.");
1929  einfo.setErrInfo(EINVAL, buff);
1930  return SFS_ERROR;
1931  }
1932 
1933 // Apply security, as needed
1934 //
1935  XTRACE(stat, Path, csName);
1936  AUTHORIZE(client,&cksEnv,AOP_Stat,"checksum",Path,einfo);
1937 
1938 // If we are a menager then we need to redirect the client to where the file is
1939 //
1940  if (CksRdr && Finder && Finder->isRemote()
1941  && (rc = Finder->Locate(einfo, Path, SFS_O_RDONLY, &cksEnv)))
1942  return fsError(einfo, rc);
1943 
1944 // At this point we need to convert the lfn to a pfn
1945 //
1946  if (CksPfn && !(Path = XrdOfsOss->Lfn2Pfn(Path, buff, MAXPATHLEN, rc)))
1947  return Emsg(epname, einfo, rc, "checksum", Path,
1948  "+ofs_chksum: lfn to pfn mapping failed");
1949 
1950 // Originally we only passed he env pointer for proxy servers. Due to popular
1951 // demand, we always pass the env as it points to the SecEntity object unless
1952 // we don't have it then we pass the caller's environment.
1953 //
1954  if (Func == XrdSfsFileSystem::csGet || Func == XrdSfsFileSystem::csCalc)
1955  {if (client) cksData.envP = &cksEnv;
1956  else cksData.envP = (einfo.getEnv() ? einfo.getEnv() : &cksEnv);
1957  }
1958 
1959 // Now determine what to do
1960 //
1961  if (Func == XrdSfsFileSystem::csCalc) rc = Cks->Calc(Path, cksData);
1962  else if (Func == XrdSfsFileSystem::csGet) rc = Cks->Get( Path, cksData);
1963  else {einfo.setErrInfo(EINVAL, "Invalid checksum function.");
1964  return SFS_ERROR;
1965  }
1966 
1967 // See if all went well
1968 //
1969 #ifdef ENOATTR
1970  if (rc >= 0 || rc == -ENOATTR || rc == -ESTALE || rc == -ESRCH)
1971 #else
1972  if (rc >= 0 || rc == -ENODATA || rc == -ESTALE || rc == -ESRCH)
1973 #endif
1974  {if (rc >= 0) {cksData.Get(buff, MAXPATHLEN); rc = 0;}
1975  else {*buff = 0; rc = -rc;}
1976  einfo.setErrInfo(rc, buff);
1977  return SFS_OK;
1978  }
1979 
1980 // We failed
1981 //
1982  return Emsg(epname, einfo, rc, "checksum", Path, "?");
1983 }
1984 
1985 /******************************************************************************/
1986 /* c h m o d */
1987 /******************************************************************************/
1988 
1989 int XrdOfs::chmod(const char *path, // In
1990  XrdSfsMode Mode, // In
1991  XrdOucErrInfo &einfo, // Out
1992  const XrdSecEntity *client, // In
1993  const char *info) // In
1994 /*
1995  Function: Change the mode on a file or directory.
1996 
1997  Input: path - Is the fully qualified name of the file to be removed.
1998  einfo - Error information object to hold error details.
1999  client - Authentication credentials, if any.
2000  info - Opaque information to be used as seen fit.
2001 
2002  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2003 */
2004 {
2005  EPNAME("chmod");
2006  static const int locFlags = SFS_O_RDWR|SFS_O_META;
2007  struct stat Stat;
2008  mode_t acc_mode = Mode & S_IAMB;
2009  const char *tident = einfo.getErrUser();
2010  XrdOucEnv chmod_Env(info,0,client);
2011  int retc;
2012  XTRACE(chmod, path, "");
2013 
2014 // Apply security, as needed
2015 //
2016  AUTHORIZE(client,&chmod_Env,AOP_Chmod,"chmod",path,einfo);
2017 
2018 // Find out where we should chmod this file
2019 //
2020  if (Finder && Finder->isRemote())
2021  {if (fwdCHMOD.Cmd)
2022  {char buff[8];
2023  sprintf(buff, "%o", static_cast<int>(acc_mode));
2024  if (Forward(retc,einfo,fwdCHMOD,path,buff,&chmod_Env)) return retc;
2025  }
2026  else if ((retc = Finder->Locate(einfo, path, locFlags, &chmod_Env)))
2027  return fsError(einfo, retc);
2028  }
2029 
2030 // We need to adjust the mode based on whether this is a file or directory.
2031 //
2032  if ((retc = XrdOfsOss->Stat(path, &Stat, 0, &chmod_Env)))
2033  return XrdOfsFS->Emsg(epname, einfo, retc, "stat", path, "?");
2034  if (S_ISDIR(Stat.st_mode)) acc_mode = (acc_mode | dMask[0]) & dMask[1];
2035  else acc_mode = (acc_mode | fMask[0]) & fMask[1];
2036 
2037 // Check if we should generate an event
2038 //
2039  if (evsObject && evsObject->Enabled(XrdOfsEvs::Chmod))
2040  {XrdOfsEvsInfo evInfo(tident, path, info, &chmod_Env, acc_mode);
2041  evsObject->Notify(XrdOfsEvs::Chmod, evInfo);
2042  }
2043 
2044 // Now try to find the file or directory
2045 //
2046  if (!(retc = XrdOfsOss->Chmod(path, acc_mode, &chmod_Env))) return SFS_OK;
2047 
2048 // An error occurred, return the error info
2049 //
2050  return XrdOfsFS->Emsg(epname, einfo, retc, "chmod", path, "?");
2051 }
2052 
2053 /******************************************************************************/
2054 /* C o n n e c t */
2055 /******************************************************************************/
2056 
2057 void XrdOfs::Connect(const XrdSecEntity *client)
2058 {
2059  XrdOucEnv myEnv(0, 0, client);
2060 
2061 // Pass this call along
2062 //
2063  XrdOfsOss->Connect(myEnv);
2064 }
2065 
2066 /******************************************************************************/
2067 /* D i s c */
2068 /******************************************************************************/
2069 
2070 void XrdOfs::Disc(const XrdSecEntity *client)
2071 {
2072  XrdOucEnv myEnv(0, 0, client);
2073 
2074 // Pass this call along
2075 //
2076  XrdOfsOss->Disc(myEnv);
2077 }
2078 
2079 /******************************************************************************/
2080 /* e x i s t s */
2081 /******************************************************************************/
2082 
2083 int XrdOfs::exists(const char *path, // In
2084  XrdSfsFileExistence &file_exists, // Out
2085  XrdOucErrInfo &einfo, // Out
2086  const XrdSecEntity *client, // In
2087  const char *info) // In
2088 /*
2089  Function: Determine if file 'path' actually exists.
2090 
2091  Input: path - Is the fully qualified name of the file to be tested.
2092  file_exists - Is the address of the variable to hold the status of
2093  'path' when success is returned. The values may be:
2094  XrdSfsFileExistsIsDirectory - file not found but path is valid.
2095  XrdSfsFileExistsIsFile - file found.
2096  XrdSfsFileExistsIsNo - neither file nor directory.
2097  einfo - Error information object holding the details.
2098  client - Authentication credentials, if any.
2099  info - Opaque information to be used as seen fit.
2100 
2101  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2102 
2103  Notes: When failure occurs, 'file_exists' is not modified.
2104 */
2105 {
2106  EPNAME("exists");
2107  struct stat fstat;
2108  int retc;
2109  const char *tident = einfo.getErrUser();
2110  XrdOucEnv stat_Env(info,0,client);
2111  XTRACE(exists, path, "");
2112 
2113 // Apply security, as needed
2114 //
2115  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2116 
2117 // Find out where we should stat this file
2118 //
2119  if (Finder && Finder->isRemote()
2120  && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY, &stat_Env)))
2121  return fsError(einfo, retc);
2122 
2123 // Now try to find the file or directory
2124 //
2125  retc = XrdOfsOss->Stat(path, &fstat, 0, &stat_Env);
2126  if (!retc)
2127  { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
2128  else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
2129  else file_exists=XrdSfsFileExistNo;
2130  return SFS_OK;
2131  }
2132  if (retc == -ENOENT)
2133  {file_exists=XrdSfsFileExistNo;
2134  return SFS_OK;
2135  }
2136 
2137 // An error occurred, return the error info
2138 //
2139  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path, "?");
2140 }
2141 
2142 /******************************************************************************/
2143 /* g e t S t a t s */
2144 /******************************************************************************/
2145 
2146 int XrdOfs::getStats(char *buff, int blen)
2147 {
2148  int n;
2149 
2150 // See if the size just wanted
2151 //
2152  if (!buff) return OfsStats.Report(0,0) + XrdOfsOss->Stats(0,0);
2153 
2154 // Report ofs info followed by the oss info
2155 //
2156  n = OfsStats.Report(buff, blen);
2157  buff += n; blen -= n;
2158  n += XrdOfsOss->Stats(buff, blen);
2159 
2160 // All done
2161 //
2162  return n;
2163 }
2164 
2165 /******************************************************************************/
2166 /* m k d i r */
2167 /******************************************************************************/
2168 
2169 int XrdOfs::mkdir(const char *path, // In
2170  XrdSfsMode Mode, // In
2171  XrdOucErrInfo &einfo, // Out
2172  const XrdSecEntity *client, // In
2173  const char *info) // In
2174 /*
2175  Function: Create a directory entry.
2176 
2177  Input: path - Is the fully qualified name of the file to be removed.
2178  Mode - Is the POSIX mode value the directory is to have.
2179  Additionally, Mode may contain SFS_O_MKPTH if the
2180  full dircectory path should be created.
2181  einfo - Error information object to hold error details.
2182  client - Authentication credentials, if any.
2183  info - Opaque information to be used as seen fit.
2184 
2185  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2186 */
2187 {
2188  EPNAME("mkdir");
2189  static const int LocOpts = SFS_O_RDWR | SFS_O_CREAT | SFS_O_META;
2190  mode_t acc_mode = (Mode | dMask[0]) & dMask[1];
2191  int retc, mkpath = Mode & SFS_O_MKPTH;
2192  const char *tident = einfo.getErrUser();
2193  XrdOucEnv mkdir_Env(info,0,client);
2194  XTRACE(mkdir, path, "");
2195 
2196 // Apply security, as needed
2197 //
2198  AUTHORIZE(client,&mkdir_Env,AOP_Mkdir,"mkdir",path,einfo);
2199 
2200 // Find out where we should remove this file
2201 //
2202  if (Finder && Finder->isRemote())
2203  {if (fwdMKDIR.Cmd)
2204  {char buff[8];
2205  sprintf(buff, "%o", static_cast<int>(acc_mode));
2206  if (Forward(retc, einfo, (mkpath ? fwdMKPATH:fwdMKDIR),
2207  path, buff, &mkdir_Env)) return retc;
2208  }
2209  else if ((retc = Finder->Locate(einfo,path,LocOpts,&mkdir_Env)))
2210  return fsError(einfo, retc);
2211  }
2212 
2213 // Perform the actual operation
2214 //
2215  if ((retc = XrdOfsOss->Mkdir(path, acc_mode, mkpath, &mkdir_Env)))
2216  return XrdOfsFS->Emsg(epname, einfo, retc, "mkdir", path, "?");
2217 
2218 // Check if we should generate an event
2219 //
2220  if (evsObject && evsObject->Enabled(XrdOfsEvs::Mkdir))
2221  {XrdOfsEvsInfo evInfo(tident, path, info, &mkdir_Env, acc_mode);
2222  evsObject->Notify(XrdOfsEvs::Mkdir, evInfo);
2223  }
2224 
2225 // If we have a redirector, tell it that we now have this path
2226 //
2227  if (Balancer)
2228  {if (!mkpath) Balancer->Added(path);
2229  else {char *slash, *myPath = strdup(path);
2230  do {Balancer->Added(myPath);
2231  if ((slash = rindex(myPath, '/'))) *slash = 0;
2232  } while(slash && slash != myPath);
2233  free(myPath);
2234  }
2235  }
2236 
2237  return SFS_OK;
2238 }
2239 
2240 /******************************************************************************/
2241 /* p r e p a r e */
2242 /******************************************************************************/
2243 
2244 int XrdOfs::prepare( XrdSfsPrep &pargs, // In
2245  XrdOucErrInfo &out_error, // Out
2246  const XrdSecEntity *client) // In
2247 {
2248  EPNAME("prepare");
2249  XrdOucEnv prep_Env(0,0,client);
2250  XrdOucTList *tp = pargs.paths;
2251  int retc;
2252 
2253 // Run through the paths to make sure client can read each one unless we aren't
2254 // supposed to apply authorization.
2255 //
2256  if (prepAuth)
2257  while(tp)
2258  {AUTHORIZE(client,0,AOP_Read,"prepare",tp->text,out_error);
2259  tp = tp->next;
2260  }
2261 
2262 // If there is a prepare plugin, invoke it and return the result.
2263 //
2264  if (prepHandler)
2265  {if (pargs.opts & Prep_QUERY)
2266  return prepHandler->query(pargs, out_error, client);
2267  if (pargs.opts & Prep_CANCEL)
2268  return prepHandler->cancel(pargs, out_error, client);
2269 
2270  return prepHandler->begin(pargs, out_error, client);
2271  }
2272 
2273 // If we have a finder object, use it to prepare the paths. Otherwise,
2274 // ignore this prepare request (we may change this in the future).
2275 //
2276  if (XrdOfsFS->Finder
2277  && (retc = XrdOfsFS->Finder->Prepare(out_error, pargs, &prep_Env)))
2278  return fsError(out_error, retc);
2279  return 0;
2280 }
2281 
2282 /******************************************************************************/
2283 /* r e m o v e */
2284 /******************************************************************************/
2285 
2286 int XrdOfs::remove(const char type, // In
2287  const char *path, // In
2288  XrdOucErrInfo &einfo, // Out
2289  const XrdSecEntity *client, // In
2290  const char *info) // In
2291 /*
2292  Function: Delete a file from the namespace and release it's data storage.
2293 
2294  Input: type - 'f' for file and 'd' for directory.
2295  path - Is the fully qualified name of the file to be removed.
2296  einfo - Error information object to hold error details.
2297  client - Authentication credentials, if any.
2298  info - Opaque information to be used as seen fit.
2299 
2300  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2301 */
2302 {
2303  EPNAME("remove");
2304  static const int LocOpts = SFS_O_WRONLY|SFS_O_META;
2305  int retc, Opt;
2306  const char *tident = einfo.getErrUser();
2307  XrdOucEnv rem_Env(info,0,client);
2308  XTRACE(remove, path, type);
2309 
2310 // Apply security, as needed
2311 //
2312  AUTHORIZE(client,&rem_Env,AOP_Delete,"remove",path,einfo);
2313 
2314 // Find out where we should remove this file
2315 //
2316  if (Finder && Finder->isRemote())
2317  {struct fwdOpt *fSpec = (type == 'd' ? &fwdRMDIR : &fwdRM);
2318  if (fSpec->Cmd)
2319  {if (Forward(retc, einfo, *fSpec, path, 0, &rem_Env)) return retc;}
2320  else if ((retc = Finder->Locate(einfo, path, LocOpts, &rem_Env)))
2321  return fsError(einfo, retc);
2322  }
2323 
2324 // Check if we should generate an event
2325 //
2326  if (evsObject)
2327  {XrdOfsEvs::Event theEvent=(type == 'd' ? XrdOfsEvs::Rmdir:XrdOfsEvs::Rm);
2328  if (evsObject->Enabled(theEvent))
2329  {XrdOfsEvsInfo evInfo(tident, path, info, &rem_Env);
2330  evsObject->Notify(theEvent, evInfo);
2331  }
2332  }
2333 
2334 // Check if this is an online deletion only
2335 //
2336  Opt = (rem_Env.Get("ofs.lcl") ? XRDOSS_Online : 0);
2337 
2338 // Perform the actual deletion
2339 //
2340  retc = (type=='d' ? XrdOfsOss->Remdir(path, 0, &rem_Env)
2341  : XrdOfsOss->Unlink(path, Opt, &rem_Env));
2342  if (retc) return XrdOfsFS->Emsg(epname, einfo, retc, "remove", path, "?");
2343  if (type == 'f') XrdOfsHandle::Hide(path);
2344  if (Balancer) Balancer->Removed(path);
2345  return SFS_OK;
2346 }
2347 
2348 /******************************************************************************/
2349 /* r e n a m e */
2350 /******************************************************************************/
2351 
2352 int XrdOfs::rename(const char *old_name, // In
2353  const char *new_name, // In
2354  XrdOucErrInfo &einfo, //Out
2355  const XrdSecEntity *client, // In
2356  const char *infoO, // In
2357  const char *infoN) // In
2358 /*
2359  Function: Renames a file with name 'old_name' to 'new_name'.
2360 
2361  Input: old_name - Is the fully qualified name of the file to be renamed.
2362  new_name - Is the fully qualified name that the file is to have.
2363  einfo - Error information structure, if an error occurs.
2364  client - Authentication credentials, if any.
2365  infoO - old_name opaque information to be used as seen fit.
2366  infoN - new_name opaque information to be used as seen fit.
2367 
2368  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2369 */
2370 {
2371  EPNAME("rename");
2372  static const int LocOpts = SFS_O_RDWR|SFS_O_META;
2373  int retc;
2374  const char *tident = einfo.getErrUser();
2375  XrdOucEnv old_Env(infoO,0,client);
2376  XrdOucEnv new_Env(infoN,0,client);
2377  XTRACE(rename, new_name, "old fn=" <<old_name <<" new ");
2378 
2379 // Apply security, as needed
2380 //
2381  AUTHORIZE(client, &old_Env, AOP_Rename, "renaming", old_name, einfo);
2382 
2383 // The above authorization may mutate the XrdSecEntity by putting a mapped name
2384 // into the extended attributes. This mapped name will affect the subsequent
2385 // authorization check below, giving the client access that may not be permitted.
2386 // Hence, we delete this attribute to reset the object back to "pristine" state.
2387 // If there was a way to make a copy of the XrdSecEntity, we could avoid this
2388 // hack-y reach inside the extended attributes.
2389  if (client) client->eaAPI->Add("request.name", "", true);
2390 
2391 // If we do not have full-blown insert authorization, we'll need to test for
2392 // destination existence
2393  bool cannot_overwrite = false;
2394  if (client && XrdOfsFS->Authorization &&
2395  !XrdOfsFS->Authorization->Access(client, new_name, AOP_Insert, &new_Env))
2396  {cannot_overwrite = true;
2397  AUTHORIZE(client, &new_Env, AOP_Excl_Insert,
2398  "rename to existing file (overwrite disallowed)", new_name, einfo);
2399  }
2400 
2401 // Find out where we should rename this file
2402 //
2403  if (Finder && Finder->isRemote())
2404  {if (fwdMV.Cmd)
2405  {if (Forward(retc,einfo,fwdMV,old_name,new_name,&old_Env,&new_Env))
2406  return retc;
2407  }
2408  else if ((retc = Finder->Locate(einfo, old_name, LocOpts, &old_Env)))
2409  return fsError(einfo, retc);
2410  }
2411 
2412 // Check if we should generate an event
2413 //
2414  if (evsObject && evsObject->Enabled(XrdOfsEvs::Mv))
2415  {XrdOfsEvsInfo evInfo(tident, old_name, infoO, &old_Env, 0, 0,
2416  new_name, infoN, &new_Env);
2417  evsObject->Notify(XrdOfsEvs::Mv, evInfo);
2418  }
2419 
2420 // If we cannot overwrite, we must test for existence first. This will test whether
2421 // we will destroy data in the rename (without actually destroying data).
2422 // Note there's an obvious race condition here; it was seen as the lesser-of-evils
2423 // compared to creating an exclusive file and potentially leaking it in the event
2424 // of a crash.
2425 //
2426  if (cannot_overwrite)
2427  {XrdSfsFileExistence exists_flag;
2428  if (SFS_OK != exists(new_name, exists_flag, einfo, client, infoN))
2429  {// File existence check itself failed; we can't prove that data won't
2430  // be overwritten so we return an error.
2431  return fsError(einfo, -einfo.getErrInfo());
2432  }
2433  if (exists_flag != XrdSfsFileExistNo)
2434  {// EPERM mimics the error code set by Linux when you invoke rename()
2435  // but cannot overwrite the destination file.
2436  einfo.setErrInfo(EPERM, "Overwrite of existing data not permitted");
2437  return fsError(einfo, -EPERM);
2438  }
2439  }
2440 
2441 // Perform actual rename operation
2442 //
2443  if ((retc = XrdOfsOss->Rename(old_name, new_name, &old_Env, &new_Env)))
2444  {return XrdOfsFS->Emsg(epname, einfo, retc, "rename", old_name, "?");
2445  }
2446  XrdOfsHandle::Hide(old_name);
2447  if (Balancer) {Balancer->Removed(old_name);
2448  Balancer->Added(new_name);
2449  }
2450  return SFS_OK;
2451 }
2452 
2453 /******************************************************************************/
2454 /* s t a t */
2455 /******************************************************************************/
2456 
2457 int XrdOfs::stat(const char *path, // In
2458  struct stat *buf, // Out
2459  XrdOucErrInfo &einfo, // Out
2460  const XrdSecEntity *client, // In
2461  const char *info) // In
2462 /*
2463  Function: Return file status information
2464 
2465  Input: path - The path for which status is wanted
2466  buf - The stat structure to hold the results
2467  einfo - Error information structure, if an error occurs.
2468  client - Authentication credentials, if any.
2469  info - opaque information to be used as seen fit.
2470 
2471  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2472 */
2473 {
2474  EPNAME("stat");
2475  int retc;
2476  const char *tident = einfo.getErrUser();
2477  XrdOucEnv stat_Env(info,0,client);
2478  XTRACE(stat, path, "");
2479 
2480 // Apply security, as needed
2481 //
2482  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2483 
2484 // Find out where we should stat this file
2485 //
2486  if (Finder && Finder->isRemote()
2487  && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY|SFS_O_STAT, &stat_Env)))
2488  return fsError(einfo, retc);
2489 
2490 // Now try to find the file or directory
2491 //
2492  if ((retc = XrdOfsOss->Stat(path, buf, 0, &stat_Env)))
2493  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path, "?");
2494  return SFS_OK;
2495 }
2496 
2497 /******************************************************************************/
2498 
2499 int XrdOfs::stat(const char *path, // In
2500  mode_t &mode, // Out
2501  XrdOucErrInfo &einfo, // Out
2502  const XrdSecEntity *client, // In
2503  const char *info) // In
2504 /*
2505  Function: Return file status information (resident files only)
2506 
2507  Input: path - The path for which status is wanted
2508  mode - The stat mode entry (faked -- do not trust it)
2509  einfo - Error information structure, if an error occurs.
2510  client - Authentication credentials, if any.
2511  info - opaque information to be used as seen fit.
2512 
2513  Output: Always returns SFS_ERROR if a delay needs to be imposed. Otherwise,
2514  SFS_OK is returned and mode is appropriately, if inaccurately, set.
2515  If file residency cannot be determined, mode is set to -1.
2516 */
2517 {
2518  EPNAME("stat");
2519  struct stat buf;
2520  int retc;
2521  const char *tident = einfo.getErrUser();
2522  XrdOucEnv stat_Env(info,0,client);
2523  XTRACE(stat, path, "");
2524 
2525 // Apply security, as needed
2526 //
2527  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2528  mode = (mode_t)-1;
2529 
2530 // Find out where we should stat this file
2531 //
2532  if (Finder && Finder->isRemote()
2533  && (retc = Finder->Locate(einfo,path,SFS_O_NOWAIT|SFS_O_RDONLY|SFS_O_STAT,
2534  &stat_Env)))
2535  return fsError(einfo, retc);
2536 
2537 // Now try to find the file or directory
2538 //
2539  if (!(retc = XrdOfsOss->Stat(path, &buf, XRDOSS_resonly, &stat_Env)))
2540  mode=buf.st_mode;
2541  else if ((-ENOMSG) != retc)
2542  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path, "?");
2543  return SFS_OK;
2544 }
2545 
2546 /******************************************************************************/
2547 /* t r u n c a t e */
2548 /******************************************************************************/
2549 
2550 int XrdOfs::truncate(const char *path, // In
2551  XrdSfsFileOffset Size, // In
2552  XrdOucErrInfo &einfo, // Out
2553  const XrdSecEntity *client, // In
2554  const char *info) // In
2555 /*
2556  Function: Change the mode on a file or directory.
2557 
2558  Input: path - Is the fully qualified name of the file to be removed.
2559  Size - the size the file should have.
2560  einfo - Error information object to hold error details.
2561  client - Authentication credentials, if any.
2562  info - Opaque information to be used as seen fit.
2563 
2564  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2565 */
2566 {
2567  EPNAME("truncate");
2568  const char *tident = einfo.getErrUser();
2569  XrdOucEnv trunc_Env(info,0,client);
2570  int retc;
2571  XTRACE(truncate, path, "");
2572 
2573 // Apply security, as needed
2574 //
2575  AUTHORIZE(client,&trunc_Env,AOP_Update,"truncate",path,einfo);
2576 
2577 // Find out where we should chmod this file
2578 //
2579  if (Finder && Finder->isRemote())
2580  {if (fwdTRUNC.Cmd)
2581  {char xSz[32];
2582  sprintf(xSz, "%lld", static_cast<long long>(Size));
2583  if (Forward(retc,einfo,fwdTRUNC,path,xSz,&trunc_Env)) return retc;
2584  }
2585  else if ((retc = Finder->Locate(einfo,path,SFS_O_RDWR,&trunc_Env)))
2586  return fsError(einfo, retc);
2587  }
2588 
2589 // Check if we should generate an event
2590 //
2591  if (evsObject && evsObject->Enabled(XrdOfsEvs::Trunc))
2592  {XrdOfsEvsInfo evInfo(tident, path, info, &trunc_Env, 0, Size);
2593  evsObject->Notify(XrdOfsEvs::Trunc, evInfo);
2594  }
2595 
2596 // Now try to find the file or directory
2597 //
2598  if (!(retc = XrdOfsOss->Truncate(path, Size, &trunc_Env))) return SFS_OK;
2599 
2600 // An error occurred, return the error info
2601 //
2602  return XrdOfsFS->Emsg(epname, einfo, retc, "trunc", path, "?");
2603 }
2604 
2605 /******************************************************************************/
2606 /* E m s g */
2607 /******************************************************************************/
2608 
2609 int XrdOfs::Emsg(const char *pfx, // Message prefix value
2610  XrdOucErrInfo &einfo, // Place to put text & error code
2611  int ecode, // The error code
2612  const char *op, // Operation being performed
2613  XrdOfsHandle *hP, // The target handle
2614  bool posChk, // Unpersist if in posc mode
2615  bool chkType)// Check for type of error & subclass
2616 {
2617  const char* etP = 0;
2618  int rc;
2619 
2620 // Screen out non-errors
2621 //
2622  if (chkType && (rc = EmsgType(ecode)) != SFS_ERROR) return rc;
2623 
2624 // Get any extended information
2625 //
2626  std::string eText;
2627  if (XrdOfsFS->tryXERT && hP->Select().getErrMsg(eText)) etP = eText.c_str();
2628 
2629 // First issue the error message so if we have to unpersist it makes sense
2630 //
2631  rc = Emsg(pfx, einfo, ecode, op, hP->Name(), etP);
2632 
2633 // If this is a POSC file then we need to unpersist it. Note that we are always
2634 // called with the handle **unlocked**
2635 //
2636  if (posChk && hP->isRW == XrdOfsHandle::opPC)
2637  {hP->Lock();
2638  XrdOfsFS->Unpersist(hP);
2639  hP->UnLock();
2640  }
2641 
2642 // Now return the error
2643 //
2644  return rc;
2645 }
2646 
2647 /******************************************************************************/
2648 
2649 int XrdOfs::Emsg(const char *pfx, // Message prefix value
2650  XrdOucErrInfo &einfo, // Place to put text & error code
2651  int ecode, // The error code
2652  const char *op, // Operation being performed
2653  const char *target, // The target (e.g., fname)
2654  const char *xtra, // Optional extra error information
2655  bool chkType)// Check for type of error & subclass
2656 {
2657  char* buffer;
2658  int buflen, rc;
2659  bool msgDone = false;
2660 
2661 // Screen out non-errors
2662 //
2663  if (chkType && (rc = EmsgType(ecode)) != SFS_ERROR) return rc;
2664 
2665 // Setup message handling
2666 //
2667  if (einfo.extData()) einfo.Reset();
2668  buffer = einfo.getMsgBuff(buflen);
2669  std::string eText;
2670 
2671  // Translate ecode to corresponding errno
2672  int rcode = OfsEroute.ec2errno(ecode);
2673 
2674 // Check for extended information
2675 //
2676  if (xtra)
2677  switch(*xtra)
2678  {case '?': xtra = 0;
2679  if (XrdOfsFS->tryXERT && XrdOfsOss->getErrMsg(eText))
2680  {if (eText.find("Unable") != std::string::npos)
2681  {einfo.setErrInfo(rcode, eText.c_str());
2682  msgDone = true;
2683  } else xtra = eText.c_str();
2684  }
2685  break;
2686  case '+': xtra++;
2687  break;
2688  default: einfo.setErrInfo(rcode, xtra);
2689  msgDone = true;
2690  break;
2691  }
2692 
2693 // Format the error message if it has not been already set
2694 //
2695  if (!msgDone)
2696  {XrdOucERoute::Format(buffer, buflen, ecode, op, target, xtra);
2697  einfo.setErrCode(rcode);
2698  }
2699 
2700 // Print it out
2701 //
2702  OfsEroute.Emsg(pfx, einfo.getErrUser(), buffer);
2703 
2704 // Return an error
2705 //
2706  return SFS_ERROR;
2707 }
2708 
2709 /******************************************************************************/
2710 /* E m s g T y p e */
2711 /******************************************************************************/
2712 
2713 int XrdOfs::EmsgType(int ecode) // The error code
2714 {
2715 
2716 // If the error is EBUSY then we just need to stall the client. This is
2717 // a hack in order to provide for proxy support
2718 //
2719  if (ecode < 0) ecode = -ecode;
2720  if (ecode == EBUSY) return 5; // A hack for proxy support
2721 
2722 // Check for timeout conditions that require a client delay
2723 //
2724  if (ecode == ETIMEDOUT) return OSSDelay;
2725 
2726 // This is a real error
2727 //
2728  return SFS_ERROR;
2729 }
2730 
2731 /******************************************************************************/
2732 /* P R I V A T E S E C T I O N */
2733 /******************************************************************************/
2734 
2735 /******************************************************************************/
2736 /* F n a m e */
2737 /******************************************************************************/
2738 
2739 const char *XrdOfs::Fname(const char *path)
2740 {
2741  int i = strlen(path)-1;
2742  while(i) if (path[i] == '/') return &path[i+1];
2743  else i--;
2744  return path;
2745 }
2746 
2747 /******************************************************************************/
2748 /* F o r w a r d */
2749 /******************************************************************************/
2750 
2751 int XrdOfs::Forward(int &Result, XrdOucErrInfo &Resp, struct fwdOpt &Fwd,
2752  const char *arg1, const char *arg2,
2753  XrdOucEnv *Env1, XrdOucEnv *Env2)
2754 {
2755  int retc;
2756 
2757  if ((retc = Finder->Forward(Resp, Fwd.Cmd, arg1, arg2, Env1, Env2)))
2758  {Result = fsError(Resp, retc);
2759  return 1;
2760  }
2761 
2762  if (Fwd.Port <= 0)
2763  {Result = SFS_OK;
2764  return (Fwd.Port ? 0 : 1);
2765  }
2766 
2767  Resp.setErrInfo(Fwd.Port, Fwd.Host);
2768  Result = SFS_REDIRECT;
2770  return 1;
2771 }
2772 
2773 /******************************************************************************/
2774 /* f s E r r o r */
2775 /******************************************************************************/
2776 
2777 int XrdOfs::fsError(XrdOucErrInfo &myError, int rc)
2778 {
2779 
2780 // Screen the error code (update statistics w/o a lock for speed!)
2781 //
2782  if (rc == SFS_REDIRECT) {OfsStats.Data.numRedirect++; return SFS_REDIRECT;}
2783  if (rc == SFS_STARTED) {OfsStats.Data.numStarted++; return SFS_STARTED; }
2784  if (rc > 0) {OfsStats.Data.numDelays++; return rc; }
2785  if (rc == SFS_DATA) {OfsStats.Data.numReplies++; return SFS_DATA; }
2786  {OfsStats.Data.numErrors++; return SFS_ERROR; }
2787 }
2788 
2789 /******************************************************************************/
2790 /* R e f o r m a t */
2791 /******************************************************************************/
2792 
2793 int XrdOfs::Reformat(XrdOucErrInfo &myError)
2794 {
2795  static const char *fmt = "oss.cgroup=all&oss.space=%llu&oss.free=%llu"
2796  "&oss.maxf=%llu&oss.used=%llu&oss.quota=-1";
2797  char qsFmt, *bP;
2798  unsigned long long totSpace, totFree, maxFree;
2799  int n, blen;
2800 
2801 // Get the buffer
2802 //
2803  bP = myError.getMsgBuff(blen);
2804 
2805 // Scan out the values
2806 //
2807  n = sscanf(bP, "%c %llu %llu %llu", &qsFmt, &totSpace, &totFree, &maxFree);
2808 
2809 // Validate the response. The response will be invalid for older cmsd's
2810 //
2811  if (n != 4 || qsFmt != 'A')
2812  {myError.setErrInfo(ENOTSUP,"space fctl operation not supported by cmsd");
2813  return SFS_ERROR;
2814  }
2815 
2816 // Change megabyte values to actual bytes
2817 //
2818  totSpace = totSpace << 20LL;
2819  totFree = totFree << 20LL;
2820  maxFree = maxFree << 20LL;
2821 
2822 // Reformat the result
2823 //
2824  blen = snprintf(bP,blen,fmt,totSpace,totFree,maxFree,(totSpace-totFree));
2825 
2826  myError.setErrCode(blen);
2827  return SFS_DATA;
2828 }
2829 
2830 /******************************************************************************/
2831 /* S p l i t */
2832 /******************************************************************************/
2833 
2834 const char * XrdOfs::Split(const char *Args, const char **Opq,
2835  char *Path, int Plen)
2836 {
2837  int xlen;
2838  *Opq = index(Args, '?');
2839  if (!(*Opq)) return Args;
2840  xlen = (*Opq)-Args;
2841  if (xlen >= Plen) xlen = Plen-1;
2842  strncpy(Path, Args, xlen);
2843  Path[xlen] = 0;
2844  return Path;
2845 }
2846 
2847 /******************************************************************************/
2848 /* S t a l l */
2849 /******************************************************************************/
2850 
2851 int XrdOfs::Stall(XrdOucErrInfo &einfo, // Error text & code
2852  int stime, // Seconds to stall
2853  const char *path) // The path to stall on
2854 {
2855  const char *msgfmt = "File %s is being %s; "
2856  "estimated time to completion %s";
2857  EPNAME("Stall")
2858 #ifndef NODEBUG
2859  const char *tident = "";
2860 #endif
2861  char Mbuff[2048], Tbuff[32];
2862  const char *What = "staged";
2863 
2864 // Check why the stall is occurring
2865 //
2866  if (stime < 0) {stime = 60; What = "created";}
2867 
2868 // Format the stall message
2869 //
2870  snprintf(Mbuff, sizeof(Mbuff)-1, msgfmt,
2871  Fname(path), What, WaitTime(stime, Tbuff, sizeof(Tbuff)));
2872  ZTRACE(delay, "Stall " <<stime <<": " <<Mbuff <<" for " <<path);
2873 
2874 // Place the error message in the error object and return
2875 //
2876  einfo.setErrInfo(0, Mbuff);
2877 
2878 // All done
2879 //
2880  return (stime > MaxDelay ? MaxDelay : stime);
2881 }
2882 
2883 /******************************************************************************/
2884 /* U n p e r s i s t */
2885 /******************************************************************************/
2886 
2887 void XrdOfs::Unpersist(XrdOfsHandle *oh, int xcev)
2888 {
2889  EPNAME("Unpersist");
2890  const char *tident = oh->PoscUsr();
2891  int poscNum, retc;
2892  short theMode;
2893 
2894 // Trace the call
2895 //
2896  FTRACE(close, "use=0");
2897 
2898 // Generate a proper close event as one has not yet been generated
2899 //
2900  if (xcev && XrdOfsFS->evsObject && *tident != '?'
2901  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Closew))
2902  {XrdOfsEvsInfo evInfo(tident, oh->Name());
2903  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Closew, evInfo);
2904  }
2905 
2906 // Now generate a removal event
2907 //
2908  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Removed(oh->Name());
2909  if (XrdOfsFS->evsObject && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Rm))
2910  {XrdOfsEvsInfo evInfo(tident, oh->Name());
2911  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Rm, evInfo);
2912  }
2913 
2914 // Count this
2915 //
2917 
2918 // Now unpersist the file
2919 //
2920  OfsEroute.Emsg(epname, "Unpersisting", tident, oh->Name());
2921  if ((poscNum = oh->PoscGet(theMode))) poscQ->Del(oh->Name(), poscNum, 1);
2922  else if ((retc = XrdOfsOss->Unlink(oh->Name())))
2923  OfsEroute.Emsg(epname, retc, "unpersist", oh->Name());
2924 }
2925 
2926 /******************************************************************************/
2927 /* W a i t T i m e */
2928 /******************************************************************************/
2929 
2930 char *XrdOfs::WaitTime(int stime, char *buff, int blen)
2931 {
2932  int hr, min, sec;
2933 
2934 // Compute hours, minutes, and seconds
2935 //
2936  min = stime / 60;
2937  sec = stime % 60;
2938  hr = min / 60;
2939  min = min % 60;
2940 
2941 // Now format the message based on time duration
2942 //
2943  if (!hr && !min)
2944  snprintf(buff,blen,"%d second%s",sec,(sec > 1 ? "s" : ""));
2945  else if (!hr)
2946  {if (sec > 10) min++;
2947  snprintf(buff,blen,"%d minute%s",min,(min > 1 ? "s" : ""));
2948  }
2949  else {if (hr == 1)
2950  if (min <= 30)
2951  snprintf(buff,blen,"%d minutes",min+60);
2952  else snprintf(buff,blen,"%d hour and %d minutes",hr,min);
2953  else {if (min > 30) hr++;
2954  snprintf(buff,blen,"%d hours",hr);
2955  }
2956  }
2957 
2958 // Complete the message
2959 //
2960  buff[blen-1] = '\0';
2961  return buff;
2962 }
#define ENOATTR
Definition: XProtocol.hh:1385
@ kXR_faMaxVlen
Definition: XProtocol.hh:312
@ kXR_faMaxNlen
Definition: XProtocol.hh:311
@ AOP_Delete
rm() or rmdir()
@ AOP_Mkdir
mkdir()
@ AOP_Update
open() r/w or append
@ AOP_Create
open() with create
@ AOP_Readdir
opendir()
@ AOP_Chmod
chmod()
@ AOP_Stat
exists(), stat()
@ AOP_Rename
mv() for source
@ AOP_Read
open() r/o, prepare()
@ AOP_Excl_Create
open() with O_EXCL|O_CREAT
@ AOP_Insert
mv() for target
@ AOP_Excl_Insert
mv() where destination doesn't exist.
#define tident
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define FTRACE(act, x)
Definition: XrdBwmTrace.hh:45
#define ZTRACE(act, x)
Definition: XrdBwmTrace.hh:52
#define XTRACE(act, target, x)
Definition: XrdBwmTrace.hh:49
struct stat Stat
Definition: XrdCks.cc:49
#define S_IAMB
Definition: XrdConfig.cc:163
#define ENODATA
Definition: XrdOfsChkPnt.cc:48
#define OOIDENTENV(usr, env)
#define AUTHORIZE(usr, env, optype, action, pathp, edata)
XrdSysError OfsEroute(0)
XrdSysTrace OfsTrace("ofs")
XrdOss * XrdOfsOss
Definition: XrdOfs.cc:163
XrdOfsStats OfsStats
Definition: XrdOfs.cc:113
#define O_DIRECT
Definition: XrdOfs.cc:98
XrdOfs * XrdOfsFS
Definition: XrdOfsFS.cc:47
#define XRDOSS_coloc
Definition: XrdOss.hh:529
#define XRDOSS_Online
Definition: XrdOss.hh:528
#define XRDOSS_new
Definition: XrdOss.hh:527
#define XRDOSS_mkpath
Definition: XrdOss.hh:526
#define XRDOSS_resonly
Definition: XrdOss.hh:548
int closedir(DIR *dirp)
DIR * opendir(const char *path)
#define close(a)
Definition: XrdPosix.hh:48
#define fstat(a, b)
Definition: XrdPosix.hh:109
#define stat(a, b)
Definition: XrdPosix.hh:105
#define readdir(a)
Definition: XrdPosix.hh:90
int Mode
XrdOucString Path
#define eMsg(x)
struct myOpts opts
off_t aio_offset
Definition: XrdSfsAio.hh:49
size_t aio_nbytes
Definition: XrdSfsAio.hh:48
void * aio_buf
Definition: XrdSfsAio.hh:47
#define XRDSFS_POSCPEND
Definition: XrdSfsFlags.hh:92
int XrdSfsMode
#define SFS_DATA
#define Prep_CANCEL
#define SFS_O_RESET
#define SFS_O_CREATAT
#define SFS_O_STAT
#define Prep_QUERY
XrdOucTList * paths
List of paths.
#define SFS_O_META
#define SFS_ERROR
XrdSfsFileExistence
@ XrdSfsFileExistIsFile
@ XrdSfsFileExistNo
@ XrdSfsFileExistIsDirectory
#define SFS_O_SEQIO
#define SFS_O_NOTPC
#define SFS_O_POSC
#define SFS_FCTL_QFINFO
#define SFS_REDIRECT
#define SFS_O_MKPTH
#define SFS_O_RDONLY
#define SFS_STARTED
#define SFS_O_MULTIW
#define SFS_O_WRONLY
#define SFS_FCTL_GETFD
#define SFS_O_CREAT
#define SFS_O_RAWIO
#define SFS_O_RDWR
int XrdSfsFileOpenMode
#define SFS_FCTL_SPEC1
#define SFS_OK
long long XrdSfsFileOffset
#define SFS_O_NOWAIT
int opts
Prep_xxx.
#define SFS_O_REPLICA
#define SFS_O_TRUNC
int XrdSfsXferSize
< Prepare parameters
virtual XrdAccPrivs Access(const XrdSecEntity *Entity, const char *path, const Access_Operation oper, XrdOucEnv *Env=0)=0
int Set(const char *csName)
Definition: XrdCksData.hh:81
int Get(char *Buff, int Blen)
Definition: XrdCksData.hh:69
virtual int Get(const char *Xfn, XrdCksData &Cks)=0
virtual int Size(const char *Name=0)=0
virtual int Calc(const char *Xfn, XrdCksData &Cks, int doSet=1)=0
virtual void Added(const char *path, int Pend=0)
virtual int isRemote()
virtual int Prepare(XrdOucErrInfo &Resp, XrdSfsPrep &pargs, XrdOucEnv *Info=0)
virtual void Removed(const char *path)
virtual int Forward(XrdOucErrInfo &Resp, const char *cmd, const char *arg1=0, const char *arg2=0, XrdOucEnv *Env1=0, XrdOucEnv *Env2=0)
virtual int Locate(XrdOucErrInfo &Resp, const char *path, int flags, XrdOucEnv *Info=0)=0
static bool Enabled
char dname[MAXNAMLEN]
Definition: XrdOfs.hh:92
const char * nextEntry()
Definition: XrdOfs.cc:308
const char * tident
Definition: XrdOfs.hh:88
int autoStat(struct stat *buf)
Definition: XrdOfs.cc:417
char * fname
Definition: XrdOfs.hh:89
XrdOssDF * dp
Definition: XrdOfs.hh:90
int open(const char *dirName, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:240
void Wait4Event(const char *path, XrdOucErrInfo *einfo)
Definition: XrdOfsEvr.cc:226
void Notify(Event eNum, XrdOfsEvsInfo &Info)
Definition: XrdOfsEvs.cc:234
int Enabled(Event theEvents)
Definition: XrdOfsEvs.hh:139
XrdOfsFile(XrdOucErrInfo &eInfo, const char *user)
Definition: XrdOfs.cc:457
int getCXinfo(char cxtype[4], int &cxrsz)
Definition: XrdOfs.cc:1826
int checkpoint(XrdSfsFile::cpAct act, struct iov *range=0, int n=0)
Definition: XrdOfs.cc:982
XrdSfsXferSize pgWrite(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize wrlen, uint32_t *csvec, uint64_t opts=0)
Definition: XrdOfs.cc:1282
XrdSfsXferSize write(XrdSfsFileOffset fileOffset, const char *buffer, XrdSfsXferSize buffer_size)
Definition: XrdOfs.cc:1566
int truncate(XrdSfsFileOffset fileOffset)
Definition: XrdOfs.cc:1779
int Clone(XrdSfsFile &srcFile)
Definition: XrdOfs.cc:840
int read(XrdSfsFileOffset fileOffset, XrdSfsXferSize amount)
Definition: XrdOfs.cc:1401
XrdSfsXferSize readv(XrdOucIOVec *readV, int readCount)
Definition: XrdOfs.cc:1488
int open(const char *fileName, XrdSfsFileOpenMode openMode, mode_t createMode, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:466
XrdSfsXferSize pgRead(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize rdlen, uint32_t *csvec, uint64_t opts=0)
Definition: XrdOfs.cc:1186
int getMmap(void **Addr, off_t &Size)
Definition: XrdOfs.cc:1669
int close()
Definition: XrdOfs.cc:875
char viaDel
Definition: XrdOfs.hh:206
const char * tident
Definition: XrdOfs.hh:201
int sync()
Definition: XrdOfs.cc:1718
XrdOfsHandle * oh
Definition: XrdOfs.hh:202
int dorawio
Definition: XrdOfs.hh:205
XrdOucChkPnt * myCKP
Definition: XrdOfs.hh:204
bool ckpBad
Definition: XrdOfs.hh:207
XrdOfsTPC * myTPC
Definition: XrdOfs.hh:203
virtual int fctl(const int cmd, const char *args, XrdOucErrInfo &eInfo)=0
int stat(struct stat *buf)
Definition: XrdOfs.cc:1690
int Retire(int &retc, long long *retsz=0, char *buff=0, int blen=0)
static void Hide(const char *thePath)
static const int opRW
int PoscGet(short &Mode, int Done=0)
static const int opPC
const char * Name()
void Suppress(int rrc=-EDOM, int wrc=-EDOM)
static int Alloc(const char *thePath, int Opts, XrdOfsHandle **Handle)
const char * PoscUsr()
XrdOssDF & Select(void)
int Del(const char *Lfn, int Offset, int Unlink=0)
Definition: XrdOfsPoscq.cc:159
int Commit(const char *Lfn, int Offset)
Definition: XrdOfsPoscq.cc:132
int Add(const char *Tident, const char *Lfn, bool isNew)
Definition: XrdOfsPoscq.cc:72
virtual int cancel(XrdSfsPrep &pargs, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)=0
virtual int begin(XrdSfsPrep &pargs, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)=0
virtual int query(XrdSfsPrep &pargs, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)=0
struct XrdOfsStats::StatsData Data
void Add(int &Cntr)
Definition: XrdOfsStats.hh:62
int Report(char *Buff, int Blen)
Definition: XrdOfsStats.cc:38
XrdSysMutex sdMutex
Definition: XrdOfsStats.hh:60
static int Authorize(XrdOfsTPC **theTPC, Facts &Args, int isPLE=0)
Definition: XrdOfsTPC.cc:221
virtual int Sync(XrdOucErrInfo *error)
Definition: XrdOfsTPC.hh:95
virtual void Del()
Definition: XrdOfsTPC.hh:79
static int Validate(XrdOfsTPC **theTPC, Facts &Args)
Definition: XrdOfsTPC.cc:550
void Connect(const XrdSecEntity *client=0)
Definition: XrdOfs.cc:2057
int chmod(const char *Name, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:1989
int truncate(const char *Name, XrdSfsFileOffset fileOffset, XrdOucErrInfo &out_error, const XrdSecEntity *client=0, const char *opaque=0)
Definition: XrdOfs.cc:2550
struct fwdOpt fwdTRUNC
Definition: XrdOfs.hh:420
void Disc(const XrdSecEntity *client=0)
Definition: XrdOfs.cc:2070
int prepare(XrdSfsPrep &pargs, XrdOucErrInfo &out_error, const XrdSecEntity *client=0)
Definition: XrdOfs.cc:2244
mode_t dMask[2]
Definition: XrdOfs.hh:389
const char * Split(const char *Args, const char **Opq, char *Path, int Plen)
Definition: XrdOfs.cc:2834
int myPort
Definition: XrdOfs.hh:385
XrdCmsClient * Finder
Definition: XrdOfs.hh:434
mode_t fMask[2]
Definition: XrdOfs.hh:390
static int EmsgType(int ecode)
Definition: XrdOfs.cc:2713
char * WaitTime(int, char *, int)
Definition: XrdOfs.cc:2930
struct fwdOpt fwdRMDIR
Definition: XrdOfs.hh:419
XrdOfsEvr evrObject
Definition: XrdOfs.hh:433
static int OSSDelay
Definition: XrdOfs.hh:423
char * ConfigFN
Definition: XrdOfs.hh:425
int tpcRdrPort[2]
Definition: XrdOfs.hh:395
@ RdrTPC
Definition: XrdOfs.hh:381
int mkdir(const char *dirName, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:2169
struct fwdOpt fwdMKPATH
Definition: XrdOfs.hh:416
XrdOfs()
Definition: XrdOfs.cc:169
char * tpcRdrHost[2]
Definition: XrdOfs.hh:394
int chksum(csFunc Func, const char *csName, const char *Path, XrdOucErrInfo &out_error, const XrdSecEntity *client=0, const char *opaque=0)
Definition: XrdOfs.cc:1877
int rename(const char *oldFileName, const char *newFileName, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *infoO=0, const char *infoN=0)
Definition: XrdOfs.cc:2352
int Options
Definition: XrdOfs.hh:384
struct fwdOpt fwdMKDIR
Definition: XrdOfs.hh:415
static int MaxDelay
Definition: XrdOfs.hh:422
struct fwdOpt fwdMV
Definition: XrdOfs.hh:417
static int Emsg(const char *, XrdOucErrInfo &, int, const char *x, XrdOfsHandle *hP, bool posChk=false, bool chktype=true)
Definition: XrdOfs.cc:2609
static int fsError(XrdOucErrInfo &myError, int rc)
Definition: XrdOfs.cc:2777
int FSctl(const int cmd, XrdSfsFSctl &args, XrdOucErrInfo &eInfo, const XrdSecEntity *client=0)
Definition: XrdOfsFSctl.cc:263
int stat(const char *Name, struct stat *buf, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:2457
struct fwdOpt fwdRM
Definition: XrdOfs.hh:418
int getStats(char *buff, int blen)
Definition: XrdOfs.cc:2146
struct fwdOpt fwdCHMOD
Definition: XrdOfs.hh:414
int Stall(XrdOucErrInfo &, int, const char *)
Definition: XrdOfs.cc:2851
int exists(const char *fileName, XrdSfsFileExistence &exists_flag, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:2083
void Unpersist(XrdOfsHandle *hP, int xcev=1)
Definition: XrdOfs.cc:2887
virtual int Fsync()
Definition: XrdOss.hh:172
virtual int StatRet(struct stat *buff)
Definition: XrdOss.hh:112
virtual int isCompressed(char *cxidp=0)
Definition: XrdOss.hh:215
virtual int Opendir(const char *path, XrdOucEnv &env)
Definition: XrdOss.hh:84
virtual int Clone(XrdOssDF &srcFile)
Definition: XrdOss.hh:127
virtual int Ftruncate(unsigned long long flen)
Definition: XrdOss.hh:192
virtual int Readdir(char *buff, int blen)
Definition: XrdOss.hh:97
virtual int Fstat(struct stat *buf)
Definition: XrdOss.hh:164
static const uint64_t Verify
all: Verify checksums
Definition: XrdOss.hh:251
virtual ssize_t ReadRaw(void *buffer, off_t offset, size_t size)
Definition: XrdOss.hh:359
virtual int Close(long long *retsz=0)=0
virtual int getFD()
Definition: XrdOss.hh:486
virtual ssize_t Read(off_t offset, size_t size)
Definition: XrdOss.hh:310
virtual int Fctl(int cmd, int alen, const char *args, char **resp=0)
Definition: XrdOss.cc:150
virtual int Fchmod(mode_t mode)
Definition: XrdOss.hh:148
static const int Fctl_ckpObj
Definition: XrdOss.hh:458
virtual ssize_t pgWrite(void *buffer, off_t offset, size_t wrlen, uint32_t *csvec, uint64_t opts)
Definition: XrdOss.cc:198
virtual ssize_t pgRead(void *buffer, off_t offset, size_t rdlen, uint32_t *csvec, uint64_t opts)
Definition: XrdOss.cc:160
static const uint16_t DF_isProxy
Object is a proxy object.
Definition: XrdOss.hh:434
virtual off_t getMmap(void **addr)
Definition: XrdOss.hh:204
virtual ssize_t ReadV(XrdOucIOVec *readV, int rdvcnt)
Definition: XrdOss.cc:252
uint16_t DFType()
Definition: XrdOss.hh:436
virtual bool getErrMsg(std::string &eText)
Definition: XrdOss.hh:478
virtual ssize_t Write(const void *buffer, off_t offset, size_t size)
Definition: XrdOss.hh:385
static const int Fctl_QFinfo
Definition: XrdOss.hh:461
virtual int Mkdir(const char *path, mode_t mode, int mkpath=0, XrdOucEnv *envP=0)=0
virtual bool getErrMsg(std::string &eText)
Definition: XrdOss.hh:680
virtual int Create(const char *tid, const char *path, mode_t mode, XrdOucEnv &env, int opts=0)=0
virtual XrdOssDF * newDir(const char *tident)=0
virtual void Connect(XrdOucEnv &env)
Definition: XrdOss.cc:42
virtual int Chmod(const char *path, mode_t mode, XrdOucEnv *envP=0)=0
virtual void Disc(XrdOucEnv &env)
Definition: XrdOss.cc:48
virtual int Lfn2Pfn(const char *Path, char *buff, int blen)
Definition: XrdOss.hh:954
virtual int Remdir(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
virtual int Rename(const char *oPath, const char *nPath, XrdOucEnv *oEnvP=0, XrdOucEnv *nEnvP=0)=0
virtual XrdOssDF * newFile(const char *tident)=0
virtual int Truncate(const char *path, unsigned long long fsize, XrdOucEnv *envP=0)=0
virtual int Stats(char *buff, int blen)
Definition: XrdOss.hh:788
virtual int Stat(const char *path, struct stat *buff, int opts=0, XrdOucEnv *envP=0)=0
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
virtual void Finished()=0
virtual int Restore(bool *readok=0)=0
virtual int Query(struct iov &range)=0
virtual int Write(struct iov *&range, int rnum)=0
virtual int Delete()=0
virtual int Truncate(struct iov *&range)=0
virtual int Create()=0
static int Format(char *buff, int blen, int ecode, const char *etxt1, const char *etxt2=0, const char *xtra=0)
Definition: XrdOucERoute.cc:44
char * Get(const char *varname)
Definition: XrdOucEnv.hh:69
void clear()
Reset data and error information to null. Any appenadges are released.
int setErrInfo(int code, const char *emsg)
char * getMsgBuff(int &mblen)
XrdOucEnv * getEnv()
const char * getErrUser()
void Reset()
Reset object to no message state. Call this method to release appendages.
int setErrCode(int code)
static void csCalc(const char *data, off_t offs, size_t count, uint32_t *csval)
static bool csVer(dataInfo &dInfo, off_t &bado, int &badc)
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
static const char * tpcDlgOn
Definition: XrdOucTPC.hh:68
static const char * tpcKey
Definition: XrdOucTPC.hh:58
bool Add(XrdSecAttr &attr)
XrdSecEntityAttr * eaAPI
non-const API to attributes
Definition: XrdSecEntity.hh:92
uint32_t * cksVec
Definition: XrdSfsAio.hh:63
ssize_t Result
Definition: XrdSfsAio.hh:65
virtual void doneRead()=0
struct aiocb sfsAio
Definition: XrdSfsAio.hh:62
virtual void doneWrite()=0
XrdOucErrInfo & error
static const uint64_t Verify
Options for pgRead() and pgWrite() as noted below.
XrdOucErrInfo & error
@ cpTrunc
Truncate a file within checkpoint.
@ cpDelete
Delete an existing checkpoint.
@ cpRestore
Restore an active checkpoint and delete it.
@ cpWrite
Add data to an existing checkpoint.
@ cpQuery
Return checkpoint limits.
@ cpCreate
Create a checkpoint, one must not be active.
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:116
int ec2errno(int ecode)
Definition: XrdSysError.cc:96
@ hex1
Definition: XrdSysTrace.hh:42
@ oct1
Definition: XrdSysTrace.hh:42
const char * Cmd
Definition: XrdOfs.hh:404
static const int uUrlOK
ucap: Supports async responses
static const int uLclF
ucap: Client is on a private net