Modernize extfs(8) error handling.
This commit is contained in:
parent
ffc1b02b94
commit
edd8566155
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2015, 2016 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -22,8 +22,8 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -212,7 +212,7 @@ int main(int argc, char* argv[])
|
||||||
read = read || write;
|
read = read || write;
|
||||||
|
|
||||||
// Default to read and write filesystem access.
|
// Default to read and write filesystem access.
|
||||||
bool default_access = !read && !write ? read = write = true : false;
|
bool default_access = !read && !write ? (read = write = true) : false;
|
||||||
|
|
||||||
if ( argc == 1 )
|
if ( argc == 1 )
|
||||||
{
|
{
|
||||||
|
@ -236,74 +236,71 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
int fd = open(device_path, write ? O_RDWR : O_RDONLY);
|
int fd = open(device_path, write ? O_RDWR : O_RDONLY);
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
error(1, errno, "`%s'", device_path);
|
err(1, "%s", device_path);
|
||||||
|
|
||||||
// Read the super block from the filesystem so we can verify it.
|
// Read the super block from the filesystem so we can verify it.
|
||||||
struct ext_superblock sb;
|
struct ext_superblock sb;
|
||||||
if ( preadall(fd, &sb, sizeof(sb), 1024) != sizeof(sb) )
|
if ( preadall(fd, &sb, sizeof(sb), 1024) != sizeof(sb) )
|
||||||
{
|
{
|
||||||
if ( errno == EEOF )
|
if ( errno == EEOF )
|
||||||
error(1, 0, "`%s' isn't a valid extended filesystem", device_path);
|
errx(1, "%s: Isn't a valid extended filesystem", device_path);
|
||||||
else
|
else
|
||||||
error(1, errno, "read: `%s'", device_path);
|
err(1, "read: %s", device_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the magic value to detect a compatible filesystem.
|
// Verify the magic value to detect a compatible filesystem.
|
||||||
if ( sb.s_magic != EXT2_SUPER_MAGIC )
|
if ( sb.s_magic != EXT2_SUPER_MAGIC )
|
||||||
error(1, 0, "`%s' isn't a valid extended filesystem", device_path);
|
errx(1, "%s: Isn't a valid extended filesystem", device_path);
|
||||||
|
|
||||||
// Test whether this revision of the extended filesystem is supported.
|
// Test whether this revision of the extended filesystem is supported.
|
||||||
if ( sb.s_rev_level == EXT2_GOOD_OLD_REV )
|
if ( sb.s_rev_level == EXT2_GOOD_OLD_REV )
|
||||||
error(1, 0, "`%s' is formatted with an obsolete filesystem revision",
|
errx(1, "%s: Is formatted with an obsolete filesystem revision",
|
||||||
device_path);
|
device_path);
|
||||||
|
|
||||||
// Verify that no incompatible features are in use.
|
// Verify that no incompatible features are in use.
|
||||||
if ( sb.s_feature_compat & ~EXT2_FEATURE_INCOMPAT_SUPPORTED )
|
if ( sb.s_feature_compat & ~EXT2_FEATURE_INCOMPAT_SUPPORTED )
|
||||||
error(1, 0, "`%s' uses unsupported and incompatible features",
|
errx(1, "%s: Uses unsupported and incompatible features", device_path);
|
||||||
device_path);
|
|
||||||
|
|
||||||
// Verify that no incompatible features are in use if opening for write.
|
// Verify that no incompatible features are in use if opening for write.
|
||||||
if ( !default_access && write &&
|
if ( !default_access && write &&
|
||||||
sb.s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPPORTED )
|
sb.s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPPORTED )
|
||||||
error(1, 0, "`%s' uses unsupported and incompatible features, "
|
errx(1, "%s: Uses unsupported and incompatible features, "
|
||||||
"read-only access is possible, but write-access was "
|
"read-only access is possible, but write-access was requested",
|
||||||
"requested", device_path);
|
device_path);
|
||||||
|
|
||||||
if ( write && sb.s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPPORTED )
|
if ( write && sb.s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPPORTED )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Warning: `%s' uses unsupported and incompatible "
|
warn("warning: %s: Uses unsupported and incompatible features, "
|
||||||
"features, falling back to read-only access\n",
|
"falling back to read-only access\n", device_path);
|
||||||
device_path);
|
|
||||||
// TODO: Modify the file descriptor such that writing fails!
|
// TODO: Modify the file descriptor such that writing fails!
|
||||||
write = false;
|
write = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether any features are in use that we can safely disregard.
|
// Check whether any features are in use that we can safely disregard.
|
||||||
if ( sb.s_feature_compat & ~EXT2_FEATURE_COMPAT_SUPPORTED )
|
if ( sb.s_feature_compat & ~EXT2_FEATURE_COMPAT_SUPPORTED )
|
||||||
fprintf(stderr, "Note: filesystem uses unsupported but compatible "
|
warn("%s: Filesystem uses unsupported but compatible features\n",
|
||||||
"features\n");
|
device_path);
|
||||||
|
|
||||||
// Check the block size is sane. 64 KiB may have issues, 32 KiB then.
|
// Check the block size is sane. 64 KiB may have issues, 32 KiB then.
|
||||||
if ( sb.s_log_block_size > (15-10) /* 32 KiB blocks */ )
|
if ( sb.s_log_block_size > (15-10) /* 32 KiB blocks */ )
|
||||||
error(1, 0, "`%s': excess block size", device_path);
|
errx(1, "%s: Filesystem has excess block size", device_path);
|
||||||
|
|
||||||
// Check whether the filesystem was unmounted cleanly.
|
// Check whether the filesystem was unmounted cleanly.
|
||||||
if ( sb.s_state != EXT2_VALID_FS )
|
if ( sb.s_state != EXT2_VALID_FS )
|
||||||
fprintf(stderr, "Warning: `%s' wasn't unmounted cleanly\n",
|
warn("warning: %s: Filesystem wasn't unmounted cleanly\n", device_path);
|
||||||
device_path);
|
|
||||||
|
|
||||||
uint32_t block_size = 1024U << sb.s_log_block_size;
|
uint32_t block_size = 1024U << sb.s_log_block_size;
|
||||||
|
|
||||||
Device* dev = new Device(fd, device_path, block_size, write);
|
Device* dev = new Device(fd, device_path, block_size, write);
|
||||||
if ( !dev ) // TODO: Use operator new nothrow!
|
if ( !dev ) // TODO: Use operator new nothrow!
|
||||||
error(1, errno, "malloc");
|
err(1, "malloc");
|
||||||
Filesystem* fs = new Filesystem(dev, pretend_mount_path);
|
Filesystem* fs = new Filesystem(dev, pretend_mount_path);
|
||||||
if ( !fs ) // TODO: Use operator new nothrow!
|
if ( !fs ) // TODO: Use operator new nothrow!
|
||||||
error(1, errno, "malloc");
|
err(1, "malloc");
|
||||||
|
|
||||||
fs->block_groups = new BlockGroup*[fs->num_groups];
|
fs->block_groups = new BlockGroup*[fs->num_groups];
|
||||||
if ( !fs->block_groups ) // TODO: Use operator new nothrow!
|
if ( !fs->block_groups ) // TODO: Use operator new nothrow!
|
||||||
error(1, errno, "malloc");
|
err(1, "malloc");
|
||||||
for ( size_t i = 0; i < fs->num_groups; i++ )
|
for ( size_t i = 0; i < fs->num_groups; i++ )
|
||||||
fs->block_groups[i] = NULL;
|
fs->block_groups[i] = NULL;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2014, 2015, 2016, 2022 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2014, 2015, 2016, 2022, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,8 +24,8 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ioleast.h>
|
#include <ioleast.h>
|
||||||
|
@ -658,8 +658,8 @@ void HandleIncomingMessage(int chl, struct fsm_msg_header* hdr, Filesystem* fs)
|
||||||
if ( (uint16_t) request_uid != request_uid ||
|
if ( (uint16_t) request_uid != request_uid ||
|
||||||
(uint16_t) request_gid != request_gid )
|
(uint16_t) request_gid != request_gid )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "extfs: id exceeded 16-bit: uid=%ju gid=%ju\n",
|
warn("id exceeded 16-bit: uid=%ju gid=%ju\n",
|
||||||
(uintmax_t) request_uid, (uintmax_t) request_gid);
|
(uintmax_t) request_uid, (uintmax_t) request_gid);
|
||||||
RespondError(chl, EOVERFLOW);
|
RespondError(chl, EOVERFLOW);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -690,7 +690,7 @@ void HandleIncomingMessage(int chl, struct fsm_msg_header* hdr, Filesystem* fs)
|
||||||
handlers[FSM_REQ_TCGETBLOB] = (handler_t) HandleTCGetBlob;
|
handlers[FSM_REQ_TCGETBLOB] = (handler_t) HandleTCGetBlob;
|
||||||
if ( FSM_MSG_NUM <= hdr->msgtype || !handlers[hdr->msgtype] )
|
if ( FSM_MSG_NUM <= hdr->msgtype || !handlers[hdr->msgtype] )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "extfs: message type %zu not supported\n", hdr->msgtype);
|
warn("message type %zu not supported\n", hdr->msgtype);
|
||||||
RespondError(chl, ENOTSUP);
|
RespondError(chl, ENOTSUP);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -744,14 +744,14 @@ int fsmarshall_main(const char* argv0,
|
||||||
struct stat root_inode_st;
|
struct stat root_inode_st;
|
||||||
Inode* root_inode = fs->GetInode((uint32_t) EXT2_ROOT_INO);
|
Inode* root_inode = fs->GetInode((uint32_t) EXT2_ROOT_INO);
|
||||||
if ( !root_inode )
|
if ( !root_inode )
|
||||||
error(1, errno, "GetInode(%u)", EXT2_ROOT_INO);
|
err(1, "GetInode(%u)", EXT2_ROOT_INO);
|
||||||
StatInode(root_inode, &root_inode_st);
|
StatInode(root_inode, &root_inode_st);
|
||||||
root_inode->Unref();
|
root_inode->Unref();
|
||||||
|
|
||||||
// Create a filesystem server connected to the kernel that we'll listen on.
|
// Create a filesystem server connected to the kernel that we'll listen on.
|
||||||
int serverfd = fsm_mountat(AT_FDCWD, mount_path, &root_inode_st, 0);
|
int serverfd = fsm_mountat(AT_FDCWD, mount_path, &root_inode_st, 0);
|
||||||
if ( serverfd < 0 )
|
if ( serverfd < 0 )
|
||||||
error(1, errno, "%s", mount_path);
|
err(1, "%s", mount_path);
|
||||||
|
|
||||||
// Make sure the server isn't unexpectedly killed and data is lost.
|
// Make sure the server isn't unexpectedly killed and data is lost.
|
||||||
signal(SIGINT, TerminationHandler);
|
signal(SIGINT, TerminationHandler);
|
||||||
|
@ -763,7 +763,7 @@ int fsmarshall_main(const char* argv0,
|
||||||
{
|
{
|
||||||
pid_t child_pid = fork();
|
pid_t child_pid = fork();
|
||||||
if ( child_pid < 0 )
|
if ( child_pid < 0 )
|
||||||
error(1, errno, "fork");
|
err(1, "fork");
|
||||||
if ( child_pid )
|
if ( child_pid )
|
||||||
exit(0);
|
exit(0);
|
||||||
setpgid(0, 0);
|
setpgid(0, 0);
|
||||||
|
@ -785,7 +785,7 @@ int fsmarshall_main(const char* argv0,
|
||||||
size_t amount;
|
size_t amount;
|
||||||
if ( (amount = readall(channel, &hdr, sizeof(hdr))) != sizeof(hdr) )
|
if ( (amount = readall(channel, &hdr, sizeof(hdr))) != sizeof(hdr) )
|
||||||
{
|
{
|
||||||
//error(0, errno, "incomplete header: got %zi of %zu bytes", amount, sizeof(hdr));
|
//warn("incomplete header: got %zi of %zu bytes", amount, sizeof(hdr));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue