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