Merge "Try SO_RCVBUF before SO_RCVBUFFORCE." am: 3f8fa0c215 am: dfcc7dbad0 am: 602a2ce0e0
am: 189527f13f
Change-Id: Ie4cdfd04c1acf48c802b233eb34b2417c859ae04
diff --git a/Android.mk b/Android.mk
index e92955f..9dba651 100644
--- a/Android.mk
+++ b/Android.mk
@@ -88,6 +88,8 @@
vold_cflags += -DTARGET_USES_MKE2FS
required_modules += mke2fs
else
+ # Adoptable storage has fully moved to mke2fs, so we need both tools
+ required_modules += mke2fs
required_modules += make_ext4fs
endif
endif
@@ -158,7 +160,10 @@
LOCAL_TIDY := true
LOCAL_TIDY_FLAGS := $(common_local_tidy_flags)
LOCAL_TIDY_CHECKS := $(common_local_tidy_checks)
-LOCAL_SRC_FILES:= secdiscard.cpp
+LOCAL_SRC_FILES:= \
+ FileDeviceUtils.cpp \
+ secdiscard.cpp \
+
LOCAL_MODULE:= secdiscard
LOCAL_SHARED_LIBRARIES := libbase
LOCAL_CFLAGS := $(vold_cflags)
diff --git a/AutoCloseFD.h b/AutoCloseFD.h
deleted file mode 100644
index 9b68469..0000000
--- a/AutoCloseFD.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <android-base/logging.h>
-
-// File descriptor which is automatically closed when this object is destroyed.
-// Cannot be copied, since that would cause double-closes.
-class AutoCloseFD {
-public:
- AutoCloseFD(const char *path, int flags = O_RDONLY, int mode = 0):
- fd{TEMP_FAILURE_RETRY(open(path, flags | O_CLOEXEC, mode))} {}
- AutoCloseFD(const std::string &path, int flags = O_RDONLY, int mode = 0):
- AutoCloseFD(path.c_str(), flags, mode) {}
- ~AutoCloseFD() {
- if (fd != -1) {
- int preserve_errno = errno;
- if (close(fd) == -1) {
- PLOG(ERROR) << "close(2) failed";
- };
- errno = preserve_errno;
- }
- }
- AutoCloseFD(const AutoCloseFD&) = delete;
- AutoCloseFD& operator=(const AutoCloseFD&) = delete;
- explicit operator bool() {return fd != -1;}
- int get() const {return fd;}
-private:
- const int fd;
-};
-
diff --git a/Disk.cpp b/Disk.cpp
index b424aba..9c22400 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -24,6 +24,7 @@
#include "Ext4Crypt.h"
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/logging.h>
#include <diskconfig/diskconfig.h>
@@ -446,7 +447,8 @@
status_t Disk::partitionMixed(int8_t ratio) {
int res;
- if (e4crypt_is_native()) {
+ if (e4crypt_is_native()
+ && !android::base::GetBoolProperty("persist.sys.adoptable_fbe", false)) {
LOG(ERROR) << "Private volumes not yet supported on FBE devices";
return -EINVAL;
}
@@ -469,9 +471,14 @@
// We've had some success above, so generate both the private partition
// GUID and encryption key and persist them.
std::string partGuidRaw;
+ if (GenerateRandomUuid(partGuidRaw) != OK) {
+ LOG(ERROR) << "Failed to generate GUID";
+ return -EIO;
+ }
+
std::string keyRaw;
- if (ReadRandomBytes(16, partGuidRaw) || ReadRandomBytes(16, keyRaw)) {
- LOG(ERROR) << "Failed to generate GUID or key";
+ if (ReadRandomBytes(16, keyRaw) != OK) {
+ LOG(ERROR) << "Failed to generate key";
return -EIO;
}
diff --git a/Ext4Crypt.cpp b/Ext4Crypt.cpp
index c3e0cc3..13cff0d 100644
--- a/Ext4Crypt.cpp
+++ b/Ext4Crypt.cpp
@@ -599,8 +599,7 @@
if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
- // For now, FBE is only supported on internal storage
- if (e4crypt_is_native() && volume_uuid == nullptr) {
+ if (e4crypt_is_native()) {
std::string de_raw_ref;
if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false;
if (!ensure_policy(de_raw_ref, system_de_path)) return false;
@@ -621,8 +620,7 @@
if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
- // For now, FBE is only supported on internal storage
- if (e4crypt_is_native() && volume_uuid == nullptr) {
+ if (e4crypt_is_native()) {
std::string ce_raw_ref;
if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false;
if (!ensure_policy(ce_raw_ref, system_ce_path)) return false;
diff --git a/FileDeviceUtils.cpp b/FileDeviceUtils.cpp
new file mode 100644
index 0000000..bc9f4bd
--- /dev/null
+++ b/FileDeviceUtils.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FileDeviceUtils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <linux/fiemap.h>
+#include <mntent.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+namespace {
+
+std::unique_ptr<struct fiemap> alloc_fiemap(uint32_t extent_count);
+
+}
+
+namespace android {
+namespace vold {
+
+// Given a file path, look for the corresponding block device in /proc/mount
+std::string BlockDeviceForPath(const std::string &path)
+{
+ std::unique_ptr<FILE, int(*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
+ if (!mnts) {
+ PLOG(ERROR) << "Unable to open /proc/mounts";
+ return "";
+ }
+ std::string result;
+ size_t best_length = 0;
+ struct mntent *mnt; // getmntent returns a thread local, so it's safe.
+ while ((mnt = getmntent(mnts.get())) != nullptr) {
+ auto l = strlen(mnt->mnt_dir);
+ if (l > best_length &&
+ path.size() > l &&
+ path[l] == '/' &&
+ path.compare(0, l, mnt->mnt_dir) == 0) {
+ result = mnt->mnt_fsname;
+ best_length = l;
+ }
+ }
+ if (result.empty()) {
+ LOG(ERROR) <<"Didn't find a mountpoint to match path " << path;
+ return "";
+ }
+ LOG(DEBUG) << "For path " << path << " block device is " << result;
+ return result;
+}
+
+std::unique_ptr<struct fiemap> PathFiemap(const std::string &path, uint32_t extent_count)
+{
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(
+ path.c_str(), O_RDONLY | O_CLOEXEC, 0)));
+ if (fd == -1) {
+ if (errno == ENOENT) {
+ PLOG(DEBUG) << "Unable to open " << path;
+ } else {
+ PLOG(ERROR) << "Unable to open " << path;
+ }
+ return nullptr;
+ }
+ auto fiemap = alloc_fiemap(extent_count);
+ if (ioctl(fd.get(), FS_IOC_FIEMAP, fiemap.get()) != 0) {
+ PLOG(ERROR) << "Unable to FIEMAP " << path;
+ return nullptr;
+ }
+ auto mapped = fiemap->fm_mapped_extents;
+ if (mapped < 1 || mapped > extent_count) {
+ LOG(ERROR) << "Extent count not in bounds 1 <= " << mapped << " <= " << extent_count
+ << " in " << path;
+ return nullptr;
+ }
+ return fiemap;
+}
+
+} // namespace vold
+} // namespace android
+
+namespace {
+
+std::unique_ptr<struct fiemap> alloc_fiemap(uint32_t extent_count)
+{
+ size_t allocsize = offsetof(struct fiemap, fm_extents[extent_count]);
+ std::unique_ptr<struct fiemap> res(new (::operator new (allocsize)) struct fiemap);
+ memset(res.get(), 0, allocsize);
+ res->fm_start = 0;
+ res->fm_length = UINT64_MAX;
+ res->fm_flags = 0;
+ res->fm_extent_count = extent_count;
+ res->fm_mapped_extents = 0;
+ return res;
+}
+
+}
diff --git a/FileDeviceUtils.h b/FileDeviceUtils.h
new file mode 100644
index 0000000..4c1d49a
--- /dev/null
+++ b/FileDeviceUtils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VOLD_FILEDEVICEUTILS_H
+#define ANDROID_VOLD_FILEDEVICEUTILS_H
+
+#include <string>
+#include <linux/fiemap.h>
+
+namespace android {
+namespace vold {
+
+// Given a file path, look for the corresponding block device in /proc/mount
+std::string BlockDeviceForPath(const std::string &path);
+
+// Read the file's FIEMAP
+std::unique_ptr<struct fiemap> PathFiemap(const std::string &path, uint32_t extent_count);
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index b707549..743e08c 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -29,10 +29,10 @@
#include <linux/dm-ioctl.h>
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include <fs_mgr.h>
-#include "AutoCloseFD.h"
#include "EncryptInplace.h"
#include "KeyStorage.h"
#include "KeyUtil.h"
@@ -105,8 +105,9 @@
}
static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t *nr_sec) {
- AutoCloseFD dev_fd(real_blkdev, O_RDONLY);
- if (!dev_fd) {
+ android::base::unique_fd dev_fd(TEMP_FAILURE_RETRY(open(
+ real_blkdev.c_str(), O_RDONLY | O_CLOEXEC, 0)));
+ if (dev_fd == -1) {
PLOG(ERROR) << "Unable to open " << real_blkdev << " to measure size";
return false;
}
@@ -143,8 +144,9 @@
static bool create_crypto_blk_dev(const std::string& dm_name, uint64_t nr_sec,
const std::string& target_type, const std::string& crypt_params,
std::string* crypto_blkdev) {
- AutoCloseFD dm_fd("/dev/device-mapper", O_RDWR);
- if (!dm_fd) {
+ android::base::unique_fd dm_fd(TEMP_FAILURE_RETRY(open(
+ "/dev/device-mapper", O_RDWR | O_CLOEXEC, 0)));
+ if (dm_fd == -1) {
PLOG(ERROR) << "Cannot open device-mapper";
return false;
}
diff --git a/MoveTask.cpp b/MoveTask.cpp
index ea64a1c..c565752 100644
--- a/MoveTask.cpp
+++ b/MoveTask.cpp
@@ -62,7 +62,8 @@
StringPrintf("%d", progress).c_str(), false);
}
-static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd) {
+static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd,
+ bool addWildcard) {
DIR* dir = opendir(path.c_str());
if (dir == NULL) {
return -1;
@@ -73,7 +74,11 @@
if ((!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, ".."))) {
continue;
}
- cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
+ if (addWildcard) {
+ cmd.push_back(StringPrintf("%s/%s/*", path.c_str(), ent->d_name));
+ } else {
+ cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
+ }
found = true;
}
closedir(dir);
@@ -90,7 +95,7 @@
cmd.push_back(kRmPath);
cmd.push_back("-f"); /* force: remove without confirmation, no error if it doesn't exist */
cmd.push_back("-R"); /* recursive: remove directory contents */
- if (pushBackContents(path, cmd) != OK) {
+ if (pushBackContents(path, cmd, true) != OK) {
LOG(WARNING) << "No contents in " << path;
return OK;
}
@@ -140,7 +145,7 @@
cmd.push_back("-R"); /* recurse into subdirectories (DEST must be a directory) */
cmd.push_back("-P"); /* Do not follow symlinks [default] */
cmd.push_back("-d"); /* don't dereference symlinks */
- if (pushBackContents(fromPath, cmd) != OK) {
+ if (pushBackContents(fromPath, cmd, false) != OK) {
LOG(WARNING) << "No contents in " << fromPath;
return OK;
}
diff --git a/Utils.cpp b/Utils.cpp
index 529cfb2..9699777 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -372,6 +372,17 @@
}
}
+status_t GenerateRandomUuid(std::string& out) {
+ status_t res = ReadRandomBytes(16, out);
+ if (res == OK) {
+ out[6] &= 0x0f; /* clear version */
+ out[6] |= 0x40; /* set to version 4 */
+ out[8] &= 0x3f; /* clear variant */
+ out[8] |= 0x80; /* set to IETF variant */
+ }
+ return res;
+}
+
status_t HexToStr(const std::string& hex, std::string& str) {
str.clear();
bool even = true;
diff --git a/Utils.h b/Utils.h
index 813ffac..7272fe1 100644
--- a/Utils.h
+++ b/Utils.h
@@ -78,6 +78,7 @@
pid_t ForkExecvpAsync(const std::vector<std::string>& args);
status_t ReadRandomBytes(size_t bytes, std::string& out);
+status_t GenerateRandomUuid(std::string& out);
/* Converts hex string to raw bytes, ignoring [ :-] */
status_t HexToStr(const std::string& hex, std::string& str);
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 6319362..43c8177 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -1302,29 +1302,24 @@
return rc;
}
-static int prep_data_fs(void)
+static void prep_data_fs(void)
{
- int i;
-
// NOTE: post_fs_data results in init calling back around to vold, so all
// callers to this method must be async
/* Do the prep of the /data filesystem */
property_set("vold.post_fs_data_done", "0");
property_set("vold.decrypt", "trigger_post_fs_data");
- SLOGD("Just triggered post_fs_data\n");
+ SLOGD("Just triggered post_fs_data");
/* Wait a max of 50 seconds, hopefully it takes much less */
- if (!android::base::WaitForProperty("vold.post_fs_data_done",
+ while (!android::base::WaitForProperty("vold.post_fs_data_done",
"1",
- std::chrono::seconds(50))) {
- /* Ugh, we failed to prep /data in time. Bail. */
- SLOGE("post_fs_data timed out!\n");
- return -1;
- } else {
- SLOGD("post_fs_data done\n");
- return 0;
+ std::chrono::seconds(15))) {
+ /* We timed out to prep /data in time. Continue wait. */
+ SLOGE("waited 15s for vold.post_fs_data_done, still waiting...");
}
+ SLOGD("post_fs_data done");
}
static void cryptfs_set_corrupt()
@@ -1475,9 +1470,7 @@
}
/* Create necessary paths on /data */
- if (prep_data_fs()) {
- return -1;
- }
+ prep_data_fs();
property_set("vold.decrypt", "trigger_load_persist_props");
/* startup service classes main and late_start */
@@ -1945,15 +1938,17 @@
SLOGI("Making empty filesystem with command %s %s %s %s %s %s\n",
args[0], args[1], args[2], args[3], args[4], args[5]);
} else if (type == F2FS_FS) {
- args[0] = "/system/bin/mkfs.f2fs";
+ args[0] = "/system/bin/make_f2fs";
args[1] = "-t";
args[2] = "-d1";
- args[3] = crypto_blkdev;
+ args[3] = "-f";
+ args[4] = "-O encrypt";
+ args[5] = crypto_blkdev;
snprintf(size_str, sizeof(size_str), "%" PRId64, size);
- args[4] = size_str;
- num_args = 5;
- SLOGI("Making empty filesystem with command %s %s %s %s %s\n",
- args[0], args[1], args[2], args[3], args[4]);
+ args[6] = size_str;
+ num_args = 7;
+ SLOGI("Making empty filesystem with command %s %s %s %s %s %s %s\n",
+ args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
} else {
SLOGE("cryptfs_enable_wipe(): unknown filesystem type %d\n", type);
return -1;
@@ -2216,9 +2211,7 @@
/* restart the framework. */
/* Create necessary paths on /data */
- if (prep_data_fs()) {
- goto error_shutting_down;
- }
+ prep_data_fs();
/* Ugh, shutting down the framework is not synchronous, so until it
* can be fixed, this horrible hack will wait a moment for it all to
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 0670bb5..adb8f2e 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -45,6 +45,7 @@
#include <selinux/selinux.h>
#include "Ext4.h"
+#include "Ext4Crypt.h"
#include "Utils.h"
#include "VoldUtil.h"
@@ -55,11 +56,7 @@
namespace ext4 {
static const char* kResizefsPath = "/system/bin/resize2fs";
-#ifdef TARGET_USES_MKE2FS
static const char* kMkfsPath = "/system/bin/mke2fs";
-#else
-static const char* kMkfsPath = "/system/bin/make_ext4fs";
-#endif
static const char* kFsckPath = "/system/bin/e2fsck";
bool IsSupported() {
@@ -170,7 +167,6 @@
std::vector<std::string> cmd;
cmd.push_back(kMkfsPath);
-#ifdef TARGET_USES_MKE2FS
cmd.push_back("-b");
cmd.push_back("4096");
@@ -180,28 +176,19 @@
cmd.push_back("-M");
cmd.push_back(target);
- cmd.push_back("-O");
- cmd.push_back("^has_journal");
-
- cmd.push_back(source);
-
- if (numSectors)
- cmd.push_back(StringPrintf("%lu", numSectors * (4096 / 512)));
-#else
- cmd.push_back("-J");
-
- cmd.push_back("-a");
- cmd.push_back(target);
-
- if (numSectors) {
- cmd.push_back("-l");
- cmd.push_back(StringPrintf("%lu", numSectors * 512));
+ std::string options("has_journal,quota");
+ if (e4crypt_is_native()) {
+ options += ",encrypt";
}
- // Always generate a real UUID
- cmd.push_back("-u");
+ cmd.push_back("-O");
+ cmd.push_back(options);
+
cmd.push_back(source);
-#endif
+
+ if (numSectors) {
+ cmd.push_back(StringPrintf("%lu", numSectors * (4096 / 512)));
+ }
return ForkExecvp(cmd);
}
diff --git a/secdiscard.cpp b/secdiscard.cpp
index fe51990..f9532ea 100644
--- a/secdiscard.cpp
+++ b/secdiscard.cpp
@@ -29,8 +29,9 @@
#include <mntent.h>
#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
-#include <AutoCloseFD.h>
+#include "FileDeviceUtils.h"
namespace {
@@ -44,10 +45,7 @@
bool read_command_line(int argc, const char * const argv[], Options &options);
void usage(const char *progname);
bool secdiscard_path(const std::string &path);
-std::unique_ptr<struct fiemap> path_fiemap(const std::string &path, uint32_t extent_count);
bool check_fiemap(const struct fiemap &fiemap, const std::string &path);
-std::unique_ptr<struct fiemap> alloc_fiemap(uint32_t extent_count);
-std::string block_device_for_path(const std::string &path);
bool overwrite_with_zeros(int fd, off64_t start, off64_t length);
}
@@ -99,16 +97,17 @@
// BLKSECDISCARD all content in "path", if it's small enough.
bool secdiscard_path(const std::string &path) {
- auto fiemap = path_fiemap(path, max_extents);
+ auto fiemap = android::vold::PathFiemap(path, max_extents);
if (!fiemap || !check_fiemap(*fiemap, path)) {
return false;
}
- auto block_device = block_device_for_path(path);
+ auto block_device = android::vold::BlockDeviceForPath(path);
if (block_device.empty()) {
return false;
}
- AutoCloseFD fs_fd(block_device, O_RDWR | O_LARGEFILE);
- if (!fs_fd) {
+ android::base::unique_fd fs_fd(TEMP_FAILURE_RETRY(open(
+ block_device.c_str(), O_RDWR | O_LARGEFILE | O_CLOEXEC, 0)));
+ if (fs_fd == -1) {
PLOG(ERROR) << "Failed to open device " << block_device;
return false;
}
@@ -125,32 +124,6 @@
return true;
}
-// Read the file's FIEMAP
-std::unique_ptr<struct fiemap> path_fiemap(const std::string &path, uint32_t extent_count)
-{
- AutoCloseFD fd(path);
- if (!fd) {
- if (errno == ENOENT) {
- PLOG(DEBUG) << "Unable to open " << path;
- } else {
- PLOG(ERROR) << "Unable to open " << path;
- }
- return nullptr;
- }
- auto fiemap = alloc_fiemap(extent_count);
- if (ioctl(fd.get(), FS_IOC_FIEMAP, fiemap.get()) != 0) {
- PLOG(ERROR) << "Unable to FIEMAP " << path;
- return nullptr;
- }
- auto mapped = fiemap->fm_mapped_extents;
- if (mapped < 1 || mapped > extent_count) {
- LOG(ERROR) << "Extent count not in bounds 1 <= " << mapped << " <= " << extent_count
- << " in " << path;
- return nullptr;
- }
- return fiemap;
-}
-
// Ensure that the FIEMAP covers the file and is OK to discard
bool check_fiemap(const struct fiemap &fiemap, const std::string &path) {
auto mapped = fiemap.fm_mapped_extents;
@@ -168,48 +141,6 @@
return true;
}
-std::unique_ptr<struct fiemap> alloc_fiemap(uint32_t extent_count)
-{
- size_t allocsize = offsetof(struct fiemap, fm_extents[extent_count]);
- std::unique_ptr<struct fiemap> res(new (::operator new (allocsize)) struct fiemap);
- memset(res.get(), 0, allocsize);
- res->fm_start = 0;
- res->fm_length = UINT64_MAX;
- res->fm_flags = 0;
- res->fm_extent_count = extent_count;
- res->fm_mapped_extents = 0;
- return res;
-}
-
-// Given a file path, look for the corresponding block device in /proc/mount
-std::string block_device_for_path(const std::string &path)
-{
- std::unique_ptr<FILE, int(*)(FILE*)> mnts(setmntent("/proc/mounts", "re"), endmntent);
- if (!mnts) {
- PLOG(ERROR) << "Unable to open /proc/mounts";
- return "";
- }
- std::string result;
- size_t best_length = 0;
- struct mntent *mnt; // getmntent returns a thread local, so it's safe.
- while ((mnt = getmntent(mnts.get())) != nullptr) {
- auto l = strlen(mnt->mnt_dir);
- if (l > best_length &&
- path.size() > l &&
- path[l] == '/' &&
- path.compare(0, l, mnt->mnt_dir) == 0) {
- result = mnt->mnt_fsname;
- best_length = l;
- }
- }
- if (result.empty()) {
- LOG(ERROR) <<"Didn't find a mountpoint to match path " << path;
- return "";
- }
- LOG(DEBUG) << "For path " << path << " block device is " << result;
- return result;
-}
-
bool overwrite_with_zeros(int fd, off64_t start, off64_t length) {
if (lseek64(fd, start, SEEK_SET) != start) {
PLOG(ERROR) << "Seek failed for zero overwrite";