XRootD
Loading...
Searching...
No Matches
XrdSfsNative.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d X f s N a t i v e . 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 <sys/types.h>
31#include <unistd.h>
32#include <dirent.h>
33#include <fcntl.h>
34#include <memory.h>
35#include <cstring>
36#include <cstdio>
37#include <cstdlib>
38#include <sys/param.h>
39#include <sys/stat.h>
40
41#include "XrdVersion.hh"
42#include "XrdSys/XrdSysE2T.hh"
43#include "XrdSys/XrdSysError.hh"
48#include "XrdSfs/XrdSfsAio.hh"
50
51#ifdef AIX
52#include <sys/mode.h>
53#endif
54
55/******************************************************************************/
56/* O S D i r e c t o r y H a n d l i n g I n t e r f a c e */
57/******************************************************************************/
58
59#ifndef S_IAMB
60#define S_IAMB 0x1FF
61#endif
62
63/******************************************************************************/
64/* G l o b a l O b j e c t s */
65/******************************************************************************/
66
67XrdSysError *XrdSfsNative::eDest;
68
69/******************************************************************************/
70/* U n i x F i l e S y s t e m I n t e r f a c e */
71/******************************************************************************/
72
74{
75public:
76
77static int Chmod(const char *fn, mode_t mode) {return chmod(fn, mode);}
78
79static int Close(int fd) {return close(fd);}
80
81static int Mkdir(const char *fn, mode_t mode) {return mkdir(fn, mode);}
82
83static int Open(const char *path, int oflag, mode_t omode)
84 {return open(path, oflag, omode);}
85
86static int Rem(const char *fn) {return unlink(fn);}
87
88static int Remdir(const char *fn) {return rmdir(fn);}
89
90static int Rename(const char *ofn, const char *nfn) {return rename(ofn, nfn);}
91
92static int Statfd(int fd, struct stat *buf) {return fstat(fd, buf);}
93
94static int Statfn(const char *fn, struct stat *buf) {return stat(fn, buf);}
95
96static int Truncate(const char *fn, off_t flen) {return truncate(fn, flen);}
97};
98
99/******************************************************************************/
100/* C o n s t r u c t o r */
101/******************************************************************************/
102
104{
105 eDest = ep;
106}
107
108/******************************************************************************/
109/* G e t F i l e S y s t e m */
110/******************************************************************************/
111
113 XrdSysLogger *lp)
114{
115 static XrdSysError Eroute(lp, "XrdSfs");
116 static XrdSfsNative myFS(&Eroute);
117
118 Eroute.Say("Copr. 2007 Stanford University/SLAC "
119 "sfs (Standard File System) v 9.0n");
120
121 return &myFS;
122}
123
124/******************************************************************************/
125/* 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 */
126/******************************************************************************/
127/******************************************************************************/
128/* o p e n */
129/******************************************************************************/
130
131int XrdSfsNativeDirectory::open(const char *dir_path, // In
132 const XrdSecClientName *client, // In
133 const char *info) // In
134/*
135 Function: Open the directory `path' and prepare for reading.
136
137 Input: path - The fully qualified name of the directory to open.
138 cred - Authentication credentials, if any.
139 info - Opaque information, if any.
140
141 Output: Returns SFS_OK upon success, otherwise SFS_ERROR.
142*/
143{
144 static const char *epname = "opendir";
145
146// Verify that this object is not already associated with an open directory
147//
148 if (dh) return
149 XrdSfsNative::Emsg(epname, error, EADDRINUSE,
150 "open directory", dir_path);
151
152// Set up values for this directory object
153//
154 ateof = 0;
155 fname = strdup(dir_path);
156
157// Open the directory and get it's id
158//
159 if (!(dh = opendir(dir_path))) return
160 XrdSfsNative::Emsg(epname,error,errno,"open directory",dir_path);
161
162// All done
163//
164 return SFS_OK;
165}
166
167/******************************************************************************/
168/* n e x t E n t r y */
169/******************************************************************************/
170
172/*
173 Function: Read the next directory entry.
174
175 Input: None.
176
177 Output: Upon success, returns the contents of the next directory entry as
178 a null terminated string. Returns a null pointer upon EOF or an
179 error. To differentiate the two cases, getErrorInfo will return
180 0 upon EOF and an actual error code (i.e., not 0) on error.
181*/
182{
183 static const char *epname = "nextEntry";
184 struct dirent *rp;
185 int retc;
186
187// Lock the direcrtory and do any required tracing
188//
189 if (!dh)
190 {XrdSfsNative::Emsg(epname,error,EBADF,"read directory",fname);
191 return (const char *)0;
192 }
193
194// Check if we are at EOF (once there we stay there)
195//
196 if (ateof) return (const char *)0;
197
198// Read the next directory entry
199//
200#if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
201 errno = 0;
202 rp = readdir(dh);
203 if (!rp)
204 {if (!(retc = errno)) {ateof = 1; error.clear();}
205 else XrdSfsNative::Emsg(epname,error,retc,"read directory",fname);
206 d_pnt->d_name[0] = '\0';
207 return (const char *)0;
208 }
209 return (const char *)(rp->d_name);
210#else
211 if ((retc = readdir_r(dh, d_pnt, &rp)))
212 {XrdSfsNative::Emsg(epname,error,retc,"read directory",fname);
213 d_pnt->d_name[0] = '\0';
214 return (const char *)0;
215 }
216
217// Check if we have reached end of file
218//
219 if (!rp || !d_pnt->d_name[0])
220 {ateof = 1;
221 error.clear();
222 return (const char *)0;
223 }
224
225// Return the actual entry
226//
227 return (const char *)(d_pnt->d_name);
228#endif
229}
230
231/******************************************************************************/
232/* c l o s e */
233/******************************************************************************/
234
236/*
237 Function: Close the directory object.
238
239 Input: cred - Authentication credentials, if any.
240
241 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
242*/
243{
244 static const char *epname = "closedir";
245
246// Release the handle
247//
248 if (dh && closedir(dh))
249 {XrdSfsNative::Emsg(epname, error, errno, "close directory", fname);
250 return SFS_ERROR;
251 }
252
253// Do some clean-up
254//
255 if (fname) free(fname);
256 dh = (DIR *)0;
257 return SFS_OK;
258}
259
260/******************************************************************************/
261/* F i l e O b j e c t I n t e r f a c e s */
262/******************************************************************************/
263/******************************************************************************/
264/* o p e n */
265/******************************************************************************/
266
267int XrdSfsNativeFile::open(const char *path, // In
268 XrdSfsFileOpenMode open_mode, // In
269 mode_t Mode, // In
270 const XrdSecClientName *client, // In
271 const char *info) // In
272/*
273 Function: Open the file `path' in the mode indicated by `open_mode'.
274
275 Input: path - The fully qualified name of the file to open.
276 open_mode - One of the following flag values:
277 SFS_O_RDONLY - Open file for reading.
278 SFS_O_WRONLY - Open file for writing.
279 SFS_O_RDWR - Open file for update
280 SFS_O_CREAT - Create the file open in RDWR mode
281 SFS_O_TRUNC - Trunc the file open in RDWR mode
282 Mode - The Posix access mode bits to be assigned to the file.
283 These bits correspond to the standard Unix permission
284 bits (e.g., 744 == "rwxr--r--"). Mode may also conatin
285 SFS_O_MKPTH is the full path is to be created. The
286 agument is ignored unless open_mode = SFS_O_CREAT.
287 client - Authentication credentials, if any.
288 info - Opaque information to be used as seen fit.
289
290 Output: Returns OOSS_OK upon success, otherwise SFS_ERROR is returned.
291*/
292{
293 static const char *epname = "open";
294 const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
295 char *opname;
296 mode_t acc_mode = Mode & S_IAMB;
297 int retc, open_flag = 0;
298 struct stat buf;
299
300// Verify that this object is not already associated with an open file
301//
302 if (oh >= 0)
303 return XrdSfsNative::Emsg(epname,error,EADDRINUSE,"open file",path);
304 fname = strdup(path);
305
306// Set the actual open mode
307//
308 switch(open_mode & (SFS_O_RDONLY | SFS_O_WRONLY | SFS_O_RDWR))
309 {
310 case SFS_O_RDONLY: open_flag = O_RDONLY; break;
311 case SFS_O_WRONLY: open_flag = O_WRONLY; break;
312 case SFS_O_RDWR: open_flag = O_RDWR; break;
313 default: open_flag = O_RDONLY; break;
314 }
315
316// Prepare to create or open the file, as needed
317//
318 if (open_mode & SFS_O_CREAT)
319 {open_flag = O_RDWR | O_CREAT | O_EXCL;
320 opname = (char *)"create";
321 if ((Mode & SFS_O_MKPTH) && (retc = XrdSfsNative::Mkpath(path,AMode,info)))
322 return XrdSfsNative::Emsg(epname,error,retc,"create path for",path);
323 } else if (open_mode & SFS_O_TRUNC)
324 {open_flag = O_RDWR | O_CREAT | O_TRUNC;
325 opname = (char *)"truncate";
326 } else opname = (char *)"open";
327
328// Open the file and make sure it is a file
329//
330 if ((oh = XrdSfsUFS::Open(path, open_flag, acc_mode)) >= 0)
331 {do {retc = XrdSfsUFS::Statfd(oh, &buf);} while(retc && errno == EINTR);
332 if (!retc && !(buf.st_mode & S_IFREG))
333 {close(); oh = (buf.st_mode & S_IFDIR ? -EISDIR : -ENOTBLK);}
334 } else {
335 oh = -errno;
336 if (errno == EEXIST)
337 {do {retc = XrdSfsUFS::Statfn(path, &buf);}
338 while(retc && errno == EINTR);
339 if (!retc && (buf.st_mode & S_IFDIR)) oh = -EISDIR;
340 }
341 }
342
343// All done.
344//
345 if (oh < 0) return XrdSfsNative::Emsg(epname, error, oh, opname, path);
346 return SFS_OK;
347}
348
349/******************************************************************************/
350/* c l o s e */
351/******************************************************************************/
352
354/*
355 Function: Close the file object.
356
357 Input: None
358
359 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
360*/
361{
362 static const char *epname = "close";
363
364// Release the handle and return
365//
366 if (oh >= 0 && XrdSfsUFS::Close(oh))
367 return XrdSfsNative::Emsg(epname, error, errno, "close", fname);
368 oh = -1;
369 if (fname) {free(fname); fname = 0;}
370 return SFS_OK;
371}
372
373/******************************************************************************/
374/* f c t l */
375/******************************************************************************/
376
377int XrdSfsNativeFile::fctl(const int cmd,
378 const char *args,
379 XrdOucErrInfo &out_error)
380{
381// See if we can do this
382//
383 if (cmd == SFS_FCTL_GETFD)
384 {out_error.setErrCode(oh);
385 return SFS_OK;
386 }
387
388// We don't support this
389//
390 out_error.setErrInfo(ENOTSUP, "fctl operation not supported");
391 return SFS_ERROR;
392}
393
394/******************************************************************************/
395/* r e a d */
396/******************************************************************************/
397
399 char *buff, // Out
400 XrdSfsXferSize blen) // In
401/*
402 Function: Read `blen' bytes at `offset' into 'buff' and return the actual
403 number of bytes read.
404
405 Input: offset - The absolute byte offset at which to start the read.
406 buff - Address of the buffer in which to place the data.
407 blen - The size of the buffer. This is the maximum number
408 of bytes that will be read from 'fd'.
409
410 Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
411*/
412{
413 static const char *epname = "read";
414 XrdSfsXferSize nbytes;
415
416// Make sure the offset is not too large
417//
418#if _FILE_OFFSET_BITS!=64
419 if (offset > 0x000000007fffffff)
420 return XrdSfsNative::Emsg(epname, error, EFBIG, "read", fname);
421#endif
422
423// Read the actual number of bytes
424//
425 do { nbytes = pread(oh, (void *)buff, (size_t)blen, (off_t)offset); }
426 while(nbytes < 0 && errno == EINTR);
427
428 if (nbytes < 0)
429 return XrdSfsNative::Emsg(epname, error, errno, "read", fname);
430
431// Return number of bytes read
432//
433 return nbytes;
434}
435
436/******************************************************************************/
437/* r e a d v */
438/******************************************************************************/
439
441 int readCount) // In
442/*
443 Function: Perform all the reads specified in the readV vector.
444
445 Input: readV - A description of the reads to perform; includes the
446 absolute offset, the size of the read, and the buffer
447 to place the data into.
448 readCount - The size of the readV vector.
449
450 Output: Returns the number of bytes read upon success and SFS_ERROR o/w.
451 If the number of bytes read is less than requested, it is considered
452 an error.
453*/
454{
455 static const char *epname = "readv";
456 XrdSfsXferSize nbytes = 0;
457 ssize_t curCount;
458 int i;
459
460 for (i=0; i<int(readCount); i++)
461 {do {curCount = pread(oh, (void *)readV[i].data, (size_t)readV[i].size, (off_t)readV[i].offset);}
462 while(curCount < 0 && errno == EINTR);
463
464 if (curCount != readV[i].size)
465 {if (curCount > 0) errno = ESPIPE;
466 return XrdSfsNative::Emsg(epname, error, errno, "readv", fname);
467 }
468 nbytes += curCount;
469 }
470
471 return nbytes;
472}
473
474/******************************************************************************/
475/* r e a d A I O */
476/******************************************************************************/
477
479{
480
481// Execute this request in a synchronous fashion
482//
483 aiop->Result = this->read((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
484 (char *)aiop->sfsAio.aio_buf,
486 aiop->doneRead();
487 return 0;
488}
489
490/******************************************************************************/
491/* w r i t e */
492/******************************************************************************/
493
495 const char *buff, // In
496 XrdSfsXferSize blen) // In
497/*
498 Function: Write `blen' bytes at `offset' from 'buff' and return the actual
499 number of bytes written.
500
501 Input: offset - The absolute byte offset at which to start the write.
502 buff - Address of the buffer from which to get the data.
503 blen - The size of the buffer. This is the maximum number
504 of bytes that will be written to 'fd'.
505
506 Output: Returns the number of bytes written upon success and SFS_ERROR o/w.
507
508 Notes: An error return may be delayed until the next write(), close(), or
509 sync() call.
510*/
511{
512 static const char *epname = "write";
513 XrdSfsXferSize nbytes;
514
515// Make sure the offset is not too large
516//
517#if _FILE_OFFSET_BITS!=64
518 if (offset > 0x000000007fffffff)
519 return XrdSfsNative::Emsg(epname, error, EFBIG, "write", fname);
520#endif
521
522// Write the requested bytes
523//
524 do { nbytes = pwrite(oh, (void *)buff, (size_t)blen, (off_t)offset); }
525 while(nbytes < 0 && errno == EINTR);
526
527 if (nbytes < 0)
528 return XrdSfsNative::Emsg(epname, error, errno, "write", fname);
529
530// Return number of bytes written
531//
532 return nbytes;
533}
534
535/******************************************************************************/
536/* w r i t e A I O */
537/******************************************************************************/
538
540{
541
542// Execute this request in a synchronous fashion
543//
544 aiop->Result = this->write((XrdSfsFileOffset)aiop->sfsAio.aio_offset,
545 (char *)aiop->sfsAio.aio_buf,
547 aiop->doneWrite();
548 return 0;
549}
550
551/******************************************************************************/
552/* s t a t */
553/******************************************************************************/
554
555int XrdSfsNativeFile::stat(struct stat *buf) // Out
556/*
557 Function: Return file status information
558
559 Input: buf - The stat structiure to hold the results
560
561 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
562*/
563{
564 static const char *epname = "stat";
565
566// Execute the function
567//
568 if (XrdSfsUFS::Statfd(oh, buf))
569 return XrdSfsNative::Emsg(epname, error, errno, "state", fname);
570
571// All went well
572//
573 return SFS_OK;
574}
575
576/******************************************************************************/
577/* s y n c */
578/******************************************************************************/
579
581/*
582 Function: Commit all unwritten bytes to physical media.
583
584 Input: None
585
586 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
587*/
588{
589 static const char *epname = "sync";
590
591// Perform the function
592//
593 if (fsync(oh))
594 return XrdSfsNative::Emsg(epname,error,errno,"synchronize",fname);
595
596// All done
597//
598 return SFS_OK;
599}
600
601/******************************************************************************/
602/* s y n c A I O */
603/******************************************************************************/
604
606{
607
608// Execute this request in a synchronous fashion
609//
610 aiop->Result = this->sync();
611 aiop->doneWrite();
612 return 0;
613}
614
615/******************************************************************************/
616/* t r u n c a t e */
617/******************************************************************************/
618
620/*
621 Function: Set the length of the file object to 'flen' bytes.
622
623 Input: flen - The new size of the file.
624
625 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
626
627 Notes: If 'flen' is smaller than the current size of the file, the file
628 is made smaller and the data past 'flen' is discarded. If 'flen'
629 is larger than the current size of the file, a hole is created
630 (i.e., the file is logically extended by filling the extra bytes
631 with zeroes).
632*/
633{
634 static const char *epname = "trunc";
635
636// Make sure the offset is not too larg
637//
638 if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
639 return XrdSfsNative::Emsg(epname, error, EFBIG, "truncate", fname);
640
641// Perform the function
642//
643 if (ftruncate(oh, flen))
644 return XrdSfsNative::Emsg(epname, error, errno, "truncate", fname);
645
646// All done
647//
648 return SFS_OK;
649}
650
651/******************************************************************************/
652/* 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 */
653/******************************************************************************/
654/******************************************************************************/
655/* c h m o d */
656/******************************************************************************/
657
658int XrdSfsNative::chmod(const char *path, // In
659 XrdSfsMode Mode, // In
660 XrdOucErrInfo &error, // Out
661 const XrdSecClientName *client, // In
662 const char *info) // In
663/*
664 Function: Change the mode on a file or directory.
665
666 Input: path - Is the fully qualified name of the file to be removed.
667 einfo - Error information object to hold error details.
668 client - Authentication credentials, if any.
669 info - Opaque information, if any.
670
671 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
672*/
673{
674 static const char *epname = "chmod";
675 mode_t acc_mode = Mode & S_IAMB;
676
677// Perform the actual deletion
678//
679 if (XrdSfsUFS::Chmod(path, acc_mode) )
680 return XrdSfsNative::Emsg(epname,error,errno,"change mode on",path);
681
682// All done
683//
684 return SFS_OK;
685}
686
687/******************************************************************************/
688/* e x i s t s */
689/******************************************************************************/
690
691int XrdSfsNative::exists(const char *path, // In
692 XrdSfsFileExistence &file_exists, // Out
693 XrdOucErrInfo &error, // Out
694 const XrdSecClientName *client, // In
695 const char *info) // In
696/*
697 Function: Determine if file 'path' actually exists.
698
699 Input: path - Is the fully qualified name of the file to be tested.
700 file_exists - Is the address of the variable to hold the status of
701 'path' when success is returned. The values may be:
702 XrdSfsFileExistsIsDirectory - file not found but path is valid.
703 XrdSfsFileExistsIsFile - file found.
704 XrdSfsFileExistsIsNo - neither file nor directory.
705 einfo - Error information object holding the details.
706 client - Authentication credentials, if any.
707 info - Opaque information, if any.
708
709 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
710
711 Notes: When failure occurs, 'file_exists' is not modified.
712*/
713{
714 static const char *epname = "exists";
715 struct stat fstat;
716
717// Now try to find the file or directory
718//
719 if (!XrdSfsUFS::Statfn(path, &fstat) )
720 { if (S_ISDIR(fstat.st_mode)) file_exists=XrdSfsFileExistIsDirectory;
721 else if (S_ISREG(fstat.st_mode)) file_exists=XrdSfsFileExistIsFile;
722 else file_exists=XrdSfsFileExistNo;
723 return SFS_OK;
724 }
725 if (errno == ENOENT)
726 {file_exists=XrdSfsFileExistNo;
727 return SFS_OK;
728 }
729
730// An error occurred, return the error info
731//
732 return XrdSfsNative::Emsg(epname, error, errno, "locate", path);
733}
734
735/******************************************************************************/
736/* f s c t l */
737/******************************************************************************/
738
739int XrdSfsNative::fsctl(const int cmd,
740 const char *args,
741 XrdOucErrInfo &out_error,
742 const XrdSecClientName *client)
743{
744 out_error.setErrInfo(ENOTSUP, "Operation not supported.");
745 return SFS_ERROR;
746}
747
748/******************************************************************************/
749/* g e t V e r s i o n */
750/******************************************************************************/
751
752const char *XrdSfsNative::getVersion() {return XrdVERSION;}
753
754/******************************************************************************/
755/* m k d i r */
756/******************************************************************************/
757
758int XrdSfsNative::mkdir(const char *path, // In
759 XrdSfsMode Mode, // In
760 XrdOucErrInfo &error, // Out
761 const XrdSecClientName *client, // In
762 const char *info) // In
763/*
764 Function: Create a directory entry.
765
766 Input: path - Is the fully qualified name of the file to be removed.
767 Mode - Is the POSIX mode setting for the directory. If the
768 mode contains SFS_O_MKPTH, the full path is created.
769 einfo - Error information object to hold error details.
770 client - Authentication credentials, if any.
771 info - Opaque information, if any.
772
773 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
774*/
775{
776 static const char *epname = "mkdir";
777 mode_t acc_mode = Mode & S_IAMB;
778
779// Create the path if it does not already exist
780//
781 if (Mode & SFS_O_MKPTH) Mkpath(path, acc_mode, info);
782
783// Perform the actual deletion
784//
785 if (XrdSfsUFS::Mkdir(path, acc_mode) )
786 return XrdSfsNative::Emsg(epname,error,errno,"create directory",path);
787
788// All done
789//
790 return SFS_OK;
791}
792
793/******************************************************************************/
794/* M k p a t h */
795/******************************************************************************/
796/*
797 Function: Create a directory path
798
799 Input: path - Is the fully qualified name of the new path.
800 mode - The new mode that each new directory is to have.
801 info - Opaque information, of any.
802
803 Output: Returns 0 upon success and -errno upon failure.
804*/
805
806int XrdSfsNative::Mkpath(const char *path, mode_t mode, const char *info)
807{
808 char actual_path[MAXPATHLEN], *local_path, *next_path;
809 unsigned int plen;
810 struct stat buf;
811
812// Extract out the path we should make
813//
814 if (!(plen = strlen(path))) return -ENOENT;
815 if (plen >= sizeof(actual_path)) return -ENAMETOOLONG;
816 strcpy(actual_path, path);
817 if (actual_path[plen-1] == '/') actual_path[plen-1] = '\0';
818
819// Typically, the path exist. So, do a quick check before launching into it
820//
821 if (!(local_path = rindex(actual_path, (int)'/'))
822 || local_path == actual_path) return 0;
823 *local_path = '\0';
824 if (!XrdSfsUFS::Statfn(actual_path, &buf)) return 0;
825 *local_path = '/';
826
827// Start creating directories starting with the root. Notice that we will not
828// do anything with the last component. The caller is responsible for that.
829//
830 local_path = actual_path+1;
831 while((next_path = index(local_path, int('/'))))
832 {*next_path = '\0';
833 if (XrdSfsUFS::Mkdir(actual_path,mode) && errno != EEXIST)
834 return -errno;
835 *next_path = '/';
836 local_path = next_path+1;
837 }
838
839// All done
840//
841 return 0;
842}
843
844/******************************************************************************/
845/* r e m */
846/******************************************************************************/
847
848int XrdSfsNative::rem(const char *path, // In
849 XrdOucErrInfo &error, // Out
850 const XrdSecClientName *client, // In
851 const char *info) // In
852/*
853 Function: Delete a file from the namespace.
854
855 Input: path - Is the fully qualified name of the file to be removed.
856 einfo - Error information object to hold error details.
857 client - Authentication credentials, if any.
858 info - Opaque information, if any.
859
860 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
861*/
862{
863 static const char *epname = "rem";
864
865// Perform the actual deletion
866//
867 if (XrdSfsUFS::Rem(path) )
868 return XrdSfsNative::Emsg(epname, error, errno, "remove", path);
869
870// All done
871//
872 return SFS_OK;
873}
874
875/******************************************************************************/
876/* r e m d i r */
877/******************************************************************************/
878
879int XrdSfsNative::remdir(const char *path, // In
880 XrdOucErrInfo &error, // Out
881 const XrdSecClientName *client, // In
882 const char *info) // In
883/*
884 Function: Delete a directory from the namespace.
885
886 Input: path - Is the fully qualified name of the dir to be removed.
887 einfo - Error information object to hold error details.
888 client - Authentication credentials, if any.
889 info - Opaque information, if any.
890
891 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
892*/
893{
894 static const char *epname = "remdir";
895
896// Perform the actual deletion
897//
898 if (XrdSfsUFS::Remdir(path) )
899 return XrdSfsNative::Emsg(epname, error, errno, "remove", path);
900
901// All done
902//
903 return SFS_OK;
904}
905
906/******************************************************************************/
907/* r e n a m e */
908/******************************************************************************/
909
910int XrdSfsNative::rename(const char *old_name, // In
911 const char *new_name, // In
912 XrdOucErrInfo &error, //Out
913 const XrdSecClientName *client, // In
914 const char *infoO, // In
915 const char *infoN) // In
916/*
917 Function: Renames a file/directory with name 'old_name' to 'new_name'.
918
919 Input: old_name - Is the fully qualified name of the file to be renamed.
920 new_name - Is the fully qualified name that the file is to have.
921 error - Error information structure, if an error occurs.
922 client - Authentication credentials, if any.
923 info - old_name opaque information, if any.
924 info - new_name opaque information, if any.
925
926 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
927*/
928{
929 static const char *epname = "rename";
930
931// Perform actual rename operation
932//
933 if (XrdSfsUFS::Rename(old_name, new_name) )
934 return XrdSfsNative::Emsg(epname, error, errno, "rename", old_name);
935
936// All done
937//
938 return SFS_OK;
939}
940
941/******************************************************************************/
942/* s t a t */
943/******************************************************************************/
944
945int XrdSfsNative::stat(const char *path, // In
946 struct stat *buf, // Out
947 XrdOucErrInfo &error, // Out
948 const XrdSecClientName *client, // In
949 const char *info) // In
950/*
951 Function: Get info on 'path'.
952
953 Input: path - Is the fully qualified name of the file to be tested.
954 buf - The stat structiure to hold the results
955 error - Error information object holding the details.
956 client - Authentication credentials, if any.
957 info - Opaque information, if any.
958
959 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
960*/
961{
962 static const char *epname = "stat";
963
964// Execute the function
965//
966 if (XrdSfsUFS::Statfn(path, buf) )
967 return XrdSfsNative::Emsg(epname, error, errno, "state", path);
968
969// All went well
970//
971 return SFS_OK;
972}
973
974/******************************************************************************/
975/* t r u n c a t e */
976/******************************************************************************/
977
978int XrdSfsNative::truncate(const char *path, // In
979 XrdSfsFileOffset flen, // In
980 XrdOucErrInfo &error, // Out
981 const XrdSecClientName *client, // In
982 const char *info) // In
983/*
984 Function: Set the length of the file object to 'flen' bytes.
985
986 Input: path - The path to the file.
987 flen - The new size of the file.
988 einfo - Error information object to hold error details.
989 client - Authentication credentials, if any.
990 info - Opaque information, if any.
991
992 Output: Returns SFS_OK upon success and SFS_ERROR upon failure.
993
994 Notes: If 'flen' is smaller than the current size of the file, the file
995 is made smaller and the data past 'flen' is discarded. If 'flen'
996 is larger than the current size of the file, a hole is created
997 (i.e., the file is logically extended by filling the extra bytes
998 with zeroes).
999*/
1000{
1001 static const char *epname = "trunc";
1002
1003// Make sure the offset is not too larg
1004//
1005 if (sizeof(off_t) < sizeof(flen) && flen > 0x000000007fffffff)
1006 return XrdSfsNative::Emsg(epname, error, EFBIG, "truncate", path);
1007
1008// Perform the function
1009//
1010 if (XrdSfsUFS::Truncate(path, flen) )
1011 return XrdSfsNative::Emsg(epname, error, errno, "truncate", path);
1012
1013// All done
1014//
1015 return SFS_OK;
1016}
1017
1018/******************************************************************************/
1019/* E m s g */
1020/******************************************************************************/
1021
1022int XrdSfsNative::Emsg(const char *pfx, // Message prefix value
1023 XrdOucErrInfo &einfo, // Place to put text & error code
1024 int ecode, // The error code
1025 const char *op, // Operation being performed
1026 const char *target) // The target (e.g., fname)
1027{
1028 const char *etext;
1029 char buffer[MAXPATHLEN+80];
1030
1031// Get the reason for the error
1032//
1033 if (ecode < 0) ecode = -ecode;
1034 etext = XrdSysE2T(ecode);
1035
1036// Format the error message
1037//
1038 snprintf(buffer,sizeof(buffer),"Unable to %s %s; %s", op, target, etext);
1039
1040// Print it out if debugging is enabled
1041//
1042#ifndef NODEBUG
1043 eDest->Emsg(pfx, buffer);
1044#endif
1045
1046// Place the error message in the error object and return
1047//
1048 einfo.setErrInfo(ecode, buffer);
1049
1050 return SFS_ERROR;
1051}
#define S_IAMB
Definition XrdConfig.cc:160
static XrdSysError eDest(0,"crypto_")
#define close(a)
Definition XrdPosix.hh:48
#define rmdir(a)
Definition XrdPosix.hh:97
#define fsync(a)
Definition XrdPosix.hh:64
#define fstat(a, b)
Definition XrdPosix.hh:62
#define readdir_r(a, b, c)
Definition XrdPosix.hh:89
#define write(a, b, c)
Definition XrdPosix.hh:115
#define opendir(a)
Definition XrdPosix.hh:78
#define mkdir(a, b)
Definition XrdPosix.hh:74
#define open
Definition XrdPosix.hh:76
#define closedir(a)
Definition XrdPosix.hh:50
#define unlink(a)
Definition XrdPosix.hh:113
#define stat(a, b)
Definition XrdPosix.hh:101
#define rename(a, b)
Definition XrdPosix.hh:92
#define readdir(a)
Definition XrdPosix.hh:86
#define ftruncate(a, b)
Definition XrdPosix.hh:70
#define truncate(a, b)
Definition XrdPosix.hh:111
#define read(a, b, c)
Definition XrdPosix.hh:82
#define pwrite(a, b, c, d)
Definition XrdPosix.hh:107
#define pread(a, b, c, d)
Definition XrdPosix.hh:80
#define XrdSecClientName
int Mode
off_t aio_offset
Definition XrdSfsAio.hh:49
size_t aio_nbytes
Definition XrdSfsAio.hh:48
void * aio_buf
Definition XrdSfsAio.hh:47
int XrdSfsMode
#define SFS_ERROR
XrdSfsFileExistence
@ XrdSfsFileExistIsFile
@ XrdSfsFileExistNo
@ XrdSfsFileExistIsDirectory
#define SFS_O_MKPTH
#define SFS_O_RDONLY
#define SFS_O_WRONLY
#define SFS_FCTL_GETFD
#define SFS_O_CREAT
#define SFS_O_RDWR
int XrdSfsFileOpenMode
#define SFS_OK
long long XrdSfsFileOffset
#define SFS_O_TRUNC
int XrdSfsXferSize
XrdSfsFileSystem * XrdSfsGetFileSystem(XrdSfsFileSystem *native_fs, XrdSysLogger *lp)
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
void clear()
Reset data and error information to null. Any appenadges are released.
int setErrInfo(int code, const char *emsg)
int setErrCode(int code)
ssize_t Result
Definition XrdSfsAio.hh:65
virtual void doneRead()=0
struct aiocb sfsAio
Definition XrdSfsAio.hh:62
virtual void doneWrite()=0
XrdOucErrInfo & error
XrdOucErrInfo & error
const char * nextEntry()
int open(const char *dirName, const XrdSecClientName *client=0, const char *opaque=0)
int fctl(const int cmd, const char *args, XrdOucErrInfo &out_error)
XrdSfsXferSize readv(XrdOucIOVec *readV, int readCount)
int stat(struct stat *buf)
int open(const char *fileName, XrdSfsFileOpenMode openMode, mode_t createMode, const XrdSecClientName *client=0, const char *opaque=0)
XrdSfsXferSize write(XrdSfsFileOffset fileOffset, const char *buffer, XrdSfsXferSize buffer_size)
int read(XrdSfsFileOffset fileOffset, XrdSfsXferSize preread_sz)
int truncate(XrdSfsFileOffset fileOffset)
XrdSfsNative(XrdSysError *lp)
int rem(const char *path, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
int exists(const char *fileName, XrdSfsFileExistence &exists_flag, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
int truncate(const char *Name, XrdSfsFileOffset fileOffset, XrdOucErrInfo &out_error, const XrdSecEntity *client=0, const char *opaque=0)
int rename(const char *oldFileName, const char *newFileName, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaqueO=0, const char *opaqueN=0)
int fsctl(const int cmd, const char *args, XrdOucErrInfo &out_error, const XrdSecClientName *client=0)
static int Mkpath(const char *path, mode_t mode, const char *info=0)
int stat(const char *Name, struct stat *buf, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
int chmod(const char *Name, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
int remdir(const char *dirName, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
static int Emsg(const char *, XrdOucErrInfo &, int, const char *x, const char *y="")
const char * getVersion()
int mkdir(const char *dirName, XrdSfsMode Mode, XrdOucErrInfo &out_error, const XrdSecClientName *client=0, const char *opaque=0)
static int Mkdir(const char *fn, mode_t mode)
static int Rem(const char *fn)
static int Rename(const char *ofn, const char *nfn)
static int Truncate(const char *fn, off_t flen)
static int Open(const char *path, int oflag, mode_t omode)
static int Remdir(const char *fn)
static int Close(int fd)
static int Statfd(int fd, struct stat *buf)
static int Statfn(const char *fn, struct stat *buf)
static int Chmod(const char *fn, mode_t mode)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)