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
19331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines#include "bcc/Support/Log.h"
20331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines
214f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <sys/file.h>
224f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <sys/stat.h>
234f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <unistd.h>
244f94c520f8d699a5973956a1716272146be17128Zonr Chang
254f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <cerrno>
26331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines#include <cstring>
274f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <new>
284f94c520f8d699a5973956a1716272146be17128Zonr Chang
294f94c520f8d699a5973956a1716272146be17128Zonr Chang#include <utils/FileMap.h>
304f94c520f8d699a5973956a1716272146be17128Zonr Chang
314f94c520f8d699a5973956a1716272146be17128Zonr Changusing namespace bcc;
324f94c520f8d699a5973956a1716272146be17128Zonr Chang
3348cd745480738c026312931877ecb8ebecb1c64eStephen Hines#ifdef _WIN32
3448cd745480738c026312931877ecb8ebecb1c64eStephen Hines// TODO: Fix flock usage under windows
3548cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define LOCK_SH 0
3648cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define LOCK_EX 0
3748cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define LOCK_NB 0
3848cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define LOCK_UN 0
3948cd745480738c026312931877ecb8ebecb1c64eStephen Hines
4048cd745480738c026312931877ecb8ebecb1c64eStephen Hinesint flock(int fd, int operation) {
4148cd745480738c026312931877ecb8ebecb1c64eStephen Hines  return 0;
4248cd745480738c026312931877ecb8ebecb1c64eStephen Hines}
4348cd745480738c026312931877ecb8ebecb1c64eStephen Hines#endif  // _WIN32
4448cd745480738c026312931877ecb8ebecb1c64eStephen Hines
454f94c520f8d699a5973956a1716272146be17128Zonr ChangFileBase::FileBase(const std::string &pFilename,
464f94c520f8d699a5973956a1716272146be17128Zonr Chang                   unsigned pOpenFlags,
474f94c520f8d699a5973956a1716272146be17128Zonr Chang                   unsigned pFlags)
484f94c520f8d699a5973956a1716272146be17128Zonr Chang  : mFD(-1),
494f94c520f8d699a5973956a1716272146be17128Zonr Chang    mError(),
504f94c520f8d699a5973956a1716272146be17128Zonr Chang    mName(pFilename), mOpenFlags(pOpenFlags),
51331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    mShouldUnlock(false),
52331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    mShouldDelete(false) {
534f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Process pFlags
544f94c520f8d699a5973956a1716272146be17128Zonr Chang#ifdef O_BINARY
554f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pFlags & kBinary) {
564f94c520f8d699a5973956a1716272146be17128Zonr Chang    mOpenFlags |= O_BINARY;
574f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
584f94c520f8d699a5973956a1716272146be17128Zonr Chang#endif
59c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao  if (pFlags & kTruncate) {
60c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao    mOpenFlags |= O_TRUNC;
61c02eae6f35de7dfd92233d591b27c05f15c2a6a1Shih-wei Liao  }
624f94c520f8d699a5973956a1716272146be17128Zonr Chang
63b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao  if (pFlags & kAppend) {
64b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao    mOpenFlags |= O_APPEND;
65b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao  }
66b2b8c64cd0524f9210218df4738f40409631ea26Shih-wei Liao
67331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines  if (pFlags & kDeleteOnClose) {
68331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    mShouldDelete = true;
69331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines  }
70331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines
714f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Open the file.
724f94c520f8d699a5973956a1716272146be17128Zonr Chang  open();
734f94c520f8d699a5973956a1716272146be17128Zonr Chang
744f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
754f94c520f8d699a5973956a1716272146be17128Zonr Chang}
764f94c520f8d699a5973956a1716272146be17128Zonr Chang
774f94c520f8d699a5973956a1716272146be17128Zonr ChangFileBase::~FileBase() {
784f94c520f8d699a5973956a1716272146be17128Zonr Chang  close();
794f94c520f8d699a5973956a1716272146be17128Zonr Chang}
804f94c520f8d699a5973956a1716272146be17128Zonr Chang
814f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::open() {
824f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
834f94c520f8d699a5973956a1716272146be17128Zonr Chang    // FIXME: Hard-coded permissions (0644) for newly created file should be
844f94c520f8d699a5973956a1716272146be17128Zonr Chang    //        removed and provide a way to let the user configure the value.
854f94c520f8d699a5973956a1716272146be17128Zonr Chang    mFD = ::open(mName.c_str(), mOpenFlags, 0644);
864f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (mFD > 0) {
874f94c520f8d699a5973956a1716272146be17128Zonr Chang      return true;
884f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
894f94c520f8d699a5973956a1716272146be17128Zonr Chang
904f94c520f8d699a5973956a1716272146be17128Zonr Chang    // Some errors occurred ...
914f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (errno != EINTR) {
924f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
934f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
944f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
954f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
964f94c520f8d699a5973956a1716272146be17128Zonr Chang  // unreachable
974f94c520f8d699a5973956a1716272146be17128Zonr Chang}
984f94c520f8d699a5973956a1716272146be17128Zonr Chang
994f94c520f8d699a5973956a1716272146be17128Zonr Chang
1004f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::checkFileIntegrity() {
1014f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Check the file integrity by examining whether the inode referring to the mFD
1024f94c520f8d699a5973956a1716272146be17128Zonr Chang  // and to the file mName are the same.
1034f94c520f8d699a5973956a1716272146be17128Zonr Chang  struct stat fd_stat, file_stat;
1044f94c520f8d699a5973956a1716272146be17128Zonr Chang
1054f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Get the file status of file descriptor mFD.
1064f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
1074f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::fstat(mFD, &fd_stat) == 0) {
1084f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
1094f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
1104f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
1114f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
1124f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1134f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
1144f94c520f8d699a5973956a1716272146be17128Zonr Chang
1154f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Get the file status of file mName.
1164f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
1174f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::stat(mName.c_str(), &file_stat) == 0) {
1184f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
1194f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
1204f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
1214f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
1224f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1234f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
1244f94c520f8d699a5973956a1716272146be17128Zonr Chang
1254f94c520f8d699a5973956a1716272146be17128Zonr Chang  return ((fd_stat.st_dev == file_stat.st_dev) &&
1264f94c520f8d699a5973956a1716272146be17128Zonr Chang          (fd_stat.st_ino == file_stat.st_ino));
1274f94c520f8d699a5973956a1716272146be17128Zonr Chang}
1284f94c520f8d699a5973956a1716272146be17128Zonr Chang
1294f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::detectError() {
1304f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Read error from errno.
131f21590eae009b4f596d7e448d0b8e142c46fc382Stephen Hines  mError.assign(errno, std::generic_category());
1324f94c520f8d699a5973956a1716272146be17128Zonr Chang}
1334f94c520f8d699a5973956a1716272146be17128Zonr Chang
1344f94c520f8d699a5973956a1716272146be17128Zonr Changbool FileBase::lock(enum LockModeEnum pMode,
1354f94c520f8d699a5973956a1716272146be17128Zonr Chang                    bool pNonblocking,
1364f94c520f8d699a5973956a1716272146be17128Zonr Chang                    unsigned pMaxRetry,
1374f94c520f8d699a5973956a1716272146be17128Zonr Chang                    useconds_t pRetryInterval) {
1384f94c520f8d699a5973956a1716272146be17128Zonr Chang  int lock_operation;
1394f94c520f8d699a5973956a1716272146be17128Zonr Chang  unsigned retry = 0;
1404f94c520f8d699a5973956a1716272146be17128Zonr Chang
1414f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Check the state.
1424f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
1434f94c520f8d699a5973956a1716272146be17128Zonr Chang    return false;
1444f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1454f94c520f8d699a5973956a1716272146be17128Zonr Chang
1464f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Return immediately if it's already locked.
1474f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mShouldUnlock) {
1484f94c520f8d699a5973956a1716272146be17128Zonr Chang    return true;
1494f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1504f94c520f8d699a5973956a1716272146be17128Zonr Chang
1514f94c520f8d699a5973956a1716272146be17128Zonr Chang  // Determine the lock operation (2nd argument) to the flock().
1524f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pMode == kReadLock) {
1534f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation = LOCK_SH;
1544f94c520f8d699a5973956a1716272146be17128Zonr Chang  } else if (pMode == kWriteLock) {
1554f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation = LOCK_EX;
1564f94c520f8d699a5973956a1716272146be17128Zonr Chang  } else {
157f21590eae009b4f596d7e448d0b8e142c46fc382Stephen Hines    mError = std::make_error_code(std::errc::invalid_argument);
1584f94c520f8d699a5973956a1716272146be17128Zonr Chang    return false;
1594f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1604f94c520f8d699a5973956a1716272146be17128Zonr Chang
1614f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (pNonblocking) {
1624f94c520f8d699a5973956a1716272146be17128Zonr Chang    lock_operation |= LOCK_NB;
1634f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
1644f94c520f8d699a5973956a1716272146be17128Zonr Chang
1654f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
1664f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::flock(mFD, lock_operation) == 0) {
1674f94c520f8d699a5973956a1716272146be17128Zonr Chang      mShouldUnlock = true;
1684f94c520f8d699a5973956a1716272146be17128Zonr Chang      // Here we got a lock but we need to check whether the mFD still
1694f94c520f8d699a5973956a1716272146be17128Zonr Chang      // "represents" the filename (mName) we opened in the contructor. This
1704f94c520f8d699a5973956a1716272146be17128Zonr Chang      // check may failed when another process deleted the original file mFD
1714f94c520f8d699a5973956a1716272146be17128Zonr Chang      // mapped when we were trying to obtain the lock on the file.
1724f94c520f8d699a5973956a1716272146be17128Zonr Chang      if (!checkFileIntegrity()) {
1734f94c520f8d699a5973956a1716272146be17128Zonr Chang        if (hasError() || !reopen()) {
1744f94c520f8d699a5973956a1716272146be17128Zonr Chang          // Error occurred when check the file integrity or re-open the file.
1754f94c520f8d699a5973956a1716272146be17128Zonr Chang          return false;
1764f94c520f8d699a5973956a1716272146be17128Zonr Chang        } else {
1774f94c520f8d699a5973956a1716272146be17128Zonr Chang          // Wait a while before the next try.
1784f94c520f8d699a5973956a1716272146be17128Zonr Chang          ::usleep(pRetryInterval);
1794f94c520f8d699a5973956a1716272146be17128Zonr Chang          retry++;
1804f94c520f8d699a5973956a1716272146be17128Zonr Chang          continue;
1814f94c520f8d699a5973956a1716272146be17128Zonr Chang        }
1824f94c520f8d699a5973956a1716272146be17128Zonr Chang      }
1834f94c520f8d699a5973956a1716272146be17128Zonr Chang
1844f94c520f8d699a5973956a1716272146be17128Zonr Chang      return true;
1854f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
1864f94c520f8d699a5973956a1716272146be17128Zonr Chang
1874f94c520f8d699a5973956a1716272146be17128Zonr Chang    // flock() was not performed successfully. Check the errno to see whether
1884f94c520f8d699a5973956a1716272146be17128Zonr Chang    // it's retry-able.
1894f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (errno == EINTR) {
1904f94c520f8d699a5973956a1716272146be17128Zonr Chang      // flock() was interrupted by delivery of a signal. Restart without
1914f94c520f8d699a5973956a1716272146be17128Zonr Chang      // decrement the retry counter.
1924f94c520f8d699a5973956a1716272146be17128Zonr Chang      continue;
1934f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno == EWOULDBLOCK) {
1944f94c520f8d699a5973956a1716272146be17128Zonr Chang      // The file descriptor was locked by others, wait for a while before next
1954f94c520f8d699a5973956a1716272146be17128Zonr Chang      // retry.
1964f94c520f8d699a5973956a1716272146be17128Zonr Chang      retry++;
1974f94c520f8d699a5973956a1716272146be17128Zonr Chang      ::usleep(pRetryInterval);
1984f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else {
1994f94c520f8d699a5973956a1716272146be17128Zonr Chang      // There's a fatal error occurs when perform flock(). Return immediately
2004f94c520f8d699a5973956a1716272146be17128Zonr Chang      // without further retry.
2014f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
2024f94c520f8d699a5973956a1716272146be17128Zonr Chang      return false;
2034f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2044f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (retry <= pMaxRetry);
2054f94c520f8d699a5973956a1716272146be17128Zonr Chang
2064f94c520f8d699a5973956a1716272146be17128Zonr Chang  return false;
2074f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2084f94c520f8d699a5973956a1716272146be17128Zonr Chang
2094f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::unlock() {
2104f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0) {
2114f94c520f8d699a5973956a1716272146be17128Zonr Chang    return;
2124f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2134f94c520f8d699a5973956a1716272146be17128Zonr Chang
2144f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2154f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::flock(mFD, LOCK_UN) == 0) {
2164f94c520f8d699a5973956a1716272146be17128Zonr Chang      mShouldUnlock = false;
2174f94c520f8d699a5973956a1716272146be17128Zonr Chang      return;
2184f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2194f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2204f94c520f8d699a5973956a1716272146be17128Zonr Chang
2214f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2224f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
2234f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2244f94c520f8d699a5973956a1716272146be17128Zonr Chang
2254f94c520f8d699a5973956a1716272146be17128Zonr Changandroid::FileMap *FileBase::createMap(off_t pOffset, size_t pLength,
2264f94c520f8d699a5973956a1716272146be17128Zonr Chang                                      bool pIsReadOnly) {
2274f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0 || hasError()) {
2284f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2294f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2304f94c520f8d699a5973956a1716272146be17128Zonr Chang
2314f94c520f8d699a5973956a1716272146be17128Zonr Chang  android::FileMap *map = new (std::nothrow) android::FileMap();
2324f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (map == NULL) {
233f21590eae009b4f596d7e448d0b8e142c46fc382Stephen Hines    mError = make_error_code(std::errc::not_enough_memory);
2344f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2354f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2364f94c520f8d699a5973956a1716272146be17128Zonr Chang
2374f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (!map->create(NULL, mFD, pOffset, pLength, pIsReadOnly)) {
2384f94c520f8d699a5973956a1716272146be17128Zonr Chang    detectError();
2394f94c520f8d699a5973956a1716272146be17128Zonr Chang    map->release();
2404f94c520f8d699a5973956a1716272146be17128Zonr Chang    return NULL;
2414f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2424f94c520f8d699a5973956a1716272146be17128Zonr Chang
2434f94c520f8d699a5973956a1716272146be17128Zonr Chang  return map;
2444f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2454f94c520f8d699a5973956a1716272146be17128Zonr Chang
2464f94c520f8d699a5973956a1716272146be17128Zonr Changsize_t FileBase::getSize() {
2474f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD < 0 || hasError()) {
2484f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<size_t>(-1);
2494f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2504f94c520f8d699a5973956a1716272146be17128Zonr Chang
2514f94c520f8d699a5973956a1716272146be17128Zonr Chang  struct stat file_stat;
2524f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2534f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (::fstat(mFD, &file_stat) == 0) {
2544f94c520f8d699a5973956a1716272146be17128Zonr Chang      break;
2554f94c520f8d699a5973956a1716272146be17128Zonr Chang    } else if (errno != EINTR) {
2564f94c520f8d699a5973956a1716272146be17128Zonr Chang      detectError();
2574f94c520f8d699a5973956a1716272146be17128Zonr Chang      return static_cast<size_t>(-1);
2584f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2594f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (true);
2604f94c520f8d699a5973956a1716272146be17128Zonr Chang
2614f94c520f8d699a5973956a1716272146be17128Zonr Chang  return file_stat.st_size;
2624f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2634f94c520f8d699a5973956a1716272146be17128Zonr Chang
2644f94c520f8d699a5973956a1716272146be17128Zonr Changoff_t FileBase::seek(off_t pOffset) {
2654f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
2664f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<off_t>(-1);
2674f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2684f94c520f8d699a5973956a1716272146be17128Zonr Chang
2694f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2704f94c520f8d699a5973956a1716272146be17128Zonr Chang    off_t result = ::lseek(mFD, pOffset, SEEK_SET);
2714f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (result == pOffset) {
2724f94c520f8d699a5973956a1716272146be17128Zonr Chang      return result;
2734f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2744f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2754f94c520f8d699a5973956a1716272146be17128Zonr Chang
2764f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2774f94c520f8d699a5973956a1716272146be17128Zonr Chang  return static_cast<off_t>(-1);
2784f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2794f94c520f8d699a5973956a1716272146be17128Zonr Chang
2804f94c520f8d699a5973956a1716272146be17128Zonr Changoff_t FileBase::tell() {
2814f94c520f8d699a5973956a1716272146be17128Zonr Chang  if ((mFD < 0) || hasError()) {
2824f94c520f8d699a5973956a1716272146be17128Zonr Chang    return static_cast<off_t>(-1);
2834f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
2844f94c520f8d699a5973956a1716272146be17128Zonr Chang
2854f94c520f8d699a5973956a1716272146be17128Zonr Chang  do {
2864f94c520f8d699a5973956a1716272146be17128Zonr Chang    off_t result = ::lseek(mFD, 0, SEEK_CUR);
2874f94c520f8d699a5973956a1716272146be17128Zonr Chang    if (result != static_cast<off_t>(-1)) {
2884f94c520f8d699a5973956a1716272146be17128Zonr Chang      return result;
2894f94c520f8d699a5973956a1716272146be17128Zonr Chang    }
2904f94c520f8d699a5973956a1716272146be17128Zonr Chang  } while (errno == EINTR);
2914f94c520f8d699a5973956a1716272146be17128Zonr Chang
2924f94c520f8d699a5973956a1716272146be17128Zonr Chang  detectError();
2934f94c520f8d699a5973956a1716272146be17128Zonr Chang  return static_cast<off_t>(-1);
2944f94c520f8d699a5973956a1716272146be17128Zonr Chang}
2954f94c520f8d699a5973956a1716272146be17128Zonr Chang
2964f94c520f8d699a5973956a1716272146be17128Zonr Changvoid FileBase::close() {
2974f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mShouldUnlock) {
2984f94c520f8d699a5973956a1716272146be17128Zonr Chang    unlock();
2994f94c520f8d699a5973956a1716272146be17128Zonr Chang    mShouldUnlock = false;
3004f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
3014f94c520f8d699a5973956a1716272146be17128Zonr Chang  if (mFD > 0) {
3024f94c520f8d699a5973956a1716272146be17128Zonr Chang    ::close(mFD);
3034f94c520f8d699a5973956a1716272146be17128Zonr Chang    mFD = -1;
3044f94c520f8d699a5973956a1716272146be17128Zonr Chang  }
305331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines  if (mShouldDelete) {
306331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    int res = ::remove(mName.c_str());
307331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    if (res != 0) {
308331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines      ALOGE("Failed to remove file: %s - %s", mName.c_str(), ::strerror(res));
309331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines    }
310331310e1f3f86a795f78e42b3f03558a43829f09Stephen Hines  }
3114f94c520f8d699a5973956a1716272146be17128Zonr Chang  return;
3124f94c520f8d699a5973956a1716272146be17128Zonr Chang}
313