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#include "bcc/Support/FileBase.h"
184f94c520f8d699a5973956a1716272146be17128Zonr Chang
194f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <sys/file.h>
204f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <sys/stat.h>
214f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <unistd.h>
224f94c520f8d699a5973956a1716272146be17128Zonr Chang
234f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <cerrno>
244f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <new>
254f94c520f8d699a5973956a1716272146be17128Zonr Chang
264f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <utils/FileMap.h>
274f94c520f8d699a5973956a1716272146be17128Zonr Chang
284f94c520f8d699a5973956a1716272146be17128Zonr Changusing namespace bcc;
294f94c520f8d699a5973956a1716272146be17128Zonr Chang
304f94c520f8d699a5973956a1716272146be17128Zonr ChangFileBase::FileBase(const std::string &pFilename,
314f94c520f8d699a5973956a1716272146be17128Zonr Chang                   unsigned pOpenFlags,
324f94c520f8d699a5973956a1716272146be17128Zonr Chang                   unsigned pFlags)
334f94c520f8d699a5973956a1716272146be17128Zonr Chang  : mFD(-1),
344f94c520f8d699a5973956a1716272146be17128Zonr Chang    mError(),
354f94c520f8d699a5973956a1716272146be17128Zonr Chang    mName(pFilename), mOpenFlags(pOpenFlags),
364f94c520f8d699a5973956a1716272146be17128Zonr Chang    mShouldUnlock(false) {
374f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Process pFlags
384f94c520f8d699a5973956a1716272146be17128Zonr Chang#ifdef O_BINARY
394f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pFlags & kBinary) {
404f94c520f8d699a5973956a1716272146be17128Zonr Chang    mOpenFlags |= O_BINARY;
414f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
424f94c520f8d699a5973956a1716272146be17128Zonr Chang#endif
43c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao  if (pFlags & kTruncate) {
44c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao    mOpenFlags |= O_TRUNC;
45c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao  }
464f94c520f8d699a5973956a1716272146be17128Zonr Chang
47b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao  if (pFlags & kAppend) {
48b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao    mOpenFlags |= O_APPEND;
49b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao  }
50b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao
514f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Open the file.
524f94c520f8d699a5973956a1716272146be17128Zonr Chang  open();
534f94c520f8d699a5973956a1716272146be17128Zonr Chang
544f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
554f94c520f8d699a5973956a1716272146be17128Zonr Chang}
564f94c520f8d699a5973956a1716272146be17128Zonr Chang
574f94c520f8d699a5973956a1716272146be17128Zonr ChangFileBase::~FileBase() {
584f94c520f8d699a5973956a1716272146be17128Zonr Chang  close();
594f94c520f8d699a5973956a1716272146be17128Zonr Chang}
604f94c520f8d699a5973956a1716272146be17128Zonr Chang
614f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::open() {
624f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
634f94c520f8d699a5973956a1716272146be17128Zonr Chang    // FIXME: Hard-coded permissions (0644) for newly created file should be
644f94c520f8d699a5973956a1716272146be17128Zonr Chang    //        removed and provide a way to let the user configure the value.
654f94c520f8d699a5973956a1716272146be17128Zonr Chang    mFD = ::open(mName.c_str(), mOpenFlags, 0644);
664f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (mFD > 0) {
674f94c520f8d699a5973956a1716272146be17128Zonr Chang      return true;
684f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
694f94c520f8d699a5973956a1716272146be17128Zonr Chang
704f94c520f8d699a5973956a1716272146be17128Zonr Chang    // Some errors occurred ...
714f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (errno != EINTR) {
724f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
734f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
744f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
754f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
764f94c520f8d699a5973956a1716272146be17128Zonr Chang  // unreachable
774f94c520f8d699a5973956a1716272146be17128Zonr Chang}
784f94c520f8d699a5973956a1716272146be17128Zonr Chang
794f94c520f8d699a5973956a1716272146be17128Zonr Chang
804f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::checkFileIntegrity() {
814f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Check the file integrity by examining whether the inode referring to the mFD
824f94c520f8d699a5973956a1716272146be17128Zonr Chang  // and to the file mName are the same.
834f94c520f8d699a5973956a1716272146be17128Zonr Chang  struct stat fd_stat, file_stat;
844f94c520f8d699a5973956a1716272146be17128Zonr Chang
854f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Get the file status of file descriptor mFD.
864f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
874f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::fstat(mFD, &fd_stat) == 0) {
884f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
894f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
904f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
914f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
924f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
934f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
944f94c520f8d699a5973956a1716272146be17128Zonr Chang
954f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Get the file status of file mName.
964f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
974f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::stat(mName.c_str(), &file_stat) == 0) {
984f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
994f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
1004f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
1014f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
1024f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1034f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
1044f94c520f8d699a5973956a1716272146be17128Zonr Chang
1054f94c520f8d699a5973956a1716272146be17128Zonr Chang  return ((fd_stat.st_dev == file_stat.st_dev) &&
1064f94c520f8d699a5973956a1716272146be17128Zonr Chang          (fd_stat.st_ino == file_stat.st_ino));
1074f94c520f8d699a5973956a1716272146be17128Zonr Chang}
1084f94c520f8d699a5973956a1716272146be17128Zonr Chang
1094f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::detectError() {
1104f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Read error from errno.
1114f94c520f8d699a5973956a1716272146be17128Zonr Chang  mError.assign(errno, llvm::posix_category());
1124f94c520f8d699a5973956a1716272146be17128Zonr Chang}
1134f94c520f8d699a5973956a1716272146be17128Zonr Chang
1144f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::lock(enum LockModeEnum pMode,
1154f94c520f8d699a5973956a1716272146be17128Zonr Chang                    bool pNonblocking,
1164f94c520f8d699a5973956a1716272146be17128Zonr Chang                    unsigned pMaxRetry,
1174f94c520f8d699a5973956a1716272146be17128Zonr Chang                    useconds_t pRetryInterval) {
1184f94c520f8d699a5973956a1716272146be17128Zonr Chang  int lock_operation;
1194f94c520f8d699a5973956a1716272146be17128Zonr Chang  unsigned retry = 0;
1204f94c520f8d699a5973956a1716272146be17128Zonr Chang
1214f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Check the state.
1224f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
1234f94c520f8d699a5973956a1716272146be17128Zonr Chang    return false;
1244f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1254f94c520f8d699a5973956a1716272146be17128Zonr Chang
1264f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Return immediately if it's already locked.
1274f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mShouldUnlock) {
1284f94c520f8d699a5973956a1716272146be17128Zonr Chang    return true;
1294f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1304f94c520f8d699a5973956a1716272146be17128Zonr Chang
1314f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Determine the lock operation (2nd argument) to the flock().
1324f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pMode == kReadLock) {
1334f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation = LOCK_SH;
1344f94c520f8d699a5973956a1716272146be17128Zonr Chang  } else if (pMode == kWriteLock) {
1354f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation = LOCK_EX;
1364f94c520f8d699a5973956a1716272146be17128Zonr Chang  } else {
1374f94c520f8d699a5973956a1716272146be17128Zonr Chang    mError.assign(llvm::errc::invalid_argument, llvm::posix_category());
1384f94c520f8d699a5973956a1716272146be17128Zonr Chang    return false;
1394f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1404f94c520f8d699a5973956a1716272146be17128Zonr Chang
1414f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pNonblocking) {
1424f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation |= LOCK_NB;
1434f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1444f94c520f8d699a5973956a1716272146be17128Zonr Chang
1454f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
1464f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::flock(mFD, lock_operation) == 0) {
1474f94c520f8d699a5973956a1716272146be17128Zonr Chang      mShouldUnlock = true;
1484f94c520f8d699a5973956a1716272146be17128Zonr Chang      // Here we got a lock but we need to check whether the mFD still
1494f94c520f8d699a5973956a1716272146be17128Zonr Chang      // "represents" the filename (mName) we opened in the contructor. This
1504f94c520f8d699a5973956a1716272146be17128Zonr Chang      // check may failed when another process deleted the original file mFD
1514f94c520f8d699a5973956a1716272146be17128Zonr Chang      // mapped when we were trying to obtain the lock on the file.
1524f94c520f8d699a5973956a1716272146be17128Zonr Chang      if (!checkFileIntegrity()) {
1534f94c520f8d699a5973956a1716272146be17128Zonr Chang        if (hasError() || !reopen()) {
1544f94c520f8d699a5973956a1716272146be17128Zonr Chang          // Error occurred when check the file integrity or re-open the file.
1554f94c520f8d699a5973956a1716272146be17128Zonr Chang          return false;
1564f94c520f8d699a5973956a1716272146be17128Zonr Chang        } else {
1574f94c520f8d699a5973956a1716272146be17128Zonr Chang          // Wait a while before the next try.
1584f94c520f8d699a5973956a1716272146be17128Zonr Chang          ::usleep(pRetryInterval);
1594f94c520f8d699a5973956a1716272146be17128Zonr Chang          retry++;
1604f94c520f8d699a5973956a1716272146be17128Zonr Chang          continue;
1614f94c520f8d699a5973956a1716272146be17128Zonr Chang        }
1624f94c520f8d699a5973956a1716272146be17128Zonr Chang      }
1634f94c520f8d699a5973956a1716272146be17128Zonr Chang
1644f94c520f8d699a5973956a1716272146be17128Zonr Chang      return true;
1654f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1664f94c520f8d699a5973956a1716272146be17128Zonr Chang
1674f94c520f8d699a5973956a1716272146be17128Zonr Chang    // flock() was not performed successfully. Check the errno to see whether
1684f94c520f8d699a5973956a1716272146be17128Zonr Chang    // it's retry-able.
1694f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (errno == EINTR) {
1704f94c520f8d699a5973956a1716272146be17128Zonr Chang      // flock() was interrupted by delivery of a signal. Restart without
1714f94c520f8d699a5973956a1716272146be17128Zonr Chang      // decrement the retry counter.
1724f94c520f8d699a5973956a1716272146be17128Zonr Chang      continue;
1734f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno == EWOULDBLOCK) {
1744f94c520f8d699a5973956a1716272146be17128Zonr Chang      // The file descriptor was locked by others, wait for a while before next
1754f94c520f8d699a5973956a1716272146be17128Zonr Chang      // retry.
1764f94c520f8d699a5973956a1716272146be17128Zonr Chang      retry++;
1774f94c520f8d699a5973956a1716272146be17128Zonr Chang      ::usleep(pRetryInterval);
1784f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else {
1794f94c520f8d699a5973956a1716272146be17128Zonr Chang      // There's a fatal error occurs when perform flock(). Return immediately
1804f94c520f8d699a5973956a1716272146be17128Zonr Chang      // without further retry.
1814f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
1824f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
1834f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1844f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (retry <= pMaxRetry);
1854f94c520f8d699a5973956a1716272146be17128Zonr Chang
1864f94c520f8d699a5973956a1716272146be17128Zonr Chang  return false;
1874f94c520f8d699a5973956a1716272146be17128Zonr Chang}
1884f94c520f8d699a5973956a1716272146be17128Zonr Chang
1894f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::unlock() {
1904f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0) {
1914f94c520f8d699a5973956a1716272146be17128Zonr Chang    return;
1924f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1934f94c520f8d699a5973956a1716272146be17128Zonr Chang
1944f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
1954f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::flock(mFD, LOCK_UN) == 0) {
1964f94c520f8d699a5973956a1716272146be17128Zonr Chang      mShouldUnlock = false;
1974f94c520f8d699a5973956a1716272146be17128Zonr Chang      return;
1984f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1994f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2004f94c520f8d699a5973956a1716272146be17128Zonr Chang
2014f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2024f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
2034f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2044f94c520f8d699a5973956a1716272146be17128Zonr Chang
2054f94c520f8d699a5973956a1716272146be17128Zonr Changandroid::FileMap *FileBase::createMap(off_t pOffset, size_t pLength,
2064f94c520f8d699a5973956a1716272146be17128Zonr Chang                                      bool pIsReadOnly) {
2074f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0 || hasError()) {
2084f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2094f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2104f94c520f8d699a5973956a1716272146be17128Zonr Chang
2114f94c520f8d699a5973956a1716272146be17128Zonr Chang  android::FileMap *map = new (std::nothrow) android::FileMap();
2124f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (map == NULL) {
2134f94c520f8d699a5973956a1716272146be17128Zonr Chang    mError.assign(llvm::errc::not_enough_memory, llvm::system_category());
2144f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2154f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2164f94c520f8d699a5973956a1716272146be17128Zonr Chang
2174f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (!map->create(NULL, mFD, pOffset, pLength, pIsReadOnly)) {
2184f94c520f8d699a5973956a1716272146be17128Zonr Chang    detectError();
2194f94c520f8d699a5973956a1716272146be17128Zonr Chang    map->release();
2204f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2214f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2224f94c520f8d699a5973956a1716272146be17128Zonr Chang
2234f94c520f8d699a5973956a1716272146be17128Zonr Chang  return map;
2244f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2254f94c520f8d699a5973956a1716272146be17128Zonr Chang
2264f94c520f8d699a5973956a1716272146be17128Zonr Changsize_t FileBase::getSize() {
2274f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0 || hasError()) {
2284f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<size_t>(-1);
2294f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2304f94c520f8d699a5973956a1716272146be17128Zonr Chang
2314f94c520f8d699a5973956a1716272146be17128Zonr Chang  struct stat file_stat;
2324f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2334f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::fstat(mFD, &file_stat) == 0) {
2344f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
2354f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
2364f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
2374f94c520f8d699a5973956a1716272146be17128Zonr Chang      return static_cast<size_t>(-1);
2384f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2394f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
2404f94c520f8d699a5973956a1716272146be17128Zonr Chang
2414f94c520f8d699a5973956a1716272146be17128Zonr Chang  return file_stat.st_size;
2424f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2434f94c520f8d699a5973956a1716272146be17128Zonr Chang
2444f94c520f8d699a5973956a1716272146be17128Zonr Changoff_t FileBase::seek(off_t pOffset) {
2454f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
2464f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<off_t>(-1);
2474f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2484f94c520f8d699a5973956a1716272146be17128Zonr Chang
2494f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2504f94c520f8d699a5973956a1716272146be17128Zonr Chang    off_t result = ::lseek(mFD, pOffset, SEEK_SET);
2514f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (result == pOffset) {
2524f94c520f8d699a5973956a1716272146be17128Zonr Chang      return result;
2534f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2544f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2554f94c520f8d699a5973956a1716272146be17128Zonr Chang
2564f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2574f94c520f8d699a5973956a1716272146be17128Zonr Chang  return static_cast<off_t>(-1);
2584f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2594f94c520f8d699a5973956a1716272146be17128Zonr Chang
2604f94c520f8d699a5973956a1716272146be17128Zonr Changoff_t FileBase::tell() {
2614f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
2624f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<off_t>(-1);
2634f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2644f94c520f8d699a5973956a1716272146be17128Zonr Chang
2654f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2664f94c520f8d699a5973956a1716272146be17128Zonr Chang    off_t result = ::lseek(mFD, 0, SEEK_CUR);
2674f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (result != static_cast<off_t>(-1)) {
2684f94c520f8d699a5973956a1716272146be17128Zonr Chang      return result;
2694f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2704f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2714f94c520f8d699a5973956a1716272146be17128Zonr Chang
2724f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2734f94c520f8d699a5973956a1716272146be17128Zonr Chang  return static_cast<off_t>(-1);
2744f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2754f94c520f8d699a5973956a1716272146be17128Zonr Chang
2764f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::close() {
2774f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mShouldUnlock) {
2784f94c520f8d699a5973956a1716272146be17128Zonr Chang    unlock();
2794f94c520f8d699a5973956a1716272146be17128Zonr Chang    mShouldUnlock = false;
2804f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2814f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD > 0) {
2824f94c520f8d699a5973956a1716272146be17128Zonr Chang    ::close(mFD);
2834f94c520f8d699a5973956a1716272146be17128Zonr Chang    mFD = -1;
2844f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2854f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
2864f94c520f8d699a5973956a1716272146be17128Zonr Chang}
287