103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved. 203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// Use of this source code is governed by a BSD-style license that can be 303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// found in the LICENSE file. 403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include "file.h" 603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <errno.h> 803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <fcntl.h> 9daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#ifdef __linux__ 10daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#include <linux/fs.h> 11daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#endif // __linux__ 1203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <string.h> 1303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <sys/ioctl.h> 1403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <sys/stat.h> 1503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <sys/types.h> 1603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <unistd.h> 1703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 1803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo// TEMP_FAILURE_RETRY is defined by some versions of <unistd.h>. 1903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#ifndef TEMP_FAILURE_RETRY 2003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <utils/Compat.h> 2103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#endif 2203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 2303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo#include <algorithm> 2403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 2503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymonamespace bsdiff { 2603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 2703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymostd::unique_ptr<File> File::FOpen(const char* pathname, int flags) { 28d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang int fd = TEMP_FAILURE_RETRY(open(pathname, flags, 0644)); 2903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (fd < 0) 3003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return std::unique_ptr<File>(); 3103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return std::unique_ptr<File>(new File(fd)); 3203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 3303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 3403f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoFile::~File() { 3503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo Close(); 3603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 3703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 3803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymobool File::Read(void* buf, size_t count, size_t* bytes_read) { 3903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (fd_ < 0) { 4003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EBADF; 4103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 4203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 4303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo ssize_t rc = TEMP_FAILURE_RETRY(read(fd_, buf, count)); 4403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (rc == -1) 4503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 4603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo *bytes_read = static_cast<size_t>(rc); 4703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return true; 4803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 4903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 5003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymobool File::Write(const void* buf, size_t count, size_t* bytes_written) { 5103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (fd_ < 0) { 5203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EBADF; 5303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 5403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 5503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo ssize_t rc = TEMP_FAILURE_RETRY(write(fd_, buf, count)); 5603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (rc == -1) 5703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 5803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo *bytes_written = static_cast<size_t>(rc); 5903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return true; 6003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 6103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 6203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymobool File::Seek(off_t pos) { 6303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (fd_ < 0) { 6403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EBADF; 6503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 6603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 6703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo // fseek() uses a long value for the offset which could be smaller than off_t. 6803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (pos > std::numeric_limits<long>::max()) { 6903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EOVERFLOW; 7003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 7103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 72d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang off_t newpos = lseek(fd_, pos, SEEK_SET); 7303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (newpos < 0) 7403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 7503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (newpos != pos) { 7603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EINVAL; 7703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 7803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 7903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return true; 8003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 8103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 8203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymobool File::Close() { 8303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (fd_ < 0) { 8403f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo errno = EBADF; 8503f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return false; 8603f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo } 8703f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo bool success = close(fd_) == 0; 8803f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo if (!success && errno == EINTR) 8903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo success = true; 9003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo fd_ = -1; 9103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo return success; 9203f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} 9303f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 94daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymobool File::GetSize(uint64_t* size) { 95daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo struct stat stbuf; 96daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (fstat(fd_, &stbuf) == -1) 97daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return false; 98daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (S_ISREG(stbuf.st_mode)) { 99d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang *size = stbuf.st_size; 100d87c83566c8411c16098dcc09ac56cce6007f9c6Sen Jiang return true; 101daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo } 102daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (S_ISBLK(stbuf.st_mode)) { 103daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#if defined(BLKGETSIZE64) 104daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return ioctl(fd_, BLKGETSIZE64, size); 105daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#elif defined(DKIOCGETBLOCKCOUNT) 106daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo uint64_t sectors = 0; 107daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (ioctl(fd_, DKIOCGETBLOCKCOUNT, §ors) == 0) { 108daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo *size = sectors << 9; 109daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return true; 110daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo } 111daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return false; 112daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#else 113daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo // Fall back to doing seeks to know the EOF. 114daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo off_t pos = lseek(fd_, 0, SEEK_CUR); 115daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (pos == -1) 116daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return false; 117daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo off_t end_pos = lseek(fd_, 0, SEEK_END); 118daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo if (end_pos == -1) 119daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return false; 120daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo *size = end_pos; 121daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo lseek(fd_, 0, SEEK_END); 122daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return true; 123daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo#endif 124daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo } 125daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo return false; 126daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo} 127daf35169e3fa51cc9ff468f12acd435a9b075266Alex Deymo 12803f1debab429e673ba5e9e317c5a04e36e850cefAlex DeymoFile::File(int fd) 12903f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo : fd_(fd) {} 13003f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo 13103f1debab429e673ba5e9e317c5a04e36e850cefAlex Deymo} // namespace bsdiff 132