]>
Commit | Line | Data |
---|---|---|
e99fa721 | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
e99fa721 EB |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_BASE_FILE_H | |
10 | #define SQUID_BASE_FILE_H | |
11 | ||
12 | #include "sbuf/SBuf.h" | |
13 | ||
588512b3 AJ |
14 | #if HAVE_SYS_FILE_H |
15 | #include <sys/file.h> | |
16 | #endif | |
17 | ||
e99fa721 EB |
18 | /// How should a file be opened/created? Should it be locked? |
19 | class FileOpeningConfig | |
20 | { | |
21 | public: | |
22 | static FileOpeningConfig ReadOnly(); // shared reading | |
23 | static FileOpeningConfig ReadWrite(); // exclusive creation and/or reading/writing | |
24 | ||
25 | /* adjustment methods; named to work well with the File::Be::X shorthand */ | |
26 | ||
27 | /// protect concurrent accesses by attempting to obtain an appropriate lock | |
28 | FileOpeningConfig &locked(unsigned int attempts = 5); | |
29 | ||
30 | /// when opening a file for writing, create it if it does not exist | |
31 | FileOpeningConfig &createdIfMissing(); | |
32 | ||
33 | /// enter_suid() to open the file; leaves suid ASAP after that | |
34 | FileOpeningConfig &openedByRoot() { openByRoot = true; return *this; } | |
35 | ||
36 | /* add more mode adjustment methods as needed */ | |
37 | ||
38 | private: | |
39 | friend class File; | |
40 | ||
41 | /* file opening parameters */ | |
42 | #if _SQUID_WINDOWS_ | |
43 | DWORD desiredAccess = 0; ///< 2nd CreateFile() parameter | |
44 | DWORD shareMode = 0; ///< 3rd CreateFile() parameter | |
45 | DWORD creationDisposition = OPEN_EXISTING; ///< 5th CreateFile() parameter | |
46 | #else | |
47 | mode_t creationMask = 0; ///< umask() parameter; the default is S_IWGRP|S_IWOTH | |
48 | int openFlags = 0; ///< opening flags; 2nd open(2) parameter | |
49 | mode_t openMode = 0644; ///< access mode; 3rd open(2) parameter | |
50 | #endif | |
51 | ||
52 | /* file locking (disabled unless lock(n) sets positive lockAttempts) */ | |
53 | #if _SQUID_WINDOWS_ | |
54 | DWORD lockFlags = 0; ///< 2nd LockFileEx() parameter | |
55 | #elif _SQUID_SOLARIS_ | |
56 | int lockType = F_UNLCK; ///< flock::type member for fcntl(F_SETLK) | |
57 | #else | |
58 | int flockMode = LOCK_UN; ///< 2nd flock(2) parameter | |
59 | #endif | |
60 | static const unsigned int RetryGapUsec = 500000; /// pause before each lock retry | |
61 | unsigned int lockAttempts = 0; ///< how many times to try locking | |
62 | bool openByRoot = false; | |
63 | }; | |
64 | ||
65 | /// a portable locking-aware exception-friendly file (with RAII API) | |
66 | class File | |
67 | { | |
68 | public: | |
69 | typedef FileOpeningConfig Be; ///< convenient shorthand for File() callers | |
70 | ||
71 | /// \returns nil if File() throws or a new File object (otherwise) | |
72 | static File *Optional(const SBuf &aName, const FileOpeningConfig &cfg); | |
73 | ||
74 | File(const SBuf &aFilename, const FileOpeningConfig &cfg); ///< opens | |
75 | ~File(); ///< closes | |
76 | ||
77 | /* can move but cannot copy */ | |
78 | File(const File &) = delete; | |
79 | File &operator = (const File &) = delete; | |
80 | File(File &&other); | |
81 | File &operator = (File &&other); | |
82 | ||
83 | const SBuf &name() const { return name_; } | |
84 | ||
85 | /* system call wrappers */ | |
86 | ||
87 | /// makes the file size (and the current I/O offset) zero | |
88 | void truncate(); | |
89 | SBuf readSmall(SBuf::size_type minBytes, SBuf::size_type maxBytes); ///< read(2) for small files | |
90 | void writeAll(const SBuf &data); ///< write(2) with a "wrote everything" check | |
91 | void synchronize(); ///< fsync(2) | |
92 | ||
93 | protected: | |
886e99cd AR |
94 | bool isOpen() const { |
95 | #if _SQUID_WINDOWS_ | |
96 | return fd_ != InvalidHandle; | |
97 | #else | |
98 | return fd_ >= 0; | |
99 | #endif | |
100 | } | |
e99fa721 EB |
101 | |
102 | void open(const FileOpeningConfig &cfg); | |
103 | void lock(const FileOpeningConfig &cfg); | |
104 | void lockOnce(const FileOpeningConfig &cfg); | |
105 | void close(); | |
106 | ||
107 | /// \returns a description a system call-related failure | |
6c1219b9 | 108 | SBuf sysCallFailure(const char *callName, const SBuf &error) const; |
e99fa721 EB |
109 | /// \returns a description of an errno-based system call failure |
110 | SBuf sysCallError(const char *callName, const int savedErrno) const; | |
111 | ||
112 | private: | |
113 | SBuf name_; ///< location on disk | |
114 | ||
115 | // Windows-specific HANDLE is needed because LockFileEx() does not take POSIX FDs. | |
116 | #if _SQUID_WINDOWS_ | |
117 | typedef HANDLE Handle; | |
ee244464 | 118 | static const Handle InvalidHandle; |
e99fa721 EB |
119 | #else |
120 | typedef int Handle; | |
121 | static const Handle InvalidHandle = -1; | |
122 | #endif | |
123 | Handle fd_ = InvalidHandle; ///< OS-specific file handle | |
124 | }; | |
125 | ||
126 | #endif | |
127 |