Loading...
--- dyld/dyld-1122.1.2/common/FileManager.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
- *
- * Copyright (c) 2021 Apple Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <TargetConditionals.h>
-
-#if !TARGET_OS_EXCLAVEKIT
-
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/attr.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/ucred.h>
-#include <sys/mount.h>
-#include <System/sys/fsgetpath.h>
-
-#include "FileManager.h"
-
-namespace dyld4 {
-
-using lsl::UUID;
-using lsl::UniquePtr;
-using lsl::Allocator;
-using lsl::OrderedMap;
-
-FileManager::FileManager(Allocator& allocator, const SyscallDelegate* syscall)
-: _syscall(syscall), _allocator(&allocator), _fsUUIDMap(_allocator->makeUnique<OrderedMap<uint64_t,UUID>>(*_allocator)) {}
-
-void FileManager::swap(FileManager& other) {
- using std::swap;
-
- std::swap(_allocator, other._allocator);
- std::swap(_fsUUIDMap, other._fsUUIDMap);
-}
-
-
-FileRecord FileManager::fileRecordForPath(Allocator& allocator, const char* filePath) {
- auto str = allocator.strdup(filePath);
- return FileRecord(*this, UniquePtr<const char>(str));
-}
-
-FileRecord FileManager::fileRecordForStat(const struct stat& sb) {
- return FileRecord(*this, sb);
-}
-
-FileRecord FileManager::fileRecordForVolumeUUIDAndObjID(const UUID& VID, uint64_t objectID) {
- return FileRecord(*this, VID, objectID);
-}
-
-FileRecord FileManager::fileRecordForVolumeDevIDAndObjID(uint64_t device, uint64_t objectID) {
-// auto volume = uuidForFileSystem(device);
-// char uuidString[64];
-// volume.dumpStr(&uuidString[0]);
-// fprintf(stderr, "device: %llu\n", device);
-// fprintf(stderr, "objectID: %llu\n", objectID);
-// fprintf(stderr, "VolumeUUID: %s\n", uuidString);
- return FileRecord(*this, objectID, device, 0);
-}
-
-FileRecord FileManager::fileRecordForFileID(const FileID& fileID) {
- return FileRecord(*this, fileID.inode(), fileID.device(), fileID.mtime());
-}
-
-
-void FileManager::reloadFSInfos() const {
- struct VolAttrBuf {
- u_int32_t length;
- dev_t dev;
- fsid_t fsid;
- vol_capabilities_attr_t volAttrs;
- uuid_t volUUID;
- } __attribute__((aligned(4), packed));
- typedef struct VolAttrBuf VolAttrBuf;
-
- while (1) {
- int fsCount = getfsstat(nullptr, 0, MNT_NOWAIT);
- if (fsCount == -1) {
- // getfsstat failed, stop scanning for file systems, compact info will use full paths
- break;
- }
- int fsInfoSize = fsCount*sizeof(struct statfs);
- auto fsInfos = (struct statfs *)_allocator->malloc(fsInfoSize);
- if (this->getfsstat(fsInfos, fsInfoSize, MNT_NOWAIT) != fsCount) {
- // Retry
- _allocator->free((void*)fsInfos);
- continue;
- }
- for (auto i = 0; i < fsCount; ++i) {
- // On darwin the lower 32 bits of a fsid_t are the same as an the dev_t
- // it comes from, excluding some special circumstances related to volume
- // groups that are not relevent here.
- uint64_t f_fsid = (*((uint64_t*)&fsInfos[i].f_fsid)) & 0x00ffffffff;
- if (_fsUUIDMap->find(f_fsid) != _fsUUIDMap->end()) { continue; }
-
- // getattrlist() can upcall when used against a non-root volume which results in a deadlock.
- if ((fsInfos[i].f_flags & MNT_ROOTFS) == 0) {
- _fsUUIDMap->insert({f_fsid, UUID()});
- continue;
- }
-
- int err;
- attrlist attrList;
- VolAttrBuf attrBuf;
-
- memset(&attrList, 0, sizeof(attrList));
- attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
- attrList.commonattr = ATTR_CMN_FSID | ATTR_CMN_DEVID;
- attrList.volattr = ATTR_VOL_INFO
- | ATTR_VOL_CAPABILITIES
- | ATTR_VOL_UUID;
- err = this->getattrlist(fsInfos[i].f_mntonname, &attrList, &attrBuf, sizeof(attrBuf), 0);
- if (err == 0 && (attrBuf.volAttrs.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_PERSISTENTOBJECTIDS)) {
- _fsUUIDMap->insert({f_fsid, attrBuf.volUUID});
- } else {
- _fsUUIDMap->insert({f_fsid, UUID()});
- }
- }
- _allocator->free((void*)fsInfos);
- break;
- }
-}
-
-const UUID FileManager::uuidForFileSystem(uint64_t fsid) const {
- return withFSInfoLock([&]{
- fsid &= 0x00ffffffff; // Mask off high bits that are an fs type tag
- auto i = _fsUUIDMap->find(fsid);
- if (i == _fsUUIDMap->end()) {
- // Maybe a new filesystem was loaded, try scanning
- reloadFSInfos();
- i = _fsUUIDMap->find(fsid);
- }
- if (i == _fsUUIDMap->end()) {
- // Still nothing, add a sentinel
- _fsUUIDMap->insert({fsid, UUID()});
- i = _fsUUIDMap->find(fsid);
- }
- assert (i != _fsUUIDMap->end());
- return i->second;
- });
-}
-
-uint64_t FileManager::fsidForUUID(const UUID& uuid) const {
- return withFSInfoLock([&]{
- for (const auto& i : *_fsUUIDMap) {
- if (i.second == uuid) {
- return i.first;
- }
- }
- // Maybe a new filesystem was loaded, try scanning
- // This is inefficient, but the only time it can happen is in libdyld reconsituting a compact info
- // after a volume is gone, so it is not worth the memory to make a reverse mapping table
- reloadFSInfos();
- for (const auto& i : *_fsUUIDMap) {
- if (i.second == uuid) {
- return i.first;
- }
- }
- return 0ULL;
- });
-}
-
-UniquePtr<char> FileManager::getPath(const UUID& VID, uint64_t OID) {
- if (!VID) { return nullptr; }
- uint64_t fsid = fsidForUUID(VID);
- return getPath(fsid, OID);
-}
-
-UniquePtr<char> FileManager::getPath(uint64_t fsid, uint64_t OID) {
- if ((fsid == 0) || (OID == 0)) { return nullptr; }
- char path[PATH_MAX];
- ssize_t result = this->fsgetpath(&path[0], PATH_MAX, fsid, OID);
-#if !__LP64__
- //FIXME: Workaround for missing stat high bit on 32 bit platforms
- if (result == -1) {
- OID = 0x0fffffff00000000ULL | OID;
- result = this->fsgetpath(&path[0], PATH_MAX, fsid, OID);
- }
-#endif
- if (result == -1) {
- return nullptr;
- }
- return UniquePtr<char>((char*)_allocator->strdup(path));
-}
-
-ssize_t FileManager::fsgetpath(char result[], size_t resultBufferSize, uint64_t fsID, uint64_t objID) const
-{
-#if BUILDING_DYLD
- return _syscall->fsgetpath(result, resultBufferSize, fsID, objID);
-#else
- fsid_t fsid = *reinterpret_cast<fsid_t*>(&fsID);
- return ::fsgetpath(result, resultBufferSize, &fsid, objID);
-#endif
-}
-
-int FileManager::getfsstat(struct statfs *buf, int bufsize, int flags) const {
-#if BUILDING_DYLD
- return _syscall->getfsstat(buf, bufsize, flags);
-#else
- return ::getfsstat(buf, bufsize, flags);
-#endif
-}
-
-int FileManager::getattrlist(const char* path, struct attrlist * attrList, void * attrBuf, size_t attrBufSize, uint32_t options)
-const {
-#if BUILDING_DYLD
- return _syscall->getattrlist(path, attrList, attrBuf, attrBufSize, options);
-#else
- return ::getattrlist(path, attrList, attrBuf, attrBufSize, options);
-#endif
-}
-
-#pragma mark -
-#pragma mark FileRecord
-
-FileRecord::FileRecord(FileManager& fileManager, const UUID& VID, uint64_t objectID)
- : _fileManager(&fileManager), _objectID(objectID), _volume(VID) {}
-
-FileRecord::FileRecord(FileManager& fileManager, UniquePtr<const char>&& FP)
- : _fileManager(&fileManager), _path(std::move(FP)) {}
-
-
-FileRecord::FileRecord(FileManager& fileManager, uint64_t objectID, uint64_t device, uint64_t mtime)
- : _fileManager(&fileManager), _objectID(objectID), _device(device), _volume(_fileManager->uuidForFileSystem(_device)), _mtime(mtime) {
- if (_objectID && _device && _mtime) {
- _statResult = 0;
- }
- }
-
-FileRecord::FileRecord(FileManager& fileManager, const struct stat& sb)
- : _fileManager(&fileManager), _objectID(sb.st_ino), _device(sb.st_dev), _volume(_fileManager->uuidForFileSystem(_device)), _mtime(sb.st_mtime), _statResult(0) {}
-
-FileRecord::FileRecord(const FileRecord& other)
- : _fileManager(other._fileManager), _objectID(other._objectID), _volume(other._volume),
- _path(UniquePtr<char>(_fileManager->_allocator->strdup(&*other._path))),
- _size(other._size), _mtime(other._mtime), _fd(other._fd), _statResult(other._statResult), _mode(other._mode),
- _valid(other._valid) {}
-
-FileRecord::FileRecord(FileRecord&& other) {
- swap(other);
-}
-
-FileRecord& FileRecord::operator=(const FileRecord& other) {
- auto tmp = other;
- swap(tmp);
- return *this;
-}
-FileRecord& FileRecord::operator=(FileRecord&& other) {
- swap(other);
- return *this;
-}
-
-FileRecord::~FileRecord() {
- close();
-}
-
-void FileRecord::swap(FileRecord& other) {
- std::swap(_volume, other._volume);
- std::swap(_objectID, other._objectID);
- std::swap(_device, other._device);
- std::swap(_path, other._path);
- std::swap(_fileManager, other._fileManager);
- std::swap(_size, other._size);
- std::swap(_mtime, other._mtime);
- std::swap(_fd, other._fd);
- std::swap(_statResult, other._statResult);
- std::swap(_mode, other._mode);
- std::swap(_valid, other._valid);
-}
-
-int FileRecord::open(int flags) {
- assert(_fd == -1);
- uint64_t fsid = 0;
- if (_volume) {
- fsid = _fileManager->fsidForUUID(_volume);
- }
- if (fsid && _objectID) {
- _fd = openbyid_np((fsid_t*)&fsid, (fsobj_id_t*)_objectID, flags);
- }
- if (_fd == -1) {
- _fd = ::open(getPath(), flags);
- }
- return _fd;
-}
-
-void FileRecord::close() {
- if (_fd != -1) {
- ::close(_fd);
- _fd = -1;
- }
-}
-
-bool FileRecord::exists() const {
- stat();
- return (_statResult == 0);
-}
-
-uint64_t FileRecord::objectID() const {
- if (_objectID == 0) { stat(); }
- return _objectID;
-}
-
-uint64_t FileRecord::mtime() const {
- if (_mtime == 0) {
- stat();
- }
- return _mtime;
-}
-
-size_t FileRecord::size() const {
- if (_size == 0) { stat(); }
- return _size;
-}
-
-void FileRecord::stat() const {
- if (_statResult != 1) { return; }
- struct stat stat_buf;
- if (_fd != -1) {
- _statResult = fstat(_fd, &stat_buf);
- } else {
- _statResult = ::stat(getPath(), &stat_buf);
- }
- if (_statResult != 0) { return; }
-
- _size = (size_t)stat_buf.st_size;
- _mtime = stat_buf.st_mtime;
- _mode = stat_buf.st_mode;
- if ((_objectID == 0) && !_volume) {
-#if __LP64__
- _objectID = stat_buf.st_ino;
-#else
- _objectID = stat_buf.st_ino & 0xFFFFFFFF; // HACK, work around inode randomly getting high bit set, making them uncomparable.
-#endif
- _volume = _fileManager->uuidForFileSystem(stat_buf.st_dev);
- }
-}
-
-const char* FileRecord::getPath() const {
- if (!_path) {
- if (_device) {
- _path = _fileManager->getPath(_device, _objectID);
- } else {
- _path = _fileManager->getPath(_volume, _objectID);
- }
- }
- return _path.withUnsafe([](const char * path){
- return path;
- });
-};
-
-FileManager& FileRecord::fileManager() const {
- return *_fileManager;
-}
-
-bool FileRecord::persistent() const {
- return (_volume && _objectID);
-}
-
-const UUID& FileRecord::volume() const {
- return _volume;
-}
-
-}; /* namedpace dyld4 */
-
-#endif // !TARGET_OS_EXCLAVEKIT