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