14f94c520f8d699a5973956a1716272146be17128Zonr Chang/*
24f94c520f8d699a5973956a1716272146be17128Zonr Chang * Copyright 2012, The Android Open Source Project
34f94c520f8d699a5973956a1716272146be17128Zonr Chang *
44f94c520f8d699a5973956a1716272146be17128Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
54f94c520f8d699a5973956a1716272146be17128Zonr Chang * you may not use this file except in compliance with the License.
64f94c520f8d699a5973956a1716272146be17128Zonr Chang * You may obtain a copy of the License at
74f94c520f8d699a5973956a1716272146be17128Zonr Chang *
84f94c520f8d699a5973956a1716272146be17128Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
94f94c520f8d699a5973956a1716272146be17128Zonr Chang *
104f94c520f8d699a5973956a1716272146be17128Zonr Chang * Unless required by applicable law or agreed to in writing, software
114f94c520f8d699a5973956a1716272146be17128Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
124f94c520f8d699a5973956a1716272146be17128Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f94c520f8d699a5973956a1716272146be17128Zonr Chang * See the License for the specific language governing permissions and
144f94c520f8d699a5973956a1716272146be17128Zonr Chang * limitations under the License.
154f94c520f8d699a5973956a1716272146be17128Zonr Chang */
164f94c520f8d699a5973956a1716272146be17128Zonr Chang
17c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#ifndef BCC_SUPPORT_FILE_BASE_H
18c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#define BCC_SUPPORT_FILE_BASE_H
194f94c520f8d699a5973956a1716272146be17128Zonr Chang
204f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <fcntl.h>
214f94c520f8d699a5973956a1716272146be17128Zonr Chang
224f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <string>
234f94c520f8d699a5973956a1716272146be17128Zonr Chang
244f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <llvm/Support/system_error.h>
254f94c520f8d699a5973956a1716272146be17128Zonr Chang
264f94c520f8d699a5973956a1716272146be17128Zonr Changnamespace android {
274f94c520f8d699a5973956a1716272146be17128Zonr Chang  class FileMap;
284f94c520f8d699a5973956a1716272146be17128Zonr Chang}
294f94c520f8d699a5973956a1716272146be17128Zonr Chang
304f94c520f8d699a5973956a1716272146be17128Zonr Changnamespace bcc {
314f94c520f8d699a5973956a1716272146be17128Zonr Chang
324f94c520f8d699a5973956a1716272146be17128Zonr Changclass FileBase {
334f94c520f8d699a5973956a1716272146be17128Zonr Changpublic:
344f94c520f8d699a5973956a1716272146be17128Zonr Chang  enum OpenModeEnum {
354f94c520f8d699a5973956a1716272146be17128Zonr Chang    kReadMode       = 1 << 0,
364f94c520f8d699a5973956a1716272146be17128Zonr Chang    kWriteMode      = 1 << 1,
374f94c520f8d699a5973956a1716272146be17128Zonr Chang    kReadWriteMode  = (kReadMode | kWriteMode),
384f94c520f8d699a5973956a1716272146be17128Zonr Chang  };
394f94c520f8d699a5973956a1716272146be17128Zonr Chang
404f94c520f8d699a5973956a1716272146be17128Zonr Chang  enum FlagEnum {
414f94c520f8d699a5973956a1716272146be17128Zonr Chang    // The openning file is a binary file.
424f94c520f8d699a5973956a1716272146be17128Zonr Chang    kBinary = 1 << 0,
43c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao
44c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao    // The openning file will be truncated to length 0.
45c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao    kTruncate = 1 << 1,
46b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao
47b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao    // The openning file will put its file pointer to the end of the file before
48b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao    // each write.
49b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao    kAppend = 1 << 2,
504f94c520f8d699a5973956a1716272146be17128Zonr Chang  };
514f94c520f8d699a5973956a1716272146be17128Zonr Chang
524f94c520f8d699a5973956a1716272146be17128Zonr Chang  enum LockModeEnum {
534f94c520f8d699a5973956a1716272146be17128Zonr Chang    // The shared resource behind the Stream locked in ReadLock mode can be
544f94c520f8d699a5973956a1716272146be17128Zonr Chang    // locked by other processes at the same time.
554f94c520f8d699a5973956a1716272146be17128Zonr Chang    kReadLock,
564f94c520f8d699a5973956a1716272146be17128Zonr Chang
574f94c520f8d699a5973956a1716272146be17128Zonr Chang    // The shared resource behind the Stream locked in WriteLock mode can only
584f94c520f8d699a5973956a1716272146be17128Zonr Chang    // be locked by one process. It's exclusive. That is, the shared resource
594f94c520f8d699a5973956a1716272146be17128Zonr Chang    // cannot have both ReadLock and WriteLock simultaneously.
604f94c520f8d699a5973956a1716272146be17128Zonr Chang    kWriteLock
614f94c520f8d699a5973956a1716272146be17128Zonr Chang  };
624f94c520f8d699a5973956a1716272146be17128Zonr Chang
634f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Default configuration to the lock().
644f94c520f8d699a5973956a1716272146be17128Zonr Chang  enum {
654f94c520f8d699a5973956a1716272146be17128Zonr Chang    kDefaultMaxRetryLock = 4,
664f94c520f8d699a5973956a1716272146be17128Zonr Chang    kDefaultRetryLockInterval = 200000UL,
674f94c520f8d699a5973956a1716272146be17128Zonr Chang  };
684f94c520f8d699a5973956a1716272146be17128Zonr Chang
694f94c520f8d699a5973956a1716272146be17128Zonr Changprotected:
704f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Grant direct access of the internal file descriptor to the sub-class and
714f94c520f8d699a5973956a1716272146be17128Zonr Chang  // error message such that they can implement their own I/O functionality.
724f94c520f8d699a5973956a1716272146be17128Zonr Chang  int mFD;
734f94c520f8d699a5973956a1716272146be17128Zonr Chang
744f94c520f8d699a5973956a1716272146be17128Zonr Chang  llvm::error_code mError;
754f94c520f8d699a5973956a1716272146be17128Zonr Chang
764f94c520f8d699a5973956a1716272146be17128Zonr Changprivate:
774f94c520f8d699a5973956a1716272146be17128Zonr Chang  std::string mName;
784f94c520f8d699a5973956a1716272146be17128Zonr Chang
794f94c520f8d699a5973956a1716272146be17128Zonr Chang  // The 2nd argument to the POSIX open().
804f94c520f8d699a5973956a1716272146be17128Zonr Chang  unsigned mOpenFlags;
814f94c520f8d699a5973956a1716272146be17128Zonr Chang
824f94c520f8d699a5973956a1716272146be17128Zonr Chang  // True true if we should call unlock() in destructor.
834f94c520f8d699a5973956a1716272146be17128Zonr Chang  bool mShouldUnlock;
844f94c520f8d699a5973956a1716272146be17128Zonr Chang
854f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Open mName with flag mOpenFlags (using POSIX open().)
864f94c520f8d699a5973956a1716272146be17128Zonr Chang  bool open();
874f94c520f8d699a5973956a1716272146be17128Zonr Chang
884f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Return true if mFD is the corresponded file descriptor to the file named
894f94c520f8d699a5973956a1716272146be17128Zonr Chang  // mName on the filesystem. This check may returns failed, for example,
904f94c520f8d699a5973956a1716272146be17128Zonr Chang  // someone re-create the file with the same name after we openning the file.
914f94c520f8d699a5973956a1716272146be17128Zonr Chang  bool checkFileIntegrity();
924f94c520f8d699a5973956a1716272146be17128Zonr Chang
934f94c520f8d699a5973956a1716272146be17128Zonr Chang  inline bool reopen() {
944f94c520f8d699a5973956a1716272146be17128Zonr Chang    // It's a private method, and all its callers are the few that can invoke it.
954f94c520f8d699a5973956a1716272146be17128Zonr Chang    // That is, the pre-condition will be checked by the caller. Therefore, we don't
964f94c520f8d699a5973956a1716272146be17128Zonr Chang    // need to check it again in reopen().
974f94c520f8d699a5973956a1716272146be17128Zonr Chang    close();
984f94c520f8d699a5973956a1716272146be17128Zonr Chang    return open();
994f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1004f94c520f8d699a5973956a1716272146be17128Zonr Chang
1014f94c520f8d699a5973956a1716272146be17128Zonr Changprivate:
1024f94c520f8d699a5973956a1716272146be17128Zonr Chang  FileBase(FileBase &); // Do not implement.
1034f94c520f8d699a5973956a1716272146be17128Zonr Chang  void operator=(const FileBase &); // Do not implement.
1044f94c520f8d699a5973956a1716272146be17128Zonr Chang
1054f94c520f8d699a5973956a1716272146be17128Zonr Changprotected:
1064f94c520f8d699a5973956a1716272146be17128Zonr Chang  // pOpenFlags is the 2nd argument to the POSIX open(). pFlags are the flags to
1074f94c520f8d699a5973956a1716272146be17128Zonr Chang  // FileBase. It's a bit set composed by the value defined in
1084f94c520f8d699a5973956a1716272146be17128Zonr Chang  // FileBase::FlagEnum.
1094f94c520f8d699a5973956a1716272146be17128Zonr Chang  FileBase(const std::string &pFilename, unsigned pOpenFlags, unsigned pFlags);
1104f94c520f8d699a5973956a1716272146be17128Zonr Chang
1114f94c520f8d699a5973956a1716272146be17128Zonr Chang  void detectError();
1124f94c520f8d699a5973956a1716272146be17128Zonr Chang
1134f94c520f8d699a5973956a1716272146be17128Zonr Changpublic:
1144f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Lock the file descriptor in given pMode. If pNonblocking is true, the lock
1154f94c520f8d699a5973956a1716272146be17128Zonr Chang  // request issued will return immediately when the shared resource is locked.
1164f94c520f8d699a5973956a1716272146be17128Zonr Chang  // In this case, it retries pMaxRetry times, each wait pRetryInterval (in
1174f94c520f8d699a5973956a1716272146be17128Zonr Chang  // usecs) before the previous retry getting done.
1184f94c520f8d699a5973956a1716272146be17128Zonr Chang  //
1194f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Only file is allowed to use this API.
1204f94c520f8d699a5973956a1716272146be17128Zonr Chang  bool lock(enum LockModeEnum pMode, bool pNonblocking = true,
1214f94c520f8d699a5973956a1716272146be17128Zonr Chang            unsigned pMaxRetry = kDefaultMaxRetryLock,
1224f94c520f8d699a5973956a1716272146be17128Zonr Chang            useconds_t pRetryInterval = kDefaultRetryLockInterval);
1234f94c520f8d699a5973956a1716272146be17128Zonr Chang
1244f94c520f8d699a5973956a1716272146be17128Zonr Chang  void unlock();
1254f94c520f8d699a5973956a1716272146be17128Zonr Chang
1264f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Map the file content to the memory.
1274f94c520f8d699a5973956a1716272146be17128Zonr Chang  //
1284f94c520f8d699a5973956a1716272146be17128Zonr Chang  // One who gets non-null android::FileMap returned from this API is responsible
1294f94c520f8d699a5973956a1716272146be17128Zonr Chang  // for destroying it after the use.
1304f94c520f8d699a5973956a1716272146be17128Zonr Chang  android::FileMap *createMap(off_t pOffset, size_t pLength, bool pIsReadOnly);
1314f94c520f8d699a5973956a1716272146be17128Zonr Chang
1324f94c520f8d699a5973956a1716272146be17128Zonr Chang  size_t getSize();
1334f94c520f8d699a5973956a1716272146be17128Zonr Chang
1344f94c520f8d699a5973956a1716272146be17128Zonr Chang  off_t seek(off_t pOffset);
1354f94c520f8d699a5973956a1716272146be17128Zonr Chang  off_t tell();
1364f94c520f8d699a5973956a1716272146be17128Zonr Chang
1374f94c520f8d699a5973956a1716272146be17128Zonr Chang  inline bool hasError() const
1384f94c520f8d699a5973956a1716272146be17128Zonr Chang  { return (mError.value() != llvm::errc::success); }
1394f94c520f8d699a5973956a1716272146be17128Zonr Chang
1404f94c520f8d699a5973956a1716272146be17128Zonr Chang  inline const llvm::error_code &getError() const
1414f94c520f8d699a5973956a1716272146be17128Zonr Chang  { return mError; }
1424f94c520f8d699a5973956a1716272146be17128Zonr Chang
1434f94c520f8d699a5973956a1716272146be17128Zonr Chang  // The return value of llvm::error_code::message() is obtained upon the call
1444f94c520f8d699a5973956a1716272146be17128Zonr Chang  // and is passed by value (that is, it's not a member of llvm::error_code.)
1454f94c520f8d699a5973956a1716272146be17128Zonr Chang  inline std::string getErrorMessage() const
1464f94c520f8d699a5973956a1716272146be17128Zonr Chang  { return mError.message(); }
1474f94c520f8d699a5973956a1716272146be17128Zonr Chang
1484f94c520f8d699a5973956a1716272146be17128Zonr Chang  inline const std::string &getName() const
1494f94c520f8d699a5973956a1716272146be17128Zonr Chang  { return mName; }
1504f94c520f8d699a5973956a1716272146be17128Zonr Chang
1514f94c520f8d699a5973956a1716272146be17128Zonr Chang  void close();
1524f94c520f8d699a5973956a1716272146be17128Zonr Chang
1534f94c520f8d699a5973956a1716272146be17128Zonr Chang  virtual ~FileBase();
1544f94c520f8d699a5973956a1716272146be17128Zonr Chang};
1554f94c520f8d699a5973956a1716272146be17128Zonr Chang
1564f94c520f8d699a5973956a1716272146be17128Zonr Chang} // end namespace bcc
1574f94c520f8d699a5973956a1716272146be17128Zonr Chang
158c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#endif  // BCC_SUPPORT_FILE_BASE_H
159