1 /*
2  * Copyright 2012, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef BCC_SUPPORT_FILE_BASE_H
18 #define BCC_SUPPORT_FILE_BASE_H
19 
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <string>
23 #include <system_error>
24 
25 namespace android {
26   class FileMap;
27 }
28 
29 namespace bcc {
30 
31 class FileBase {
32 public:
33   enum OpenModeEnum {
34     kReadMode       = 1 << 0,
35     kWriteMode      = 1 << 1,
36     kReadWriteMode  = (kReadMode | kWriteMode),
37   };
38 
39   enum FlagEnum {
40     kBinary = 1 << 0,
41     kTruncate = 1 << 1,
42     kAppend = 1 << 2,
43     kDeleteOnClose = 1 << 3
44   };
45 
46   enum LockModeEnum {
47     // The shared resource behind the Stream locked in ReadLock mode can be
48     // locked by other processes at the same time.
49     kReadLock,
50 
51     // The shared resource behind the Stream locked in WriteLock mode can only
52     // be locked by one process. It's exclusive. That is, the shared resource
53     // cannot have both ReadLock and WriteLock simultaneously.
54     kWriteLock
55   };
56 
57   // Default configuration to the lock().
58   enum {
59     kDefaultMaxRetryLock = 4,
60     kDefaultRetryLockInterval = 200000UL,
61   };
62 
63 protected:
64   // Grant direct access of the internal file descriptor to the sub-class and
65   // error message such that they can implement their own I/O functionality.
66   int mFD;
67 
68   std::error_code mError;
69 
70 private:
71   std::string mName;
72 
73   // The 2nd argument to the POSIX open().
74   unsigned mOpenFlags;
75 
76   // True true if we should call unlock() in destructor.
77   bool mShouldUnlock;
78 
79   // True if file should be deleted in destructor.
80   bool mShouldDelete;
81 
82   // Open mName with flag mOpenFlags (using POSIX open().)
83   bool open();
84 
85   // Return true if mFD is the corresponded file descriptor to the file named
86   // mName on the filesystem. This check may returns failed, for example,
87   // someone re-create the file with the same name after we openning the file.
88   bool checkFileIntegrity();
89 
reopen()90   inline bool reopen() {
91     // It's a private method, and all its callers are the few that can invoke it.
92     // That is, the pre-condition will be checked by the caller. Therefore, we don't
93     // need to check it again in reopen().
94     close();
95     return open();
96   }
97 
98 private:
99   FileBase(FileBase &); // Do not implement.
100   void operator=(const FileBase &); // Do not implement.
101 
102 protected:
103   // pOpenFlags is the 2nd argument to the POSIX open(). pFlags are the flags to
104   // FileBase. It's a bit set composed by the value defined in
105   // FileBase::FlagEnum.
106   FileBase(const std::string &pFilename, unsigned pOpenFlags, unsigned pFlags);
107 
108   void detectError();
109 
110 public:
111   // Lock the file descriptor in given pMode. If pNonblocking is true, the lock
112   // request issued will return immediately when the shared resource is locked.
113   // In this case, it retries pMaxRetry times, each wait pRetryInterval (in
114   // usecs) before the previous retry getting done.
115   //
116   // Only file is allowed to use this API.
117   bool lock(enum LockModeEnum pMode, bool pNonblocking = true,
118             unsigned pMaxRetry = kDefaultMaxRetryLock,
119             useconds_t pRetryInterval = kDefaultRetryLockInterval);
120 
121   void unlock();
122 
hasError()123   inline bool hasError() const
124   { return (bool) mError; }
125 
getError()126   inline const std::error_code &getError() const
127   { return mError; }
128 
129   // The return value of std::error_code::message() is obtained upon the call
130   // and is passed by value (that is, it's not a member of std::error_code.)
getErrorMessage()131   inline std::string getErrorMessage() const
132   { return mError.message(); }
133 
134   void close();
135 
136   virtual ~FileBase();
137 };
138 
139 } // end namespace bcc
140 
141 #endif  // BCC_SUPPORT_FILE_BASE_H
142