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 // Do an fsync() on this file prior to closing if it was open r/w
854 //
855  if (ocFsync && hP->isRW) hP->Select().Fsync(); // Ignore errors
856 
857 // If this file was tagged as a POSC then we need to make sure it will persist
858 // Note that we unpersist the file immediately when it's inactive or if no hold
859 // time is allowed. Also, close events occur only for active handles. If the
860 // entry was via delete then we ignore the close return code as there is no
861 // one to handle it on the other side.
862 //
863  if ((poscNum = hP->PoscGet(theMode, !viaDel)))
864  {if (viaDel)
865  {if (hP->Inactive() || !XrdOfsFS->poscHold)
866  {XrdOfsFS->Unpersist(hP, !hP->Inactive()); hP->Retire(cRetc);}
867  else hP->Retire(hCB, XrdOfsFS->poscHold);
868  return SFS_OK;
869  }
870  if ((retc = hP->Select().Fchmod(theMode)))
871  XrdOfsFS->Emsg(epname, error, retc, "fchmod", hP->Name());
872  else {XrdOfsFS->poscQ->Del(hP->Name(), poscNum);
873  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Added(hP->Name());
874  }
875  }
876 
877 // Handle any oustanding checkpoint
878 //
879  if (myCKP)
880  {retc = myCKP->Restore();
881  if (retc) XrdOfsFS->Emsg(epname,error,retc,"restore chkpnt",hP->Name());
882  myCKP->Finished();
883  myCKP = 0;
884  }
885 
886 // We need to handle the cunudrum that an event may have to be sent upon
887 // the final close. However, that would cause the path name to be destroyed.
888 // So, we have two modes of logic where we copy out the pathname if a final
889 // close actually occurs. The path is not copied if it's not final and we
890 // don't bother with any of it if we need not generate an event.
891 //
892  if (XrdOfsFS->evsObject && tident
893  && XrdOfsFS->evsObject->Enabled(hP->isRW ? XrdOfsEvs::Closew
895  {long long FSize, *retsz;
896  char pathbuff[MAXPATHLEN+8];
897  XrdOfsEvs::Event theEvent;
898  if (hP->isRW) {theEvent = XrdOfsEvs::Closew; retsz = &FSize;}
899  else { theEvent = XrdOfsEvs::Closer; retsz = 0; FSize=0;}
900  if (!(hP->Retire(cRetc, retsz, pathbuff, sizeof(pathbuff))))
901  {XrdOfsEvsInfo evInfo(tident, pathbuff, "" , 0, 0, FSize);
902  XrdOfsFS->evsObject->Notify(theEvent, evInfo);
903  }
904  } else hP->Retire(cRetc);
905 
906 // All done
907 //
908  return (cRetc ? XrdOfsFS->Emsg(epname, error, cRetc, "close file") : SFS_OK);
909 }
910 
911 /******************************************************************************/
912 /* c h e c k p o i n t */
913 /******************************************************************************/
914 
915 int XrdOfsFile::checkpoint(XrdSfsFile::cpAct act, struct iov *range, int n)
916 {
917  EPNAME("chkpnt");
918  const char *ckpName;
919  int rc;
920  bool readok;
921 
922 // Make sure we are active
923 //
924  if (oh->Inactive()) return XrdOfsFS->Emsg(epname, error, EBADF,
925  "handle checkpoint", (const char *)0);
926 
927 // If checkpointing is disabled, the don't accept this request.
928 //
929  if (!XrdOfsConfigCP::Enabled) return XrdOfsFS->Emsg(epname, error, ENOTSUP,
930  "handle disabled checkpoint", (const char *)0);
931 
932 // If this checkpoint is bad then only a delete, query or restore is allowed.
933 //
934  if (ckpBad && (act == XrdSfsFile::cpTrunc || act == XrdSfsFile::cpWrite))
935  return XrdOfsFS->Emsg(epname, error, EIDRM, "extend checkpoint "
936  "(only delete or restore possible) for", oh->Name());
937 
938 // Handle the request
939 //
940  switch(act)
941  {case XrdSfsFile::cpCreate:
942  ckpName = "create checkpoint for";
943  if ((rc = CreateCKP())) return rc;
944  if ((rc = myCKP->Create())) {myCKP->Finished(); myCKP = 0;}
945  break;
947  ckpName = "delete checkpoint for";
948  if (!myCKP) rc = ENOENT;
949  else {rc = myCKP->Delete();
950  myCKP->Finished();
951  myCKP = 0;
952  ckpBad = false;
953  }
954  break;
955  case XrdSfsFile::cpQuery:
956  ckpName = "query checkpoint for";
957  if (!range || n <= 0)
958  return XrdOfsFS->Emsg(epname, error, EINVAL,
959  "query checkpoint limits for", oh->Name());
960  rc = (myCKP ? myCKP->Query(*range) : ENOENT);
961  break;
963  ckpName = "restore checkpoint for";
964  if (!myCKP) rc = ENOENT;
965  else {if (!(rc = myCKP->Restore(&readok)))
966  {myCKP->Finished();
967  myCKP = 0;
968  ckpBad = false;
969  } else {
970  if (!(oh->Select().DFType() & XrdOssDF::DF_isProxy))
971  oh->Suppress((readok ? 0 : -EDOM));
972  ckpBad = true;
973  }
974  }
975  break;
976  case XrdSfsFile::cpTrunc:
977  ckpName = "checkpoint truncate";
978  if (!range) rc = EINVAL;
979  else if (!myCKP) rc = ENOENT;
980  else if ((rc = myCKP->Truncate(range))) ckpBad = true;
981  break;
982  case XrdSfsFile::cpWrite:
983  ckpName = "checkpoint write";
984  if (!range || n <= 0) rc = EINVAL;
985  else if (!myCKP) rc = ENOENT;
986  else if ((rc = myCKP->Write(range, n))) ckpBad = true;
987  break;
988 
989  default: return XrdOfsFS->Emsg(epname, error, EINVAL,
990  "decode checkpoint request for", oh->Name());
991  };
992 
993 // Complete as needed
994 //
995  if (rc) return XrdOfsFS->Emsg(epname, error, rc, ckpName, oh->Name());
996 
997 // Trace success and return
998 //
999  FTRACE(chkpnt, ckpName);
1000  return SFS_OK;
1001 }
1002 
1003 /******************************************************************************/
1004 /* Private: C r e a t e C K P */
1005 /******************************************************************************/
1006 
1007 int XrdOfsFile::CreateCKP()
1008 {
1009 
1010 // Verify that a checkpoint does not exist
1011 //
1012  if (myCKP) return XrdOfsFS->Emsg("CreateCKP", error, EEXIST,
1013  "create checkpoint for", oh->Name());
1014 
1015 // Verify that this file is open r/w mode
1016 //
1017  if (!(oh->isRW)) return XrdOfsFS->Emsg("CreateCKP", error, ENOTTY,
1018  "create checkpoint for R/O", oh->Name());
1019 
1020 // POSC and checkpoints are mutally exclusive
1021 //
1022  if (oh->isRW == XrdOfsHandle::opPC)
1023  return XrdOfsFS->Emsg("CreateCKP", error, ENOTTY,
1024  "create checkpoint for POSC file", oh->Name());
1025 
1026 // Get a new checkpoint object
1027 //
1028  if (XrdOfsFS->OssIsProxy)
1029  {char *resp;
1030  int rc = oh->Select().Fctl(XrdOssDF::Fctl_ckpObj, 0, 0, &resp);
1031  if (rc) return XrdOfsFS->Emsg("CreateCKP", error, rc,
1032  "create proxy checkpoint");
1033  myCKP = (XrdOucChkPnt *)resp;
1034  } else myCKP = new XrdOfsChkPnt(oh->Select(), oh->Name());
1035 
1036 // All done
1037 //
1038  return 0;
1039 }
1040 
1041 /******************************************************************************/
1042 /* f c t l */
1043 /******************************************************************************/
1044 
1045 int XrdOfsFile::fctl(const int cmd,
1046  const char *args,
1047  XrdOucErrInfo &out_error)
1048 {
1049 // See if we can do this
1050 //
1051  if (cmd == SFS_FCTL_GETFD)
1052  {out_error.setErrCode(oh->Select().getFD());
1053  return SFS_OK;
1054  }
1055 
1056 // We don't support this
1057 //
1058  out_error.setErrInfo(ENOTSUP, "fctl operation not supported");
1059 
1060 // Return
1061 //
1062  return SFS_ERROR;
1063 }
1064 
1065 /******************************************************************************/
1066 
1067 int XrdOfsFile::fctl(const int cmd, int alen, const char *args,
1068  const XrdSecEntity *client)
1069 { // 12345678901234
1070  static const char *fctlArg = "ofs.tpc cancel";
1071  static const int fctlAsz = 15;
1072 
1073 // See if the is a tpc cancellation (the only thing we support here)
1074 //
1075  if (cmd != SFS_FCTL_SPEC1 || !args || alen < fctlAsz || strcmp(fctlArg,args))
1076  return XrdOfsFS->FSctl(*this, cmd, alen, args, client);
1077 
1078 // Check if we have a tpc operation in progress
1079 //
1080  if (!myTPC)
1081  {error.setErrInfo(ESRCH, "tpc operation not found");
1082  return SFS_ERROR;
1083  }
1084 
1085 // Cancel the tpc
1086 //
1087  myTPC->Del();
1088  myTPC = 0;
1089  return SFS_OK;
1090 }
1091 
1092 /******************************************************************************/
1093 /* p g R e a d */
1094 /******************************************************************************/
1095 
1097  char *buffer,
1098  XrdSfsXferSize rdlen,
1099  uint32_t *csvec,
1100  uint64_t opts)
1101 {
1102  EPNAME("pgRead");
1103  XrdSfsXferSize nbytes;
1104  uint64_t pgOpts;
1105 
1106 // If the oss plugin does not support pgRead and we doing rawio then simulate
1107 // the pgread. As this is relatively common we skip the vtable. This means
1108 // this class cannot be a inherited to override the read() method.
1109 //
1110  if (!XrdOfsFS->OssHasPGrw || dorawio)
1111  {if ((nbytes = XrdOfsFile::read(offset, buffer, rdlen)) > 0)
1112  XrdOucPgrwUtils::csCalc(buffer, offset, nbytes, csvec);
1113  return nbytes;
1114  }
1115 
1116 // Perform required tracing
1117 //
1118  FTRACE(read, rdlen <<"@" <<offset);
1119 
1120 // Make sure the offset is not too large
1121 //
1122 #if _FILE_OFFSET_BITS!=64
1123  if (offset > 0x000000007fffffff)
1124  return XrdOfsFS->Emsg(epname, error, EFBIG, "pgRead", oh->Name());
1125 #endif
1126 
1127 // Pass through any flags of interest
1128 //
1129  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1130  else pgOpts = 0;
1131 
1132 // Now read the actual number of bytes
1133 //
1134  nbytes = (XrdSfsXferSize)(oh->Select().pgRead((void *)buffer,
1135  (off_t)offset, (size_t)rdlen, csvec, pgOpts));
1136  if (nbytes < 0)
1137  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "pgRead", oh->Name());
1138 
1139 // Return number of bytes read
1140 //
1141  return nbytes;
1142 }
1143 
1144 /******************************************************************************/
1145 
1147 {
1148  EPNAME("aiopgread");
1149  uint64_t pgOpts;
1150  int rc;
1151 
1152 // If the oss plugin does not support pgRead or if we are doing rawio or the
1153 // file is compressed then revert to using a standard async read. Note that
1154 // the standard async read will generate checksums if a vector is present.
1155 // Note: we set cksVec in the request to nil to indicate simulation!
1156 //
1157  if (!XrdOfsFS->OssHasPGrw || dorawio || oh->isCompressed)
1158  {aioparm->cksVec = 0;
1159  return XrdOfsFile::read(aioparm);
1160  }
1161 
1162 // Perform required tracing
1163 //
1164  FTRACE(aio, aioparm->sfsAio.aio_nbytes <<"@" <<aioparm->sfsAio.aio_offset);
1165 
1166 // Make sure the offset is not too large
1167 //
1168 #if _FILE_OFFSET_BITS!=64
1169  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1170  return XrdOfsFS->Emsg(epname, error, EFBIG, "pgRead", oh->Name());
1171 #endif
1172 
1173 // Pass through any flags of interest
1174 //
1175  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1176  else pgOpts = 0;
1177 
1178 // Issue the read. Only true errors are returned here.
1179 //
1180  if ((rc = oh->Select().pgRead(aioparm, pgOpts)) < 0)
1181  return XrdOfsFS->Emsg(epname, error, rc, "pgRead", oh->Name());
1182 
1183 // All done
1184 //
1185  return SFS_OK;
1186 }
1187 
1188 /******************************************************************************/
1189 /* p g W r i t e */
1190 /******************************************************************************/
1191 
1193  char *buffer,
1194  XrdSfsXferSize wrlen,
1195  uint32_t *csvec,
1196  uint64_t opts)
1197 {
1198  EPNAME("pgWrite");
1199  XrdSfsXferSize nbytes;
1200  uint64_t pgOpts;
1201 
1202 // If the oss plugin does not support pgWrite revert to using a standard write.
1203 //
1204  if (!XrdOfsFS->OssHasPGrw)
1205  {if ((opts & XrdSfsFile::Verify)
1206  && !VerPgw(buffer, offset, wrlen, csvec, oh, error)) return SFS_ERROR;
1207  return XrdOfsFile::write(offset, buffer, wrlen);
1208  }
1209 
1210 // Perform any required tracing
1211 //
1212  FTRACE(write, wrlen <<"@" <<offset);
1213 
1214 // Make sure the offset is not too large
1215 //
1216 #if _FILE_OFFSET_BITS!=64
1217  if (offset > 0x000000007fffffff)
1218  return XrdOfsFS->Emsg(epname, error, EFBIG, "pgwrite", oh);
1219 #endif
1220 
1221 // Silly Castor stuff
1222 //
1223  if (XrdOfsFS->evsObject && !(oh->isChanged)
1224  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1225 
1226 // Pass through any flags of interest
1227 //
1228  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1229  else pgOpts = 0;
1230 
1231 // Write the requested bytes
1232 //
1233  oh->isPending = 1;
1234  nbytes = (XrdSfsXferSize)(oh->Select().pgWrite((void *)buffer,
1235  (off_t)offset, (size_t)wrlen, csvec, pgOpts));
1236  if (nbytes < 0)
1237  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "pgwrite", oh);
1238 
1239 // Return number of bytes written
1240 //
1241  return nbytes;
1242 }
1243 
1244 /******************************************************************************/
1245 
1247 {
1248  EPNAME("aiopgWrite");
1249  uint64_t pgOpts;
1250  int rc;
1251 
1252 // If the oss plugin does not support pgWrite revert to using a standard write.
1253 //
1254  if (!XrdOfsFS->OssHasPGrw)
1255  {if ((opts & XrdSfsFile::Verify)
1256  && !VerPgw((char *)aioparm->sfsAio.aio_buf,
1257  aioparm->sfsAio.aio_offset,
1258  aioparm->sfsAio.aio_nbytes,
1259  aioparm->cksVec, oh, error)) return SFS_ERROR;
1260  return XrdOfsFile::write(aioparm);
1261  }
1262 
1263 // If this is a POSC file, we must convert the async call to a sync call as we
1264 // must trap any errors that unpersist the file. We can't do that via aio i/f.
1265 //
1266  if (oh->isRW == XrdOfsHandle::opPC)
1267  {aioparm->Result = XrdOfsFile::pgWrite(aioparm->sfsAio.aio_offset,
1268  (char *)aioparm->sfsAio.aio_buf,
1269  aioparm->sfsAio.aio_nbytes,
1270  aioparm->cksVec, opts);
1271  aioparm->doneWrite();
1272  return SFS_OK;
1273  }
1274 
1275 // Perform any required tracing
1276 //
1277  FTRACE(aio, aioparm->sfsAio.aio_nbytes <<"@" <<aioparm->sfsAio.aio_offset);
1278 
1279 // Make sure the offset is not too large
1280 //
1281 #if _FILE_OFFSET_BITS!=64
1282  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1283  return XrdOfsFS->Emsg(epname, error, EFBIG, "pgwrite", oh->Name());
1284 #endif
1285 
1286 // Silly Castor stuff
1287 //
1288  if (XrdOfsFS->evsObject && !(oh->isChanged)
1289  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1290 
1291 // Pass through any flags of interest
1292 //
1293  if (opts & XrdSfsFile::Verify) pgOpts = XrdOssDF::Verify;
1294  else pgOpts = 0;
1295 
1296 // Write the requested bytes
1297 //
1298  oh->isPending = 1;
1299  if ((rc = oh->Select().pgWrite(aioparm, pgOpts)) < 0)
1300  return XrdOfsFS->Emsg(epname, error, rc, "pgwrite", oh->Name());
1301 
1302 // All done
1303 //
1304  return SFS_OK;
1305 }
1306 
1307 /******************************************************************************/
1308 /* r e a d */
1309 /******************************************************************************/
1310 
1312  XrdSfsXferSize blen) // In
1313 /*
1314  Function: Preread `blen' bytes at `offset'
1315 
1316  Input: offset - The absolute byte offset at which to start the read.
1317  blen - The amount to preread.
1318 
1319  Output: Returns SFS_OK upon success and SFS_ERROR o/w.
1320 */
1321 {
1322  EPNAME("read");
1323  int retc;
1324 
1325 // Perform required tracing
1326 //
1327  FTRACE(read, "preread " <<blen <<"@" <<offset);
1328 
1329 // Make sure the offset is not too large
1330 //
1331 #if _FILE_OFFSET_BITS!=64
1332  if (offset > 0x000000007fffffff)
1333  return XrdOfsFS->Emsg(epname, error, EFBIG, "read", oh->Name());
1334 #endif
1335 
1336 // Now preread the actual number of bytes
1337 //
1338  if ((retc = oh->Select().Read((off_t)offset, (size_t)blen)) < 0)
1339  return XrdOfsFS->Emsg(epname, error, (int)retc, "preread", oh->Name());
1340 
1341 // Return number of bytes read
1342 //
1343  return retc;
1344 }
1345 
1346 /******************************************************************************/
1347 /* r e a d */
1348 /******************************************************************************/
1349 
1351  char *buff, // Out
1352  XrdSfsXferSize blen) // In
1353 /*
1354  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
1355  number of bytes read.
1356 
1357  Input: offset - The absolute byte offset at which to start the read.
1358  buff - Address of the buffer in which to place the data.
1359  blen - The size of the buffer. This is the maximum number
1360  of bytes that will be read from 'fd'.
1361 
1362  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
1363 */
1364 {
1365  EPNAME("read");
1366  XrdSfsXferSize nbytes;
1367 
1368 // Perform required tracing
1369 //
1370  FTRACE(read, blen <<"@" <<offset);
1371 
1372 // Make sure the offset is not too large
1373 //
1374 #if _FILE_OFFSET_BITS!=64
1375  if (offset > 0x000000007fffffff)
1376  return XrdOfsFS->Emsg(epname, error, EFBIG, "read", oh->Name());
1377 #endif
1378 
1379 // Now read the actual number of bytes
1380 //
1381  nbytes = (dorawio ?
1382  (XrdSfsXferSize)(oh->Select().ReadRaw((void *)buff,
1383  (off_t)offset, (size_t)blen))
1384  : (XrdSfsXferSize)(oh->Select().Read((void *)buff,
1385  (off_t)offset, (size_t)blen)));
1386  if (nbytes < 0)
1387  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "read", oh->Name());
1388 
1389 // Return number of bytes read
1390 //
1391  return nbytes;
1392 }
1393 
1394 /******************************************************************************/
1395 /* r e a d v */
1396 /******************************************************************************/
1397 
1399  int readCount) // In
1400 /*
1401  Function: Perform all the reads specified in the readV vector.
1402 
1403  Input: readV - A description of the reads to perform; includes the
1404  absolute offset, the size of the read, and the buffer
1405  to place the data into.
1406  readCount - The size of the readV vector.
1407 
1408  Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
1409  If the number of bytes read is less than requested, it is considered
1410  an error.
1411 */
1412 {
1413  EPNAME("readv");
1414 
1415  XrdSfsXferSize nbytes = oh->Select().ReadV(readV, readCount);
1416  if (nbytes < 0)
1417  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "readv", oh->Name());
1418 
1419  return nbytes;
1420 
1421 }
1422 
1423 /******************************************************************************/
1424 /* r e a d A I O */
1425 /******************************************************************************/
1426 
1427 /*
1428  Function: Read `blen' bytes at `offset' into 'buff' and return the actual
1429  number of bytes read using asynchronous I/O, if possible.
1430 
1431  Output: Returns the 0 if successfullt queued, otherwise returns an error.
1432  The underlying implementation will convert the request to
1433  synchronous I/O is async mode is not possible.
1434 */
1435 
1437 {
1438  EPNAME("aioread");
1439  int rc;
1440 
1441 // Async mode for compressed files is not supported.
1442 //
1443  if (oh->isCompressed)
1444  {aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
1445  (char *)aiop->sfsAio.aio_buf,
1447  aiop->doneRead();
1448  return 0;
1449  }
1450 
1451 // Perform required tracing
1452 //
1453  FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
1454 
1455 // Make sure the offset is not too large
1456 //
1457 #if _FILE_OFFSET_BITS!=64
1458  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1459  return XrdOfsFS->Emsg(epname, error, EFBIG, "read", oh->Name());
1460 #endif
1461 
1462 // Issue the read. Only true errors are returned here.
1463 //
1464  if ((rc = oh->Select().Read(aiop)) < 0)
1465  return XrdOfsFS->Emsg(epname, error, rc, "read", oh->Name());
1466 
1467 // All done
1468 //
1469  return SFS_OK;
1470 }
1471 
1472 /******************************************************************************/
1473 /* w r i t e */
1474 /******************************************************************************/
1475 
1477  const char *buff, // Out
1478  XrdSfsXferSize blen) // In
1479 /*
1480  Function: Write `blen' bytes at `offset' from 'buff' and return the actual
1481  number of bytes written.
1482 
1483  Input: offset - The absolute byte offset at which to start the write.
1484  buff - Address of the buffer from which to get the data.
1485  blen - The size of the buffer. This is the maximum number
1486  of bytes that will be written to 'fd'.
1487 
1488  Output: Returns the number of bytes written upon success and SFS_ERROR o/w.
1489 
1490  Notes: An error return may be delayed until the next write(), close(), or
1491  sync() call.
1492 */
1493 {
1494  EPNAME("write");
1495  XrdSfsXferSize nbytes;
1496 
1497 // Perform any required tracing
1498 //
1499  FTRACE(write, blen <<"@" <<offset);
1500 
1501 // Make sure the offset is not too large
1502 //
1503 #if _FILE_OFFSET_BITS!=64
1504  if (offset > 0x000000007fffffff)
1505  return XrdOfsFS->Emsg(epname, error, EFBIG, "write", oh);
1506 #endif
1507 
1508 // Silly Castor stuff
1509 //
1510  if (XrdOfsFS->evsObject && !(oh->isChanged)
1511  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1512 
1513 // Write the requested bytes
1514 //
1515  oh->isPending = 1;
1516  nbytes = (XrdSfsXferSize)(oh->Select().Write((const void *)buff,
1517  (off_t)offset, (size_t)blen));
1518  if (nbytes < 0)
1519  return XrdOfsFS->Emsg(epname, error, (int)nbytes, "write", oh);
1520 
1521 // Return number of bytes written
1522 //
1523  return nbytes;
1524 }
1525 
1526 /******************************************************************************/
1527 /* w r i t e A I O */
1528 /******************************************************************************/
1529 
1530 // For now, this reverts to synchronous I/O
1531 //
1533 {
1534  EPNAME("aiowrite");
1535  int rc;
1536 
1537 // Perform any required tracing
1538 //
1539  FTRACE(aio, aiop->sfsAio.aio_nbytes <<"@" <<aiop->sfsAio.aio_offset);
1540 
1541 // If this is a POSC file, we must convert the async call to a sync call as we
1542 // must trap any errors that unpersist the file. We can't do that via aio i/f.
1543 //
1544  if (oh->isRW == XrdOfsHandle::opPC)
1545  {aiop->Result = this->write(aiop->sfsAio.aio_offset,
1546  (const char *)aiop->sfsAio.aio_buf,
1547  aiop->sfsAio.aio_nbytes);
1548  aiop->doneWrite();
1549  return 0;
1550  }
1551 
1552 // Make sure the offset is not too large
1553 //
1554 #if _FILE_OFFSET_BITS!=64
1555  if (aiop->sfsAio.aio_offset > 0x000000007fffffff)
1556  return XrdOfsFS->Emsg(epname, error, EFBIG, "write", oh->Name());
1557 #endif
1558 
1559 // Silly Castor stuff
1560 //
1561  if (XrdOfsFS->evsObject && !(oh->isChanged)
1562  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1563 
1564 // Write the requested bytes
1565 //
1566  oh->isPending = 1;
1567  if ((rc = oh->Select().Write(aiop)) < 0)
1568  return XrdOfsFS->Emsg(epname, error, rc, "write", oh->Name());
1569 
1570 // All done
1571 //
1572  return SFS_OK;
1573 }
1574 
1575 /******************************************************************************/
1576 /* g e t M m a p */
1577 /******************************************************************************/
1578 
1579 int XrdOfsFile::getMmap(void **Addr, off_t &Size) // Out
1580 /*
1581  Function: Return memory mapping for file, if any.
1582 
1583  Output: Addr - Address of memory location
1584  Size - Size of the file or zero if not memory mapped.
1585  Returns SFS_OK upon success and SFS_ERROR upon failure.
1586 */
1587 {
1588 
1589 // Perform the function
1590 //
1591  Size = oh->Select().getMmap(Addr);
1592 
1593  return SFS_OK;
1594 }
1595 
1596 /******************************************************************************/
1597 /* s t a t */
1598 /******************************************************************************/
1599 
1600 int XrdOfsFile::stat(struct stat *buf) // Out
1601 /*
1602  Function: Return file status information
1603 
1604  Input: buf - The stat structiure to hold the results
1605 
1606  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1607 */
1608 {
1609  EPNAME("fstat");
1610  int retc;
1611 
1612 // Perform any required tracing
1613 //
1614  FTRACE(stat, "");
1615 
1616 // Perform the function
1617 //
1618  if ((retc = oh->Select().Fstat(buf)) < 0)
1619  return XrdOfsFS->Emsg(epname,error,retc,"get state for",oh->Name());
1620 
1621  return SFS_OK;
1622 }
1623 
1624 /******************************************************************************/
1625 /* s y n c */
1626 /******************************************************************************/
1627 
1628 int XrdOfsFile::sync() // In
1629 /*
1630  Function: Commit all unwritten bytes to physical media.
1631 
1632  Input: n/a
1633 
1634  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1635 */
1636 {
1637  EPNAME("sync");
1638  int retc;
1639 
1640 // Perform any required tracing
1641 //
1642  FTRACE(sync, "");
1643 
1644 // If we have a tpc object hanging about, we need to dispatch that first
1645 //
1646  if (myTPC && (retc = myTPC->Sync(&error))) return retc;
1647 
1648 // We can test the pendio flag w/o a lock because the person doing this
1649 // sync must have done the previous write. Causality is the synchronizer.
1650 //
1651  if (!(oh->isPending)) return SFS_OK;
1652 
1653 // We can also skip the sync if the file is closed. However, we need a file
1654 // object lock in order to test the flag. We can also reset the PENDIO flag.
1655 //
1656  oh->Lock();
1657  oh->isPending = 0;
1658  oh->UnLock();
1659 
1660 // Perform the function
1661 //
1662  if ((retc = oh->Select().Fsync()))
1663  {oh->isPending = 1;
1664  return XrdOfsFS->Emsg(epname, error, retc, "synchronize", oh);
1665  }
1666 
1667 // Indicate all went well
1668 //
1669  return SFS_OK;
1670 }
1671 
1672 /******************************************************************************/
1673 /* s y n c A I O */
1674 /******************************************************************************/
1675 
1676 // For now, reverts to synchronous case. This must also be the case for POSC!
1677 //
1679 {
1680  aiop->Result = this->sync();
1681  aiop->doneWrite();
1682  return 0;
1683 }
1684 
1685 /******************************************************************************/
1686 /* t r u n c a t e */
1687 /******************************************************************************/
1688 
1690 /*
1691  Function: Set the length of the file object to 'flen' bytes.
1692 
1693  Input: flen - The new size of the file.
1694 
1695  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1696 
1697  Notes: If 'flen' is smaller than the current size of the file, the file
1698  is made smaller and the data past 'flen' is discarded. If 'flen'
1699  is larger than the current size of the file, a hole is created
1700  (i.e., the file is logically extended by filling the extra bytes
1701  with zeroes).
1702 */
1703 {
1704  EPNAME("trunc");
1705  int retc;
1706 
1707 // Lock the file handle and perform any tracing
1708 //
1709  FTRACE(truncate, "len=" <<flen);
1710 
1711 // Make sure the offset is not too large
1712 //
1713  if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
1714  return XrdOfsFS->Emsg(epname, error, EFBIG, "truncate", oh);
1715 
1716 // Silly Castor stuff
1717 //
1718  if (XrdOfsFS->evsObject && !(oh->isChanged)
1719  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Fwrite)) GenFWEvent();
1720 
1721 // Perform the function
1722 //
1723  oh->isPending = 1;
1724  if ((retc = oh->Select().Ftruncate(flen)))
1725  return XrdOfsFS->Emsg(epname, error, retc, "truncate", oh);
1726 
1727 // Indicate Success
1728 //
1729  return SFS_OK;
1730 }
1731 
1732 /******************************************************************************/
1733 /* g e t C X i n f o */
1734 /******************************************************************************/
1735 
1736 int XrdOfsFile::getCXinfo(char cxtype[4], int &cxrsz)
1737 /*
1738  Function: Set the length of the file object to 'flen' bytes.
1739 
1740  Input: n/a
1741 
1742  Output: cxtype - Compression algorithm code
1743  cxrsz - Compression region size
1744 
1745  Returns SFS_OK upon success and SFS_ERROR upon failure.
1746 */
1747 {
1748 
1749 // Copy out the info
1750 //
1751  cxrsz = oh->Select().isCompressed(cxtype);
1752  return SFS_OK;
1753 }
1754 
1755 /******************************************************************************/
1756 /* P r i v a t e F i l e M e t h o d s */
1757 /******************************************************************************/
1758 /******************************************************************************/
1759 /* protected G e n F W E v e n t */
1760 /******************************************************************************/
1761 
1762 void XrdOfsFile::GenFWEvent()
1763 {
1764  int first_write;
1765 
1766 // This silly code is to generate a 1st write event which slows things down
1767 // but is needed by the one and only Castor. What a big sigh!
1768 //
1769  oh->Lock();
1770  if ((first_write = !(oh->isChanged))) oh->isChanged = 1;
1771  oh->UnLock();
1772  if (first_write)
1773  {XrdOfsEvsInfo evInfo(tident, oh->Name());
1774  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Fwrite, evInfo);
1775  }
1776 }
1777 
1778 /******************************************************************************/
1779 /* */
1780 /* 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 */
1781 /* */
1782 /******************************************************************************/
1783 /******************************************************************************/
1784 /* c h k s u m */
1785 /******************************************************************************/
1786 
1787 int XrdOfs::chksum( csFunc Func, // In
1788  const char *csName, // In
1789  const char *Path, // In
1790  XrdOucErrInfo &einfo, // Out
1791  const XrdSecEntity *client, // In
1792  const char *opaque) // In
1793 /*
1794  Function: Compute and return file checksum.
1795 
1796  Input: Func - Function to be performed:
1797  csCalc - Return precomputed or computed checksum.
1798  csGet - Return precomputed checksum.
1799  csSize - Verify csName and get its size.
1800  Path - Pathname of file for csCalc and csSize.
1801  einfo - Error information object to hold error details.
1802  client - Authentication credentials, if any.
1803  opaque - Opaque information to be used as seen fit.
1804 
1805  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1806 */
1807 {
1808  EPNAME("chksum");
1809  XrdOucEnv cksEnv(opaque,0,client);
1810  XrdCksData cksData;
1811  const char *tident = einfo.getErrUser();
1812  char buff[MAXPATHLEN+8];
1813  int rc;
1814 
1815 // Check if we support checksumming
1816 //
1817  if (!Cks)
1818  {einfo.setErrInfo(ENOTSUP, "Checksums are not supported.");
1819  return SFS_ERROR;
1820  }
1821 
1822 // A csSize request is issued usually once to verify everything is working. We
1823 // take this opportunity to also verify the checksum name.
1824 //
1825  rc = cksData.Set(csName);
1826  if (!rc || Func == XrdSfsFileSystem::csSize)
1827  {if (rc && (rc = Cks->Size(csName)))
1828  {einfo.setErrCode(rc); return SFS_OK;}
1829  strcpy(buff, csName); strcat(buff, " checksum not supported.");
1830  einfo.setErrInfo(ENOTSUP, buff);
1831  return SFS_ERROR;
1832  }
1833 
1834 // Everything else requires a path
1835 //
1836  if (!Path)
1837  {strcpy(buff, csName);
1838  strcat(buff, " checksum path not specified.");
1839  einfo.setErrInfo(EINVAL, buff);
1840  return SFS_ERROR;
1841  }
1842 
1843 // Apply security, as needed
1844 //
1845  XTRACE(stat, Path, csName);
1846  AUTHORIZE(client,&cksEnv,AOP_Stat,"checksum",Path,einfo);
1847 
1848 // If we are a menager then we need to redirect the client to where the file is
1849 //
1850  if (CksRdr && Finder && Finder->isRemote()
1851  && (rc = Finder->Locate(einfo, Path, SFS_O_RDONLY, &cksEnv)))
1852  return fsError(einfo, rc);
1853 
1854 // At this point we need to convert the lfn to a pfn
1855 //
1856  if (CksPfn && !(Path = XrdOfsOss->Lfn2Pfn(Path, buff, MAXPATHLEN, rc)))
1857  return Emsg(epname, einfo, rc, "checksum", Path);
1858 
1859 // Originally we only passed he env pointer for proxy servers. Due to popular
1860 // demand, we always pass the env as it points to the SecEntity object unless
1861 // we don't have it then we pass the caller's environment.
1862 //
1863  if (Func == XrdSfsFileSystem::csGet || Func == XrdSfsFileSystem::csCalc)
1864  {if (client) cksData.envP = &cksEnv;
1865  else cksData.envP = (einfo.getEnv() ? einfo.getEnv() : &cksEnv);
1866  }
1867 
1868 // Now determine what to do
1869 //
1870  if (Func == XrdSfsFileSystem::csCalc) rc = Cks->Calc(Path, cksData);
1871  else if (Func == XrdSfsFileSystem::csGet) rc = Cks->Get( Path, cksData);
1872  else {einfo.setErrInfo(EINVAL, "Invalid checksum function.");
1873  return SFS_ERROR;
1874  }
1875 
1876 // See if all went well
1877 //
1878 #ifdef ENOATTR
1879  if (rc >= 0 || rc == -ENOATTR || rc == -ESTALE || rc == -ESRCH)
1880 #else
1881  if (rc >= 0 || rc == -ENODATA || rc == -ESTALE || rc == -ESRCH)
1882 #endif
1883  {if (rc >= 0) {cksData.Get(buff, MAXPATHLEN); rc = 0;}
1884  else {*buff = 0; rc = -rc;}
1885  einfo.setErrInfo(rc, buff);
1886  return SFS_OK;
1887  }
1888 
1889 // We failed
1890 //
1891  return Emsg(epname, einfo, rc, "checksum", Path);
1892 }
1893 
1894 /******************************************************************************/
1895 /* c h m o d */
1896 /******************************************************************************/
1897 
1898 int XrdOfs::chmod(const char *path, // In
1899  XrdSfsMode Mode, // In
1900  XrdOucErrInfo &einfo, // Out
1901  const XrdSecEntity *client, // In
1902  const char *info) // In
1903 /*
1904  Function: Change the mode on a file or directory.
1905 
1906  Input: path - Is the fully qualified name of the file to be removed.
1907  einfo - Error information object to hold error details.
1908  client - Authentication credentials, if any.
1909  info - Opaque information to be used as seen fit.
1910 
1911  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
1912 */
1913 {
1914  EPNAME("chmod");
1915  static const int locFlags = SFS_O_RDWR|SFS_O_META;
1916  struct stat Stat;
1917  mode_t acc_mode = Mode & S_IAMB;
1918  const char *tident = einfo.getErrUser();
1919  XrdOucEnv chmod_Env(info,0,client);
1920  int retc;
1921  XTRACE(chmod, path, "");
1922 
1923 // Apply security, as needed
1924 //
1925  AUTHORIZE(client,&chmod_Env,AOP_Chmod,"chmod",path,einfo);
1926 
1927 // Find out where we should chmod this file
1928 //
1929  if (Finder && Finder->isRemote())
1930  {if (fwdCHMOD.Cmd)
1931  {char buff[8];
1932  sprintf(buff, "%o", static_cast<int>(acc_mode));
1933  if (Forward(retc,einfo,fwdCHMOD,path,buff,&chmod_Env)) return retc;
1934  }
1935  else if ((retc = Finder->Locate(einfo, path, locFlags, &chmod_Env)))
1936  return fsError(einfo, retc);
1937  }
1938 
1939 // We need to adjust the mode based on whether this is a file or directory.
1940 //
1941  if ((retc = XrdOfsOss->Stat(path, &Stat, 0, &chmod_Env)))
1942  return XrdOfsFS->Emsg(epname, einfo, retc, "change", path);
1943  if (S_ISDIR(Stat.st_mode)) acc_mode = (acc_mode | dMask[0]) & dMask[1];
1944  else acc_mode = (acc_mode | fMask[0]) & fMask[1];
1945 
1946 // Check if we should generate an event
1947 //
1948  if (evsObject && evsObject->Enabled(XrdOfsEvs::Chmod))
1949  {XrdOfsEvsInfo evInfo(tident, path, info, &chmod_Env, acc_mode);
1950  evsObject->Notify(XrdOfsEvs::Chmod, evInfo);
1951  }
1952 
1953 // Now try to find the file or directory
1954 //
1955  if (!(retc = XrdOfsOss->Chmod(path, acc_mode, &chmod_Env))) return SFS_OK;
1956 
1957 // An error occurred, return the error info
1958 //
1959  return XrdOfsFS->Emsg(epname, einfo, retc, "change", path);
1960 }
1961 
1962 /******************************************************************************/
1963 /* C o n n e c t */
1964 /******************************************************************************/
1965 
1966 void XrdOfs::Connect(const XrdSecEntity *client)
1967 {
1968  XrdOucEnv myEnv(0, 0, client);
1969 
1970 // Pass this call along
1971 //
1972  XrdOfsOss->Connect(myEnv);
1973 }
1974 
1975 /******************************************************************************/
1976 /* D i s c */
1977 /******************************************************************************/
1978 
1979 void XrdOfs::Disc(const XrdSecEntity *client)
1980 {
1981  XrdOucEnv myEnv(0, 0, client);
1982 
1983 // Pass this call along
1984 //
1985  XrdOfsOss->Disc(myEnv);
1986 }
1987 
1988 /******************************************************************************/
1989 /* e x i s t s */
1990 /******************************************************************************/
1991 
1992 int XrdOfs::exists(const char *path, // In
1993  XrdSfsFileExistence &file_exists, // Out
1994  XrdOucErrInfo &einfo, // Out
1995  const XrdSecEntity *client, // In
1996  const char *info) // In
1997 /*
1998  Function: Determine if file 'path' actually exists.
1999 
2000  Input: path - Is the fully qualified name of the file to be tested.
2001  file_exists - Is the address of the variable to hold the status of
2002  'path' when success is returned. The values may be:
2003  XrdSfsFileExistsIsDirectory - file not found but path is valid.
2004  XrdSfsFileExistsIsFile - file found.
2005  XrdSfsFileExistsIsNo - neither file nor directory.
2006  einfo - Error information object holding the details.
2007  client - Authentication credentials, if any.
2008  info - Opaque information to be used as seen fit.
2009 
2010  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2011 
2012  Notes: When failure occurs, 'file_exists' is not modified.
2013 */
2014 {
2015  EPNAME("exists");
2016  struct stat fstat;
2017  int retc;
2018  const char *tident = einfo.getErrUser();
2019  XrdOucEnv stat_Env(info,0,client);
2020  XTRACE(exists, path, "");
2021 
2022 // Apply security, as needed
2023 //
2024  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2025 
2026 // Find out where we should stat this file
2027 //
2028  if (Finder && Finder->isRemote()
2029  && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY, &stat_Env)))
2030  return fsError(einfo, retc);
2031 
2032 // Now try to find the file or directory
2033 //
2034  retc = XrdOfsOss->Stat(path, &fstat, 0, &stat_Env);
2035  if (!retc)
2036  { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
2037  else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
2038  else file_exists=XrdSfsFileExistNo;
2039  return SFS_OK;
2040  }
2041  if (retc == -ENOENT)
2042  {file_exists=XrdSfsFileExistNo;
2043  return SFS_OK;
2044  }
2045 
2046 // An error occurred, return the error info
2047 //
2048  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path);
2049 }
2050 
2051 /******************************************************************************/
2052 /* g e t S t a t s */
2053 /******************************************************************************/
2054 
2055 int XrdOfs::getStats(char *buff, int blen)
2056 {
2057  int n;
2058 
2059 // See if the size just wanted
2060 //
2061  if (!buff) return OfsStats.Report(0,0) + XrdOfsOss->Stats(0,0);
2062 
2063 // Report ofs info followed by the oss info
2064 //
2065  n = OfsStats.Report(buff, blen);
2066  buff += n; blen -= n;
2067  n += XrdOfsOss->Stats(buff, blen);
2068 
2069 // All done
2070 //
2071  return n;
2072 }
2073 
2074 /******************************************************************************/
2075 /* m k d i r */
2076 /******************************************************************************/
2077 
2078 int XrdOfs::mkdir(const char *path, // In
2079  XrdSfsMode Mode, // In
2080  XrdOucErrInfo &einfo, // Out
2081  const XrdSecEntity *client, // In
2082  const char *info) // In
2083 /*
2084  Function: Create a directory entry.
2085 
2086  Input: path - Is the fully qualified name of the file to be removed.
2087  Mode - Is the POSIX mode value the directory is to have.
2088  Additionally, Mode may contain SFS_O_MKPTH if the
2089  full dircectory path should be created.
2090  einfo - Error information object to hold error details.
2091  client - Authentication credentials, if any.
2092  info - Opaque information to be used as seen fit.
2093 
2094  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2095 */
2096 {
2097  EPNAME("mkdir");
2098  static const int LocOpts = SFS_O_RDWR | SFS_O_CREAT | SFS_O_META;
2099  mode_t acc_mode = (Mode | dMask[0]) & dMask[1];
2100  int retc, mkpath = Mode & SFS_O_MKPTH;
2101  const char *tident = einfo.getErrUser();
2102  XrdOucEnv mkdir_Env(info,0,client);
2103  XTRACE(mkdir, path, "");
2104 
2105 // Apply security, as needed
2106 //
2107  AUTHORIZE(client,&mkdir_Env,AOP_Mkdir,"mkdir",path,einfo);
2108 
2109 // Find out where we should remove this file
2110 //
2111  if (Finder && Finder->isRemote())
2112  {if (fwdMKDIR.Cmd)
2113  {char buff[8];
2114  sprintf(buff, "%o", static_cast<int>(acc_mode));
2115  if (Forward(retc, einfo, (mkpath ? fwdMKPATH:fwdMKDIR),
2116  path, buff, &mkdir_Env)) return retc;
2117  }
2118  else if ((retc = Finder->Locate(einfo,path,LocOpts,&mkdir_Env)))
2119  return fsError(einfo, retc);
2120  }
2121 
2122 // Perform the actual operation
2123 //
2124  if ((retc = XrdOfsOss->Mkdir(path, acc_mode, mkpath, &mkdir_Env)))
2125  return XrdOfsFS->Emsg(epname, einfo, retc, "mkdir", path);
2126 
2127 // Check if we should generate an event
2128 //
2129  if (evsObject && evsObject->Enabled(XrdOfsEvs::Mkdir))
2130  {XrdOfsEvsInfo evInfo(tident, path, info, &mkdir_Env, acc_mode);
2131  evsObject->Notify(XrdOfsEvs::Mkdir, evInfo);
2132  }
2133 
2134 // If we have a redirector, tell it that we now have this path
2135 //
2136  if (Balancer)
2137  {if (!mkpath) Balancer->Added(path);
2138  else {char *slash, *myPath = strdup(path);
2139  do {Balancer->Added(myPath);
2140  if ((slash = rindex(myPath, '/'))) *slash = 0;
2141  } while(slash && slash != myPath);
2142  free(myPath);
2143  }
2144  }
2145 
2146  return SFS_OK;
2147 }
2148 
2149 /******************************************************************************/
2150 /* p r e p a r e */
2151 /******************************************************************************/
2152 
2153 int XrdOfs::prepare( XrdSfsPrep &pargs, // In
2154  XrdOucErrInfo &out_error, // Out
2155  const XrdSecEntity *client) // In
2156 {
2157  EPNAME("prepare");
2158  XrdOucEnv prep_Env(0,0,client);
2159  XrdOucTList *tp = pargs.paths;
2160  int retc;
2161 
2162 // Run through the paths to make sure client can read each one unless we aren't
2163 // supposed to apply authorization.
2164 //
2165  if (prepAuth)
2166  while(tp)
2167  {AUTHORIZE(client,0,AOP_Read,"prepare",tp->text,out_error);
2168  tp = tp->next;
2169  }
2170 
2171 // If there is a prepare plugin, invoke it and return the result.
2172 //
2173  if (prepHandler)
2174  {if (pargs.opts & Prep_QUERY)
2175  return prepHandler->query(pargs, out_error, client);
2176  if (pargs.opts & Prep_CANCEL)
2177  return prepHandler->cancel(pargs, out_error, client);
2178 
2179  return prepHandler->begin(pargs, out_error, client);
2180  }
2181 
2182 // If we have a finder object, use it to prepare the paths. Otherwise,
2183 // ignore this prepare request (we may change this in the future).
2184 //
2185  if (XrdOfsFS->Finder
2186  && (retc = XrdOfsFS->Finder->Prepare(out_error, pargs, &prep_Env)))
2187  return fsError(out_error, retc);
2188  return 0;
2189 }
2190 
2191 /******************************************************************************/
2192 /* r e m o v e */
2193 /******************************************************************************/
2194 
2195 int XrdOfs::remove(const char type, // In
2196  const char *path, // In
2197  XrdOucErrInfo &einfo, // Out
2198  const XrdSecEntity *client, // In
2199  const char *info) // In
2200 /*
2201  Function: Delete a file from the namespace and release it's data storage.
2202 
2203  Input: type - 'f' for file and 'd' for directory.
2204  path - Is the fully qualified name of the file to be removed.
2205  einfo - Error information object to hold error details.
2206  client - Authentication credentials, if any.
2207  info - Opaque information to be used as seen fit.
2208 
2209  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2210 */
2211 {
2212  EPNAME("remove");
2213  static const int LocOpts = SFS_O_WRONLY|SFS_O_META;
2214  int retc, Opt;
2215  const char *tident = einfo.getErrUser();
2216  XrdOucEnv rem_Env(info,0,client);
2217  XTRACE(remove, path, type);
2218 
2219 // Apply security, as needed
2220 //
2221  AUTHORIZE(client,&rem_Env,AOP_Delete,"remove",path,einfo);
2222 
2223 // Find out where we should remove this file
2224 //
2225  if (Finder && Finder->isRemote())
2226  {struct fwdOpt *fSpec = (type == 'd' ? &fwdRMDIR : &fwdRM);
2227  if (fSpec->Cmd)
2228  {if (Forward(retc, einfo, *fSpec, path, 0, &rem_Env)) return retc;}
2229  else if ((retc = Finder->Locate(einfo, path, LocOpts, &rem_Env)))
2230  return fsError(einfo, retc);
2231  }
2232 
2233 // Check if we should generate an event
2234 //
2235  if (evsObject)
2236  {XrdOfsEvs::Event theEvent=(type == 'd' ? XrdOfsEvs::Rmdir:XrdOfsEvs::Rm);
2237  if (evsObject->Enabled(theEvent))
2238  {XrdOfsEvsInfo evInfo(tident, path, info, &rem_Env);
2239  evsObject->Notify(theEvent, evInfo);
2240  }
2241  }
2242 
2243 // Check if this is an online deletion only
2244 //
2245  Opt = (rem_Env.Get("ofs.lcl") ? XRDOSS_Online : 0);
2246 
2247 // Perform the actual deletion
2248 //
2249  retc = (type=='d' ? XrdOfsOss->Remdir(path, 0, &rem_Env)
2250  : XrdOfsOss->Unlink(path, Opt, &rem_Env));
2251  if (retc) return XrdOfsFS->Emsg(epname, einfo, retc, "remove", path);
2252  if (type == 'f') XrdOfsHandle::Hide(path);
2253  if (Balancer) Balancer->Removed(path);
2254  return SFS_OK;
2255 }
2256 
2257 /******************************************************************************/
2258 /* r e n a m e */
2259 /******************************************************************************/
2260 
2261 int XrdOfs::rename(const char *old_name, // In
2262  const char *new_name, // In
2263  XrdOucErrInfo &einfo, //Out
2264  const XrdSecEntity *client, // In
2265  const char *infoO, // In
2266  const char *infoN) // In
2267 /*
2268  Function: Renames a file with name 'old_name' to 'new_name'.
2269 
2270  Input: old_name - Is the fully qualified name of the file to be renamed.
2271  new_name - Is the fully qualified name that the file is to have.
2272  einfo - Error information structure, if an error occurs.
2273  client - Authentication credentials, if any.
2274  infoO - old_name opaque information to be used as seen fit.
2275  infoN - new_name opaque information to be used as seen fit.
2276 
2277  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2278 */
2279 {
2280  EPNAME("rename");
2281  static const int LocOpts = SFS_O_RDWR|SFS_O_META;
2282  int retc;
2283  const char *tident = einfo.getErrUser();
2284  XrdOucEnv old_Env(infoO,0,client);
2285  XrdOucEnv new_Env(infoN,0,client);
2286  XTRACE(rename, new_name, "old fn=" <<old_name <<" new ");
2287 
2288 // Apply security, as needed
2289 //
2290  AUTHORIZE(client, &old_Env, AOP_Rename, "renaming", old_name, einfo);
2291 
2292 // The above authorization may mutate the XrdSecEntity by putting a mapped name
2293 // into the extended attributes. This mapped name will affect the subsequent
2294 // authorization check below, giving the client access that may not be permitted.
2295 // Hence, we delete this attribute to reset the object back to "pristine" state.
2296 // If there was a way to make a copy of the XrdSecEntity, we could avoid this
2297 // hack-y reach inside the extended attributes.
2298  if (client) client->eaAPI->Add("request.name", "", true);
2299 
2300 // If we do not have full-blown insert authorization, we'll need to test for
2301 // destination existence
2302  bool cannot_overwrite = false;
2303  if (client && XrdOfsFS->Authorization &&
2304  !XrdOfsFS->Authorization->Access(client, new_name, AOP_Insert, &new_Env))
2305  {cannot_overwrite = true;
2306  AUTHORIZE(client, &new_Env, AOP_Excl_Insert,
2307  "rename to existing file (overwrite disallowed)", new_name, einfo);
2308  }
2309 
2310 // Find out where we should rename this file
2311 //
2312  if (Finder && Finder->isRemote())
2313  {if (fwdMV.Cmd)
2314  {if (Forward(retc,einfo,fwdMV,old_name,new_name,&old_Env,&new_Env))
2315  return retc;
2316  }
2317  else if ((retc = Finder->Locate(einfo, old_name, LocOpts, &old_Env)))
2318  return fsError(einfo, retc);
2319  }
2320 
2321 // Check if we should generate an event
2322 //
2323  if (evsObject && evsObject->Enabled(XrdOfsEvs::Mv))
2324  {XrdOfsEvsInfo evInfo(tident, old_name, infoO, &old_Env, 0, 0,
2325  new_name, infoN, &new_Env);
2326  evsObject->Notify(XrdOfsEvs::Mv, evInfo);
2327  }
2328 
2329 // If we cannot overwrite, we must test for existence first. This will test whether
2330 // we will destroy data in the rename (without actually destroying data).
2331 // Note there's an obvious race condition here; it was seen as the lesser-of-evils
2332 // compared to creating an exclusive file and potentially leaking it in the event
2333 // of a crash.
2334 //
2335  if (cannot_overwrite)
2336  {XrdSfsFileExistence exists_flag = XrdSfsFileExistNo;
2337  if (SFS_OK != exists(new_name, exists_flag, einfo, client, infoN))
2338  {// File existence check itself failed; we can't prove that data won't
2339  // be overwritten so we return an error.
2340  return fsError(einfo, -einfo.getErrInfo());
2341  }
2342  if (exists_flag != XrdSfsFileExistNo)
2343  {// EPERM mimics the error code set by Linux when you invoke rename()
2344  // but cannot overwrite the destination file.
2345  einfo.setErrInfo(EPERM, "Overwrite of existing data not permitted");
2346  return fsError(einfo, -EPERM);
2347  }
2348  }
2349 
2350 // Perform actual rename operation
2351 //
2352  if ((retc = XrdOfsOss->Rename(old_name, new_name, &old_Env, &new_Env)))
2353  {return XrdOfsFS->Emsg(epname, einfo, retc, "rename", old_name);
2354  }
2355  XrdOfsHandle::Hide(old_name);
2356  if (Balancer) {Balancer->Removed(old_name);
2357  Balancer->Added(new_name);
2358  }
2359  return SFS_OK;
2360 }
2361 
2362 /******************************************************************************/
2363 /* s t a t */
2364 /******************************************************************************/
2365 
2366 int XrdOfs::stat(const char *path, // In
2367  struct stat *buf, // Out
2368  XrdOucErrInfo &einfo, // Out
2369  const XrdSecEntity *client, // In
2370  const char *info) // In
2371 /*
2372  Function: Return file status information
2373 
2374  Input: path - The path for which status is wanted
2375  buf - The stat structure to hold the results
2376  einfo - Error information structure, if an error occurs.
2377  client - Authentication credentials, if any.
2378  info - opaque information to be used as seen fit.
2379 
2380  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2381 */
2382 {
2383  EPNAME("stat");
2384  int retc;
2385  const char *tident = einfo.getErrUser();
2386  XrdOucEnv stat_Env(info,0,client);
2387  XTRACE(stat, path, "");
2388 
2389 // Apply security, as needed
2390 //
2391  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2392 
2393 // Find out where we should stat this file
2394 //
2395  if (Finder && Finder->isRemote()
2396  && (retc = Finder->Locate(einfo, path, SFS_O_RDONLY|SFS_O_STAT, &stat_Env)))
2397  return fsError(einfo, retc);
2398 
2399 // Now try to find the file or directory
2400 //
2401  if ((retc = XrdOfsOss->Stat(path, buf, 0, &stat_Env)))
2402  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path);
2403  return SFS_OK;
2404 }
2405 
2406 /******************************************************************************/
2407 
2408 int XrdOfs::stat(const char *path, // In
2409  mode_t &mode, // Out
2410  XrdOucErrInfo &einfo, // Out
2411  const XrdSecEntity *client, // In
2412  const char *info) // In
2413 /*
2414  Function: Return file status information (resident files only)
2415 
2416  Input: path - The path for which status is wanted
2417  mode - The stat mode entry (faked -- do not trust it)
2418  einfo - Error information structure, if an error occurs.
2419  client - Authentication credentials, if any.
2420  info - opaque information to be used as seen fit.
2421 
2422  Output: Always returns SFS_ERROR if a delay needs to be imposed. Otherwise,
2423  SFS_OK is returned and mode is appropriately, if inaccurately, set.
2424  If file residency cannot be determined, mode is set to -1.
2425 */
2426 {
2427  EPNAME("stat");
2428  struct stat buf;
2429  int retc;
2430  const char *tident = einfo.getErrUser();
2431  XrdOucEnv stat_Env(info,0,client);
2432  XTRACE(stat, path, "");
2433 
2434 // Apply security, as needed
2435 //
2436  AUTHORIZE(client,&stat_Env,AOP_Stat,"locate",path,einfo);
2437  mode = (mode_t)-1;
2438 
2439 // Find out where we should stat this file
2440 //
2441  if (Finder && Finder->isRemote()
2442  && (retc = Finder->Locate(einfo,path,SFS_O_NOWAIT|SFS_O_RDONLY|SFS_O_STAT,
2443  &stat_Env)))
2444  return fsError(einfo, retc);
2445 
2446 // Now try to find the file or directory
2447 //
2448  if (!(retc = XrdOfsOss->Stat(path, &buf, XRDOSS_resonly, &stat_Env)))
2449  mode=buf.st_mode;
2450  else if ((-ENOMSG) != retc)
2451  return XrdOfsFS->Emsg(epname, einfo, retc, "locate", path);
2452  return SFS_OK;
2453 }
2454 
2455 /******************************************************************************/
2456 /* t r u n c a t e */
2457 /******************************************************************************/
2458 
2459 int XrdOfs::truncate(const char *path, // In
2460  XrdSfsFileOffset Size, // In
2461  XrdOucErrInfo &einfo, // Out
2462  const XrdSecEntity *client, // In
2463  const char *info) // In
2464 /*
2465  Function: Change the mode on a file or directory.
2466 
2467  Input: path - Is the fully qualified name of the file to be removed.
2468  Size - the size the file should have.
2469  einfo - Error information object to hold error details.
2470  client - Authentication credentials, if any.
2471  info - Opaque information to be used as seen fit.
2472 
2473  Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
2474 */
2475 {
2476  EPNAME("truncate");
2477  const char *tident = einfo.getErrUser();
2478  XrdOucEnv trunc_Env(info,0,client);
2479  int retc;
2480  XTRACE(truncate, path, "");
2481 
2482 // Apply security, as needed
2483 //
2484  AUTHORIZE(client,&trunc_Env,AOP_Update,"truncate",path,einfo);
2485 
2486 // Find out where we should chmod this file
2487 //
2488  if (Finder && Finder->isRemote())
2489  {if (fwdTRUNC.Cmd)
2490  {char xSz[32];
2491  sprintf(xSz, "%lld", static_cast<long long>(Size));
2492  if (Forward(retc,einfo,fwdTRUNC,path,xSz,&trunc_Env)) return retc;
2493  }
2494  else if ((retc = Finder->Locate(einfo,path,SFS_O_RDWR,&trunc_Env)))
2495  return fsError(einfo, retc);
2496  }
2497 
2498 // Check if we should generate an event
2499 //
2500  if (evsObject && evsObject->Enabled(XrdOfsEvs::Trunc))
2501  {XrdOfsEvsInfo evInfo(tident, path, info, &trunc_Env, 0, Size);
2502  evsObject->Notify(XrdOfsEvs::Trunc, evInfo);
2503  }
2504 
2505 // Now try to find the file or directory
2506 //
2507  if (!(retc = XrdOfsOss->Truncate(path, Size, &trunc_Env))) return SFS_OK;
2508 
2509 // An error occurred, return the error info
2510 //
2511  return XrdOfsFS->Emsg(epname, einfo, retc, "trunc", path);
2512 }
2513 
2514 /******************************************************************************/
2515 /* E m s g */
2516 /******************************************************************************/
2517 
2518 int XrdOfs::Emsg(const char *pfx, // Message prefix value
2519  XrdOucErrInfo &einfo, // Place to put text & error code
2520  int ecode, // The error code
2521  const char *op, // Operation being performed
2522  XrdOfsHandle *hP) // The target handle
2523 {
2524  int rc;
2525 
2526 // First issue the error message so if we have to unpersist it makes sense
2527 //
2528  if ((rc = Emsg(pfx, einfo, ecode, op, hP->Name())) != SFS_ERROR) return rc;
2529 
2530 // If this is a POSC file then we need to unpersist it. Note that we are always
2531 // called with the handle **unlocked**
2532 //
2533  if (hP->isRW == XrdOfsHandle::opPC)
2534  {hP->Lock();
2535  XrdOfsFS->Unpersist(hP);
2536  hP->UnLock();
2537  }
2538 
2539 // Now return the error
2540 //
2541  return SFS_ERROR;
2542 }
2543 
2544 /******************************************************************************/
2545 
2546 int XrdOfs::Emsg(const char *pfx, // Message prefix value
2547  XrdOucErrInfo &einfo, // Place to put text & error code
2548  int ecode, // The error code
2549  const char *op, // Operation being performed
2550  const char *target) // The target (e.g., fname)
2551 {
2552  char buffer[MAXPATHLEN+80];
2553 
2554 // If the error is EBUSY then we just need to stall the client. This is
2555 // a hack in order to provide for proxy support
2556 //
2557 // The hack unfotunately is now beinng triggered for reads and writes when
2558 // it was never so before (presumably due to client changes). So do not
2559 // apply the hack for these operations. This gets a better fix in R 6.0
2560 //
2561 if (strcmp("read", op) && strcmp("readv", op) && strcmp("pgRead", op) &&
2562  strcmp("write",op) && strcmp("pgwrite",op)) {
2563  if (ecode < 0) ecode = -ecode;
2564  if (ecode == EBUSY) return 5; // A hack for proxy support
2565 
2566 // Check for timeout conditions that require a client delay
2567 //
2568  if (ecode == ETIMEDOUT) return OSSDelay;
2569  }
2570 
2571 // Format the error message
2572 //
2573  XrdOucERoute::Format(buffer, sizeof(buffer), ecode, op, target);
2574 
2575 // Print it out if debugging is enabled
2576 //
2577 #ifndef NODEBUG
2578  OfsEroute.Emsg(pfx, einfo.getErrUser(), buffer);
2579 #endif
2580 
2581 // Place the error message in the error object and return
2582 //
2583  einfo.setErrInfo(ecode, buffer);
2584  return SFS_ERROR;
2585 }
2586 
2587 /******************************************************************************/
2588 /* P R I V A T E S E C T I O N */
2589 /******************************************************************************/
2590 
2591 /******************************************************************************/
2592 /* F n a m e */
2593 /******************************************************************************/
2594 
2595 const char *XrdOfs::Fname(const char *path)
2596 {
2597  int i = strlen(path)-1;
2598  while(i) if (path[i] == '/') return &path[i+1];
2599  else i--;
2600  return path;
2601 }
2602 
2603 /******************************************************************************/
2604 /* F o r w a r d */
2605 /******************************************************************************/
2606 
2607 int XrdOfs::Forward(int &Result, XrdOucErrInfo &Resp, struct fwdOpt &Fwd,
2608  const char *arg1, const char *arg2,
2609  XrdOucEnv *Env1, XrdOucEnv *Env2)
2610 {
2611  int retc;
2612 
2613  if ((retc = Finder->Forward(Resp, Fwd.Cmd, arg1, arg2, Env1, Env2)))
2614  {Result = fsError(Resp, retc);
2615  return 1;
2616  }
2617 
2618  if (Fwd.Port <= 0)
2619  {Result = SFS_OK;
2620  return (Fwd.Port ? 0 : 1);
2621  }
2622 
2623  Resp.setErrInfo(Fwd.Port, Fwd.Host);
2624  Result = SFS_REDIRECT;
2626  return 1;
2627 }
2628 
2629 /******************************************************************************/
2630 /* f s E r r o r */
2631 /******************************************************************************/
2632 
2633 int XrdOfs::fsError(XrdOucErrInfo &myError, int rc)
2634 {
2635 
2636 // Screen the error code (update statistics w/o a lock for speed!)
2637 //
2638  if (rc == SFS_REDIRECT) {OfsStats.Data.numRedirect++; return SFS_REDIRECT;}
2639  if (rc == SFS_STARTED) {OfsStats.Data.numStarted++; return SFS_STARTED; }
2640  if (rc > 0) {OfsStats.Data.numDelays++; return rc; }
2641  if (rc == SFS_DATA) {OfsStats.Data.numReplies++; return SFS_DATA; }
2642  {OfsStats.Data.numErrors++; return SFS_ERROR; }
2643 }
2644 
2645 /******************************************************************************/
2646 /* R e f o r m a t */
2647 /******************************************************************************/
2648 
2649 int XrdOfs::Reformat(XrdOucErrInfo &myError)
2650 {
2651  static const char *fmt = "oss.cgroup=all&oss.space=%llu&oss.free=%llu"
2652  "&oss.maxf=%llu&oss.used=%llu&oss.quota=-1";
2653  char qsFmt, *bP;
2654  unsigned long long totSpace, totFree, maxFree;
2655  int n, blen;
2656 
2657 // Get the buffer
2658 //
2659  bP = myError.getMsgBuff(blen);
2660 
2661 // Scan out the values
2662 //
2663  n = sscanf(bP, "%c %llu %llu %llu", &qsFmt, &totSpace, &totFree, &maxFree);
2664 
2665 // Validate the response. The response will be invalid for older cmsd's
2666 //
2667  if (n != 4 || qsFmt != 'A')
2668  {myError.setErrInfo(ENOTSUP,"space fctl operation not supported by cmsd");
2669  return SFS_ERROR;
2670  }
2671 
2672 // Change megabyte values to actual bytes
2673 //
2674  totSpace = totSpace << 20LL;
2675  totFree = totFree << 20LL;
2676  maxFree = maxFree << 20LL;
2677 
2678 // Reformat the result
2679 //
2680  blen = snprintf(bP,blen,fmt,totSpace,totFree,maxFree,(totSpace-totFree));
2681 
2682  myError.setErrCode(blen);
2683  return SFS_DATA;
2684 }
2685 
2686 /******************************************************************************/
2687 /* S p l i t */
2688 /******************************************************************************/
2689 
2690 const char * XrdOfs::Split(const char *Args, const char **Opq,
2691  char *Path, int Plen)
2692 {
2693  int xlen;
2694  *Opq = index(Args, '?');
2695  if (!(*Opq)) return Args;
2696  xlen = (*Opq)-Args;
2697  if (xlen >= Plen) xlen = Plen-1;
2698  strncpy(Path, Args, xlen);
2699  Path[xlen] = 0;
2700  return Path;
2701 }
2702 
2703 /******************************************************************************/
2704 /* S t a l l */
2705 /******************************************************************************/
2706 
2707 int XrdOfs::Stall(XrdOucErrInfo &einfo, // Error text & code
2708  int stime, // Seconds to stall
2709  const char *path) // The path to stall on
2710 {
2711  const char *msgfmt = "File %s is being %s; "
2712  "estimated time to completion %s";
2713  EPNAME("Stall")
2714 #ifndef NODEBUG
2715  const char *tident = "";
2716 #endif
2717  char Mbuff[2048], Tbuff[32];
2718  const char *What = "staged";
2719 
2720 // Check why the stall is occurring
2721 //
2722  if (stime < 0) {stime = 60; What = "created";}
2723 
2724 // Format the stall message
2725 //
2726  snprintf(Mbuff, sizeof(Mbuff)-1, msgfmt,
2727  Fname(path), What, WaitTime(stime, Tbuff, sizeof(Tbuff)));
2728  ZTRACE(delay, "Stall " <<stime <<": " <<Mbuff <<" for " <<path);
2729 
2730 // Place the error message in the error object and return
2731 //
2732  einfo.setErrInfo(0, Mbuff);
2733 
2734 // All done
2735 //
2736  return (stime > MaxDelay ? MaxDelay : stime);
2737 }
2738 
2739 /******************************************************************************/
2740 /* U n p e r s i s t */
2741 /******************************************************************************/
2742 
2743 void XrdOfs::Unpersist(XrdOfsHandle *oh, int xcev)
2744 {
2745  EPNAME("Unpersist");
2746  const char *tident = oh->PoscUsr();
2747  int poscNum, retc;
2748  short theMode;
2749 
2750 // Trace the call
2751 //
2752  FTRACE(close, "use=0");
2753 
2754 // Generate a proper close event as one has not yet been generated
2755 //
2756  if (xcev && XrdOfsFS->evsObject && *tident != '?'
2757  && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Closew))
2758  {XrdOfsEvsInfo evInfo(tident, oh->Name());
2759  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Closew, evInfo);
2760  }
2761 
2762 // Now generate a removal event
2763 //
2764  if (XrdOfsFS->Balancer) XrdOfsFS->Balancer->Removed(oh->Name());
2765  if (XrdOfsFS->evsObject && XrdOfsFS->evsObject->Enabled(XrdOfsEvs::Rm))
2766  {XrdOfsEvsInfo evInfo(tident, oh->Name());
2767  XrdOfsFS->evsObject->Notify(XrdOfsEvs::Rm, evInfo);
2768  }
2769 
2770 // Count this
2771 //
2773 
2774 // Now unpersist the file
2775 //
2776  OfsEroute.Emsg(epname, "Unpersisting", tident, oh->Name());
2777  if ((poscNum = oh->PoscGet(theMode))) poscQ->Del(oh->Name(), poscNum, 1);
2778  else if ((retc = XrdOfsOss->Unlink(oh->Name())))
2779  OfsEroute.Emsg(epname, retc, "unpersist", oh->Name());
2780 }
2781 
2782 /******************************************************************************/
2783 /* W a i t T i m e */
2784 /******************************************************************************/
2785 
2786 char *XrdOfs::WaitTime(int stime, char *buff, int blen)
2787 {
2788  int hr, min, sec;
2789 
2790 // Compute hours, minutes, and seconds
2791 //
2792  min = stime / 60;
2793  sec = stime % 60;
2794  hr = min / 60;
2795  min = min % 60;
2796 
2797 // Now format the message based on time duration
2798 //
2799  if (!hr && !min)
2800  snprintf(buff,blen,"%d second%s",sec,(sec > 1 ? "s" : ""));
2801  else if (!hr)
2802  {if (sec > 10) min++;
2803  snprintf(buff,blen,"%d minute%s",min,(min > 1 ? "s" : ""));
2804  }
2805  else {if (hr == 1)
2806  if (min <= 30)
2807  snprintf(buff,blen,"%d minutes",min+60);
2808  else snprintf(buff,blen,"%d hour and %d minutes",hr,min);
2809  else {if (min > 30) hr++;
2810  snprintf(buff,blen,"%d hours",hr);
2811  }
2812  }
2813 
2814 // Complete the message
2815 //
2816  buff[blen-1] = '\0';
2817  return buff;
2818 }
#define ENOATTR
Definition: XProtocol.hh:1343
@ 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:163
#define ENODATA
Definition: XrdOfsChkPnt.cc:48
#define OOIDENTENV(usr, env)
#define AUTHORIZE(usr, env, optype, action, pathp, edata)
XrdSysError OfsEroute(0)
XrdSysTrace OfsTrace("ofs")
XrdOss * XrdOfsOss
Definition: XrdOfs.cc:163
XrdOfsStats OfsStats
Definition: XrdOfs.cc:113
#define O_DIRECT
Definition: XrdOfs.cc:98
XrdOfs * XrdOfsFS
Definition: XrdOfsFS.cc:47
#define XRDOSS_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 closedir(DIR *dirp)
DIR * opendir(const char *path)
#define close(a)
Definition: XrdPosix.hh:48
#define fstat(a, b)
Definition: XrdPosix.hh:62
#define stat(a, b)
Definition: XrdPosix.hh:101
#define readdir(a)
Definition: XrdPosix.hh:86
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:1736
int checkpoint(XrdSfsFile::cpAct act, struct iov *range=0, int n=0)
Definition: XrdOfs.cc:915
XrdSfsXferSize pgWrite(XrdSfsFileOffset offset, char *buffer, XrdSfsXferSize wrlen, uint32_t *csvec, uint64_t opts=0)
Definition: XrdOfs.cc:1192
XrdSfsXferSize write(XrdSfsFileOffset fileOffset, const char *buffer, XrdSfsXferSize buffer_size)
Definition: XrdOfs.cc:1476
static bool ocFsync
Definition: XrdOfs.hh:194
int truncate(XrdSfsFileOffset fileOffset)
Definition: XrdOfs.cc:1689
int read(XrdSfsFileOffset fileOffset, XrdSfsXferSize amount)
Definition: XrdOfs.cc:1311
XrdSfsXferSize readv(XrdOucIOVec *readV, int readCount)
Definition: XrdOfs.cc:1398
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:1096
int getMmap(void **Addr, off_t &Size)
Definition: XrdOfs.cc:1579
int close()
Definition: XrdOfs.cc:804
char viaDel
Definition: XrdOfs.hh:203
const char * tident
Definition: XrdOfs.hh:198
int sync()
Definition: XrdOfs.cc:1628
XrdOfsHandle * oh
Definition: XrdOfs.hh:199
int dorawio
Definition: XrdOfs.hh:202
XrdOucChkPnt * myCKP
Definition: XrdOfs.hh:201
bool ckpBad
Definition: XrdOfs.hh:204
XrdOfsTPC * myTPC
Definition: XrdOfs.hh:200
virtual int fctl(const int cmd, const char *args, XrdOucErrInfo &eInfo)=0
int stat(struct stat *buf)
Definition: XrdOfs.cc:1600
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:1966
int chmod(const char *Name, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:1898
int truncate(const char *Name, XrdSfsFileOffset fileOffset, XrdOucErrInfo &out_error, const XrdSecEntity *client=0, const char *opaque=0)
Definition: XrdOfs.cc:2459
struct fwdOpt fwdTRUNC
Definition: XrdOfs.hh:417
void Disc(const XrdSecEntity *client=0)
Definition: XrdOfs.cc:1979
int prepare(XrdSfsPrep &pargs, XrdOucErrInfo &out_error, const XrdSecEntity *client=0)
Definition: XrdOfs.cc:2153
mode_t dMask[2]
Definition: XrdOfs.hh:386
const char * Split(const char *Args, const char **Opq, char *Path, int Plen)
Definition: XrdOfs.cc:2690
int myPort
Definition: XrdOfs.hh:382
XrdCmsClient * Finder
Definition: XrdOfs.hh:431
mode_t fMask[2]
Definition: XrdOfs.hh:387
char * WaitTime(int, char *, int)
Definition: XrdOfs.cc:2786
struct fwdOpt fwdRMDIR
Definition: XrdOfs.hh:416
XrdOfsEvr evrObject
Definition: XrdOfs.hh:430
static int OSSDelay
Definition: XrdOfs.hh:420
char * ConfigFN
Definition: XrdOfs.hh:422
int tpcRdrPort[2]
Definition: XrdOfs.hh:392
@ RdrTPC
Definition: XrdOfs.hh:378
int mkdir(const char *dirName, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:2078
struct fwdOpt fwdMKPATH
Definition: XrdOfs.hh:413
XrdOfs()
Definition: XrdOfs.cc:169
char * tpcRdrHost[2]
Definition: XrdOfs.hh:391
int chksum(csFunc Func, const char *csName, const char *Path, XrdOucErrInfo &out_error, const XrdSecEntity *client=0, const char *opaque=0)
Definition: XrdOfs.cc:1787
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:2261
int Options
Definition: XrdOfs.hh:381
struct fwdOpt fwdMKDIR
Definition: XrdOfs.hh:412
static int MaxDelay
Definition: XrdOfs.hh:419
static int Emsg(const char *, XrdOucErrInfo &, int, const char *x, XrdOfsHandle *hP)
Definition: XrdOfs.cc:2518
struct fwdOpt fwdMV
Definition: XrdOfs.hh:414
static int fsError(XrdOucErrInfo &myError, int rc)
Definition: XrdOfs.cc:2633
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:2366
struct fwdOpt fwdRM
Definition: XrdOfs.hh:415
int getStats(char *buff, int blen)
Definition: XrdOfs.cc:2055
struct fwdOpt fwdCHMOD
Definition: XrdOfs.hh:411
int Stall(XrdOucErrInfo &, int, const char *)
Definition: XrdOfs.cc:2707
int exists(const char *fileName, XrdSfsFileExistence &exists_flag, XrdOucErrInfo &out_error, const XrdSecEntity *client, const char *opaque=0)
Definition: XrdOfs.cc:1992
void Unpersist(XrdOfsHandle *hP, int xcev=1)
Definition: XrdOfs.cc:2743
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:401
static const int uUrlOK
ucap: Supports async responses
static const int uLclF
ucap: Client is on a private net