Compare commits

..

36 Commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen c0d188f7b3 Add kernel(7) --firmware option. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 2132778b48 Add fatfs(8). 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 6a64cc5182 Add mtools port. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen f19b102315 Add getty(8). 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 8cdacf2b86 Add terminal and interrupt support to com(4). 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen b0a55a5652 Add nyan(1). 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 40067cecca Draft video-player. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 53fa8f4157 Work around pty deadlock. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen b3ec15f67b Add cdrom mounting live environment. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 864f3c3bf0 Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 285b35e8ee Parallelize driver initialization. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 719f44ec8a Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 835b156274 Decrease PS/2 timeouts. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 1b9c61c559 Add uptime(1) -pr options. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 88ea91c9e5 Add iso9660 filesystem implementation. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen edc6a870e7 Add kernel virtual address space usage debug information. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 9ec3997a58 Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 107db32735 Update to bison-3.8.2. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 47c8fc1381 Debug TCP socket state listing. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen f0e8196715 Add kernel heap allocation tracing debug facility. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen b24e46107d Trianglix 4. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen d884a034c0 Add tix-check(8). 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen 10c0f3b714 Volatile release. 2023-12-24 13:12:46 +01:00
Jonas 'Sortie' Termansen cbb2243b70 Add tix-upgrade(8). 2023-12-24 13:12:45 +01:00
Jonas 'Sortie' Termansen ce2238c3d3 Add signify port. 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 3a80f6eb76 Add pty(1). 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 312edb6a27 Add irc(1).
Co-authored-by: Juhani Krekelä <juhani@krekelä.fi>
2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 8955c6b85c Add getaddrinfo(1). 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 1534a67b8d Add host(1). 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 47ef7c7109 Enable stack smash protection by default. 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen 701f9025c9 Enable undefined behavior sanitization by default. 2023-12-24 13:12:26 +01:00
Jonas 'Sortie' Termansen b4665bc8ce Add m4, perl, and texinfo to the basic ports set. 2023-12-24 13:12:25 +01:00
Jonas 'Sortie' Termansen 2465f9b5dc Package the system as a tix binary package. 2023-12-24 12:58:53 +01:00
Jonas 'Sortie' Termansen 95cf3fba98 Save kernel options upon installation. 2023-12-19 00:05:42 +01:00
Jonas 'Sortie' Termansen dc98bcf0ca Add options to kernelinfo(2). 2023-12-19 00:05:42 +01:00
Jonas 'Sortie' Termansen 4aadc182a6 Fix broken manual references. 2023-12-19 00:05:42 +01:00
21 changed files with 402 additions and 1442 deletions

View File

@ -20,6 +20,7 @@ display \
dnsconfig \
editor \
ext \
fat \
games \
host \
hostname \
@ -255,7 +256,7 @@ sysroot-system: sysroot-fsh sysroot-base-headers
|| exit $$?; done)
LC_ALL=C sort -u "$(SYSROOT)/tix/manifest/system" > "$(SYSROOT)/tix/manifest/system.new"
mv "$(SYSROOT)/tix/manifest/system.new" "$(SYSROOT)/tix/manifest/system"
printf 'TIX_VERSION=3\nNAME=system\nPLATFORM=x86_64-sortix\nPREFIX=\nSYSTEM=true\n' > "$(SYSROOT)/tix/tixinfo/system"
printf 'TIX_VERSION=3\nNAME=system\nPLATFORM=$(HOST)\nPREFIX=\nSYSTEM=true\n' > "$(SYSROOT)/tix/tixinfo/system"
.PHONY: sysroot-source
sysroot-source: sysroot-fsh
@ -634,17 +635,12 @@ $(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/overlay.tar.xz: $(OVERLAY_INITR
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/src.tar.xz: $(SRC_INITRD) $(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot
xz -c $< > $@
# TODO: Temporary compatibility.
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/system.tar.xz: $(SYSTEM_INITRD) $(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot
xz -c $< > $@
.PHONY: release-boot
release-boot: \
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/sortix.bin.xz \
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/live.tar.xz \
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/overlay.tar.xz \
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/src.tar.xz \
$(SORTIX_RELEASE_DIR)/$(RELEASE)/$(MACHINE)/boot/system.tar.xz \
.PHONY: release-iso
release-iso: $(SORTIX_RELEASE_DIR)/$(RELEASE)/builds/$(BUILD_NAME).iso

View File

@ -127,9 +127,9 @@ if $mount; then
ports=
else
ports=$(ls repository |
grep -E '\.tix\.tar\.xz$' |
sed -E 's/\.tix\.tar\.xz$//' |
(grep -Ev '^system$' || true))
grep -E '\.tix\.tar\.xz$' |
sed -E 's/\.tix\.tar\.xz$//' |
(grep -Ev '^system$' || true))
fi
mkdir -p boot/grub

View File

@ -1,3 +1,4 @@
set_minimal="cut dash e2fsprogs grep grub libssl mdocml sed signify tar wget xargs xz"
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libstdc++ make m4 nano ntpd patch perl pkg-config python ssh texinfo vim"
set_basic="$set_minimal binutils bison bzip2 diffutils ed flex gawk gcc git gzip libcurl libcurses libstdc++ m4 make nano ntpd patch perl pkg-config python ssh texinfo vim xorriso"
sets="basic minimal"

View File

@ -2187,6 +2187,7 @@ static void on_mkpart(size_t argc, char** argv)
const char* mkfs_argv[] =
{
"mformat",
"-F", // TODO: Force FAT32 until FAT12/16 root dir writing is added.
"-i",
p->path,
NULL

View File

@ -1,276 +0,0 @@
/*
* Copyright (c) 2013, 2014, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* blockgroup.cpp
* Filesystem block group.
*/
#include <sys/types.h>
#include <assert.h>
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include "ext-constants.h"
#include "ext-structs.h"
#include "block.h"
#include "blockgroup.h"
#include "device.h"
#include "filesystem.h"
#include "util.h"
BlockGroup::BlockGroup(Filesystem* filesystem, uint32_t group_id)
{
this->data_block = NULL;
this->data = NULL;
this->filesystem = filesystem;
this->block_bitmap_chunk = NULL;
this->inode_bitmap_chunk = NULL;
this->reference_count = 1;
this->group_id = group_id;
this->block_alloc_chunk = 0;
this->inode_alloc_chunk = 0;
this->block_bitmap_chunk_i = 0;
this->inode_bitmap_chunk_i = 0;
this->first_block_id = filesystem->sb->s_first_data_block +
filesystem->sb->s_blocks_per_group * group_id;
this->first_inode_id = 1 +
filesystem->sb->s_inodes_per_group * group_id;
this->num_blocks = group_id+1== filesystem->num_groups ?
filesystem->num_blocks - first_block_id :
filesystem->sb->s_blocks_per_group;
this->num_inodes = group_id+1== filesystem->num_groups ?
filesystem->num_inodes - first_inode_id :
filesystem->sb->s_inodes_per_group;
size_t num_chunk_bits = filesystem->block_size * 8UL;
this->num_block_bitmap_chunks = divup(num_blocks, (uint32_t) num_chunk_bits);
this->num_inode_bitmap_chunks = divup(num_inodes, (uint32_t) num_chunk_bits);
this->dirty = false;
}
BlockGroup::~BlockGroup()
{
Sync();
if ( block_bitmap_chunk )
block_bitmap_chunk->Unref();
if ( inode_bitmap_chunk )
inode_bitmap_chunk->Unref();
if ( data_block )
data_block->Unref();
filesystem->block_groups[group_id] = NULL;
}
uint32_t BlockGroup::AllocateBlock()
{
if ( !filesystem->device->write )
return errno = EROFS, 0;
if ( !data->bg_free_blocks_count )
return errno = ENOSPC, 0;
size_t num_chunk_bits = filesystem->block_size * 8UL;
uint32_t begun_chunk = block_alloc_chunk;
for ( uint32_t i = 0; i < num_block_bitmap_chunks; i++ )
{
block_alloc_chunk = (begun_chunk + i) % num_block_bitmap_chunks;
bool last = block_alloc_chunk + 1 == num_block_bitmap_chunks;
if ( !block_bitmap_chunk )
{
uint32_t block_id = data->bg_block_bitmap + block_alloc_chunk;
block_bitmap_chunk = filesystem->device->GetBlock(block_id);
if ( !block_bitmap_chunk )
return 0;
block_bitmap_chunk_i = 0;
}
uint32_t chunk_offset = block_alloc_chunk * num_chunk_bits;
uint8_t* chunk_bits = block_bitmap_chunk->block_data;
size_t num_bits = last ? num_blocks - chunk_offset : num_chunk_bits;
// TODO: This can be made faster by caching if previous bits were set.
for ( ; block_bitmap_chunk_i < num_bits; block_bitmap_chunk_i++ )
{
if ( !checkbit(chunk_bits, block_bitmap_chunk_i) )
{
block_bitmap_chunk->BeginWrite();
setbit(chunk_bits, block_bitmap_chunk_i);
block_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_blocks_count--;
FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_blocks_count--;
filesystem->FinishWrite();
uint32_t group_block_id = chunk_offset + block_bitmap_chunk_i++;
uint32_t block_id = first_block_id + group_block_id;
return block_id;
}
}
block_bitmap_chunk->Unref();
block_bitmap_chunk = NULL;
}
BeginWrite();
data->bg_free_blocks_count = 0;
FinishWrite();
return errno = ENOSPC, 0;
}
uint32_t BlockGroup::AllocateInode()
{
if ( !filesystem->device->write )
return errno = EROFS, 0;
if ( !data->bg_free_inodes_count )
return errno = ENOSPC, 0;
size_t num_chunk_bits = filesystem->block_size * 8UL;
uint32_t begun_chunk = inode_alloc_chunk;
for ( uint32_t i = 0; i < num_inode_bitmap_chunks; i++ )
{
inode_alloc_chunk = (begun_chunk + i) % num_inode_bitmap_chunks;
bool last = inode_alloc_chunk + 1 == num_inode_bitmap_chunks;
if ( !inode_bitmap_chunk )
{
uint32_t block_id = data->bg_inode_bitmap + inode_alloc_chunk;
inode_bitmap_chunk = filesystem->device->GetBlock(block_id);
if ( !inode_bitmap_chunk )
return 0;
inode_bitmap_chunk_i = 0;
}
uint32_t chunk_offset = inode_alloc_chunk * num_chunk_bits;
uint8_t* chunk_bits = inode_bitmap_chunk->block_data;
size_t num_bits = last ? num_inodes - chunk_offset : num_chunk_bits;
// TODO: This can be made faster by caching if previous bits were set.
for ( ; inode_bitmap_chunk_i < num_bits; inode_bitmap_chunk_i++ )
{
if ( !checkbit(chunk_bits, inode_bitmap_chunk_i) )
{
inode_bitmap_chunk->BeginWrite();
setbit(chunk_bits, inode_bitmap_chunk_i);
inode_bitmap_chunk->FinishWrite();
BeginWrite();
data->bg_free_inodes_count--;
FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_inodes_count--;
filesystem->FinishWrite();
uint32_t group_inode_id = chunk_offset + inode_bitmap_chunk_i++;
uint32_t inode_id = first_inode_id + group_inode_id;
return inode_id;
}
}
inode_bitmap_chunk->Unref();
inode_bitmap_chunk = NULL;
}
BeginWrite();
data->bg_free_inodes_count = 0;
FinishWrite();
return errno = ENOSPC, 0;
}
void BlockGroup::FreeBlock(uint32_t block_id)
{
assert(filesystem->device->write);
block_id -= first_block_id;
size_t num_chunk_bits = filesystem->block_size * 8UL;
uint32_t chunk_id = block_id / num_chunk_bits;
uint32_t chunk_bit = block_id % num_chunk_bits;
if ( !block_bitmap_chunk || chunk_id != block_alloc_chunk )
{
if ( block_bitmap_chunk )
block_bitmap_chunk->Unref();
block_alloc_chunk = chunk_id;
uint32_t block_id = data->bg_block_bitmap + block_alloc_chunk;
block_bitmap_chunk = filesystem->device->GetBlock(block_id);
block_bitmap_chunk_i = 0;
}
block_bitmap_chunk->BeginWrite();
uint8_t* chunk_bits = block_bitmap_chunk->block_data;
clearbit(chunk_bits, chunk_bit);
block_bitmap_chunk->FinishWrite();
if ( chunk_bit < inode_bitmap_chunk_i )
block_bitmap_chunk_i = chunk_bit;
BeginWrite();
data->bg_free_blocks_count++;
FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_blocks_count++;
filesystem->FinishWrite();
}
void BlockGroup::FreeInode(uint32_t inode_id)
{
assert(filesystem->device->write);
inode_id -= first_inode_id;
size_t num_chunk_bits = filesystem->block_size * 8UL;
uint32_t chunk_id = inode_id / num_chunk_bits;
uint32_t chunk_bit = inode_id % num_chunk_bits;
if ( !inode_bitmap_chunk || chunk_id != inode_alloc_chunk )
{
if ( inode_bitmap_chunk )
inode_bitmap_chunk->Unref();
inode_alloc_chunk = chunk_id;
uint32_t block_id = data->bg_inode_bitmap + inode_alloc_chunk;
inode_bitmap_chunk = filesystem->device->GetBlock(block_id);
inode_bitmap_chunk_i = 0;
}
inode_bitmap_chunk->BeginWrite();
uint8_t* chunk_bits = inode_bitmap_chunk->block_data;
clearbit(chunk_bits, chunk_bit);
inode_bitmap_chunk->FinishWrite();
if ( chunk_bit < inode_bitmap_chunk_i )
inode_bitmap_chunk_i = chunk_bit;
BeginWrite();
data->bg_free_inodes_count++;
FinishWrite();
filesystem->BeginWrite();
filesystem->sb->s_free_inodes_count++;
filesystem->FinishWrite();
}
void BlockGroup::Refer()
{
// TODO
}
void BlockGroup::Unref()
{
// TODO
}
void BlockGroup::Sync()
{
if ( block_bitmap_chunk )
block_bitmap_chunk->Sync();
if ( inode_bitmap_chunk )
inode_bitmap_chunk->Sync();
if ( dirty )
data_block->Sync();
dirty = false;
}
void BlockGroup::BeginWrite()
{
data_block->BeginWrite();
}
void BlockGroup::FinishWrite()
{
dirty = true;
data_block->FinishWrite();
Use();
}
void BlockGroup::Use()
{
}

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2013, 2014, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* blockgroup.h
* Filesystem block group.
*/
#ifndef BLOCKGROUP_H
#define BLOCKGROUP_H
class Block;
class Filesystem;
class BlockGroup
{
public:
BlockGroup(Filesystem* filesystem, uint32_t group_id);
~BlockGroup();
public:
Block* data_block;
struct ext_blockgrpdesc* data;
Filesystem* filesystem;
Block* block_bitmap_chunk;
Block* inode_bitmap_chunk;
size_t reference_count;
uint32_t group_id;
uint32_t block_alloc_chunk;
uint32_t inode_alloc_chunk;
uint32_t block_bitmap_chunk_i;
uint32_t inode_bitmap_chunk_i;
uint32_t first_block_id;
uint32_t first_inode_id;
uint32_t num_blocks;
uint32_t num_inodes;
uint32_t num_block_bitmap_chunks;
uint32_t num_inode_bitmap_chunks;
bool dirty;
public:
uint32_t AllocateBlock();
uint32_t AllocateInode();
void FreeBlock(uint32_t block_id);
void FreeInode(uint32_t inode_id);
void Refer();
void Unref();
void Sync();
void BeginWrite();
void FinishWrite();
void Use();
void Unlink();
void Prelink();
};
#endif

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ext-constants.h
* Constants for the extended filesystem.
*/
#ifndef EXT_CONSTANTS_H
#define EXT_CONSTANTS_H
static const uint16_t FAT_SUPER_MAGIC = 0xEF53;
static const uint16_t FAT_VALID_FS = 1;
static const uint16_t FAT_ERROR_FS = 2;
static const uint16_t FAT_ERRORS_CONTINUE = 1;
static const uint16_t FAT_ERRORS_RO = 2;
static const uint16_t FAT_ERRORS_PANIC = 3;
static const uint32_t FAT_OS_LINUX = 0;
static const uint32_t FAT_OS_HURD = 1;
static const uint32_t FAT_OS_MASIX = 2;
static const uint32_t FAT_OS_FREEBSD = 3;
static const uint32_t FAT_OS_LITES = 4;
static const uint32_t FAT_GOOD_OLD_REV = 0;
static const uint32_t FAT_DYNAMIC_REV = 1;
static const uint16_t FAT_DEF_RESUID = 0;
static const uint16_t FAT_DEF_RESGID = 0;
static const uint16_t FAT_GOOD_OLD_FIRST_INO = 11;
static const uint16_t FAT_GOOD_OLD_INODE_SIZE = 128;
static const uint32_t FAT_FEATURE_COMPAT_DIR_PREALLOC = 1U << 0U;
static const uint32_t FAT_FEATURE_COMPAT_IMAGIC_INODES = 1U << 1U;
static const uint32_t EXT3_FEATURE_COMPAT_HAS_JOURNAL = 1U << 2U;
static const uint32_t FAT_FEATURE_COMPAT_EXT_ATTR = 1U << 3U;
static const uint32_t FAT_FEATURE_COMPAT_RESIZE_INO = 1U << 4U;
static const uint32_t FAT_FEATURE_COMPAT_DIR_INDEX = 1U << 5U;
static const uint32_t FAT_FEATURE_INCOMPAT_COMPRESSION = 1U << 0U;
static const uint32_t FAT_FEATURE_INCOMPAT_FILETYPE = 1U << 1U;
static const uint32_t FAT_FEATURE_INCOMPAT_RECOVER = 1U << 2U;
static const uint32_t FAT_FEATURE_INCOMPAT_JOURNAL_DEV = 1U << 3U;
static const uint32_t FAT_FEATURE_INCOMPAT_META_BG = 1U << 4U;
static const uint32_t FAT_FEATURE_RO_COMPAT_SPARSE_SUPER = 1U << 0U;
static const uint32_t FAT_FEATURE_RO_COMPAT_LARGE_FILE = 1U << 1U;
static const uint32_t FAT_FEATURE_RO_COMPAT_BTREE_DIR = 1U << 2U;
static const uint32_t FAT_LZV1_ALG = 1U << 0U;
static const uint32_t FAT_LZRW3A_ALG = 1U << 1U;
static const uint32_t FAT_GZIP_ALG = 1U << 2U;
static const uint32_t FAT_BZIP2_ALG = 1U << 3U;
static const uint32_t FAT_LZO_ALG = 1U << 4U;
static const uint16_t FAT_S_IFMT = 0xF000;
static const uint16_t FAT_S_IFSOCK = 0xC000;
static const uint16_t FAT_S_IFLNK = 0xA000;
static const uint16_t FAT_S_IFREG = 0x8000;
static const uint16_t FAT_S_IFBLK = 0x6000;
static const uint16_t FAT_S_IFDIR = 0x4000;
static const uint16_t FAT_S_IFCHR = 0x2000;
static const uint16_t FAT_S_IFIFO = 0x1000;
static const uint16_t FAT_S_ISUID = 0x0800;
static const uint16_t FAT_S_ISGID = 0x0400;
static const uint16_t FAT_S_ISVTX = 0x0200;
static const uint16_t FAT_S_IRUSR = 0x0100;
static const uint16_t FAT_S_IWUSR = 0x0080;
static const uint16_t FAT_S_IXUSR = 0x0040;
static const uint16_t FAT_S_IRGRP = 0x0020;
static const uint16_t FAT_S_IWGRP = 0x0010;
static const uint16_t FAT_S_IXGRP = 0x0008;
static const uint16_t FAT_S_IROTH = 0x0004;
static const uint16_t FAT_S_IWOTH = 0x0002;
static const uint16_t FAT_S_IXOTH = 0x0001;
#define FAT_S_ISSOCK(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFSOCK)
#define FAT_S_ISLNK(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFLNK)
#define FAT_S_ISREG(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFREG)
#define FAT_S_ISBLK(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFBLK)
#define FAT_S_ISDIR(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFDIR)
#define FAT_S_ISCHR(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFCHR)
#define FAT_S_ISFIFO(mode) (((mode) & FAT_S_IFMT) == FAT_S_IFIFO)
static const uint32_t FAT_SECRM_FL = 0x00000001U;
static const uint32_t FAT_UNRM_FL = 0x00000002U;
static const uint32_t FAT_COMPR_FL = 0x00000004U;
static const uint32_t FAT_SYNC_FL = 0x00000008U;
static const uint32_t FAT_IMMUTABLE_FL = 0x00000010U;
static const uint32_t FAT_APPEND_FL = 0x00000020U;
static const uint32_t FAT_NODUMP_FL = 0x00000040U;
static const uint32_t FAT_NOATIME_FL = 0x00000080U;
static const uint32_t FAT_DIRTY_FL = 0x00000100U;
static const uint32_t FAT_COMPRBLK_FL = 0x00000200U;
static const uint32_t FAT_NOCOMPR_FL = 0x00000400U;
static const uint32_t FAT_ECOMPR_FL = 0x00000800U;
static const uint32_t FAT_BTREE_FL = 0x00001000U;
static const uint32_t FAT_INDEX_FL = 0x00001000U;
static const uint32_t FAT_IMAGIC_FL = 0x00002000U;
static const uint32_t EXT3_JOURNAL_DATA_FL = 0x00004000U;
static const uint32_t FAT_RESERVED_FL = 0x80000000U;
static const uint32_t FAT_ROOT_INO = 2;
static const uint8_t FAT_FT_UNKNOWN = 0;
static const uint8_t FAT_FT_REG_FILE = 1;
static const uint8_t FAT_FT_DIR = 2;
static const uint8_t FAT_FT_CHRDEV = 3;
static const uint8_t FAT_FT_BLKDEV = 4;
static const uint8_t FAT_FT_FIFO = 5;
static const uint8_t FAT_FT_SOCK = 6;
static const uint8_t FAT_FT_SYMLINK = 7;
static inline uint8_t FAT_FT_OF_MODE(mode_t mode)
{
if ( FAT_S_ISREG(mode) )
return FAT_FT_REG_FILE;
if ( FAT_S_ISDIR(mode) )
return FAT_FT_DIR;
if ( FAT_S_ISCHR(mode) )
return FAT_FT_CHRDEV;
if ( FAT_S_ISBLK(mode) )
return FAT_FT_BLKDEV;
if ( FAT_S_ISFIFO(mode) )
return FAT_FT_FIFO;
if ( FAT_S_ISSOCK(mode) )
return FAT_FT_SOCK;
if ( FAT_S_ISLNK(mode) )
return FAT_FT_SYMLINK;
return FAT_FT_UNKNOWN;
}
#endif

View File

@ -1,128 +0,0 @@
/*
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ext-structs.h
* Data structures for the extended filesystem.
*/
#ifndef EXT_STRUCTS_H
#define EXT_STRUCTS_H
struct ext_superblock
{
uint32_t s_inodes_count;
uint32_t s_blocks_count;
uint32_t s_r_blocks_count;
uint32_t s_free_blocks_count;
uint32_t s_free_inodes_count;
uint32_t s_first_data_block;
uint32_t s_log_block_size;
int32_t s_log_frag_size;
uint32_t s_blocks_per_group;
uint32_t s_frags_per_group;
uint32_t s_inodes_per_group;
uint32_t s_mtime;
uint32_t s_wtime;
uint16_t s_mnt_count;
uint16_t s_max_mnt_count;
uint16_t s_magic;
uint16_t s_state;
uint16_t s_errors;
uint16_t s_minor_rev_level;
uint32_t s_lastcheck;
uint32_t s_checkinterval;
uint32_t s_creator_os;
uint32_t s_rev_level;
uint16_t s_def_resuid;
uint16_t s_def_resgid;
// FAT_DYNAMIC_REV
uint32_t s_first_ino;
uint16_t s_inode_size;
uint16_t s_block_group_nr;
uint32_t s_feature_compat;
uint32_t s_feature_incompat;
uint32_t s_feature_ro_compat;
uint8_t s_uuid[16];
/*uint8_t*/ char s_volume_name[16];
/*uint8_t*/ char s_last_mounted[64];
uint32_t s_algo_bitmap;
// Performance Hints
uint8_t s_prealloc_blocks;
uint8_t s_prealloc_dir_blocks;
uint16_t alignment0;
// Journaling Support
uint8_t s_journal_uuid[16];
uint32_t s_journal_inum;
uint32_t s_journal_dev;
uint32_t s_last_orphan;
// Directory Indexing Support
uint32_t s_hash_seed[4];
uint8_t s_def_hash_version;
uint8_t alignment1[3];
// Other options
uint32_t s_default_mount_options;
uint32_t s_first_meta_bg;
uint8_t alignment2[760];
};
struct ext_blockgrpdesc
{
uint32_t bg_block_bitmap;
uint32_t bg_inode_bitmap;
uint32_t bg_inode_table;
uint16_t bg_free_blocks_count;
uint16_t bg_free_inodes_count;
uint16_t bg_used_dirs_count;
uint16_t alignment0;
uint8_t alignment1[12];
};
struct ext_inode
{
uint16_t i_mode;
uint16_t i_uid;
uint32_t i_size;
uint32_t i_atime;
uint32_t i_ctime;
uint32_t i_mtime;
uint32_t i_dtime;
uint16_t i_gid;
uint16_t i_links_count;
uint32_t i_blocks;
uint32_t i_flags;
uint32_t i_osd1;
uint32_t i_block[15];
uint32_t i_generation;
uint32_t i_file_acl;
uint32_t i_dir_acl;
uint32_t i_faddr;
uint8_t i_frag;
uint8_t i_fsize;
uint16_t i_mode_high;
uint16_t i_uid_high;
uint16_t i_gid_high;
uint32_t i_osd2_alignment0;
};
struct ext_dirent
{
uint32_t inode;
uint16_t reclen;
uint8_t name_len;
uint8_t file_type;
char name[0];
};
#endif

View File

@ -1,5 +1,3 @@
/*
* Copyright (c) 2013, 2014, 2015, 2016, 2023 Jonas 'Sortie' Termansen.
*
@ -41,11 +39,6 @@
#include "fuse.h"
#endif
// TODO: Remove.
#include "ext-constants.h"
#include "ext-structs.h"
#include "blockgroup.h"
#include "block.h"
#include "device.h"
#include "fat.h"
@ -55,64 +48,9 @@
#include "ioleast.h"
#include "util.h"
// These must be kept up to date with libmount/fat.c.
static const uint32_t FAT_FEATURE_COMPAT_SUPPORTED = 0;
static const uint32_t FAT_FEATURE_INCOMPAT_SUPPORTED = \
FAT_FEATURE_INCOMPAT_FILETYPE;
static const uint32_t FAT_FEATURE_RO_COMPAT_SUPPORTED = \
FAT_FEATURE_RO_COMPAT_LARGE_FILE;
uid_t request_uid;
uid_t request_gid;
mode_t HostModeFromExtMode(uint32_t extmode)
{
mode_t hostmode = extmode & 0777;
if ( extmode & FAT_S_ISVTX ) hostmode |= S_ISVTX;
if ( extmode & FAT_S_ISGID ) hostmode |= S_ISGID;
if ( extmode & FAT_S_ISUID ) hostmode |= S_ISUID;
if ( FAT_S_ISSOCK(extmode) ) hostmode |= S_IFSOCK;
if ( FAT_S_ISLNK(extmode) ) hostmode |= S_IFLNK;
if ( FAT_S_ISREG(extmode) ) hostmode |= S_IFREG;
if ( FAT_S_ISBLK(extmode) ) hostmode |= S_IFBLK;
if ( FAT_S_ISDIR(extmode) ) hostmode |= S_IFDIR;
if ( FAT_S_ISCHR(extmode) ) hostmode |= S_IFCHR;
if ( FAT_S_ISFIFO(extmode) ) hostmode |= S_IFIFO;
return hostmode;
}
uint32_t ExtModeFromHostMode(mode_t hostmode)
{
uint32_t extmode = hostmode & 0777;
if ( hostmode & S_ISVTX ) extmode |= FAT_S_ISVTX;
if ( hostmode & S_ISGID ) extmode |= FAT_S_ISGID;
if ( hostmode & S_ISUID ) extmode |= FAT_S_ISUID;
if ( S_ISSOCK(hostmode) ) extmode |= FAT_S_IFSOCK;
if ( S_ISLNK(hostmode) ) extmode |= FAT_S_IFLNK;
if ( S_ISREG(hostmode) ) extmode |= FAT_S_IFREG;
if ( S_ISBLK(hostmode) ) extmode |= FAT_S_IFBLK;
if ( S_ISDIR(hostmode) ) extmode |= FAT_S_IFDIR;
if ( S_ISCHR(hostmode) ) extmode |= FAT_S_IFCHR;
if ( S_ISFIFO(hostmode) ) extmode |= FAT_S_IFIFO;
return extmode;
}
uint8_t HostDTFromExtDT(uint8_t extdt)
{
switch ( extdt )
{
case FAT_FT_UNKNOWN: return DT_UNKNOWN;
case FAT_FT_REG_FILE: return DT_REG;
case FAT_FT_DIR: return DT_DIR;
case FAT_FT_CHRDEV: return DT_CHR;
case FAT_FT_BLKDEV: return DT_BLK;
case FAT_FT_FIFO: return DT_FIFO;
case FAT_FT_SOCK: return DT_SOCK;
case FAT_FT_SYMLINK: return DT_LNK;
}
return DT_UNKNOWN;
}
// TODO: Encapsulate.
void StatInode(Inode* inode, struct stat* st)
{
@ -326,7 +264,8 @@ int main(int argc, char* argv[])
if ( !fs ) // TODO: Use operator new nothrow!
err(1, "malloc");
printf("So far so good, data_offset=%u, data_sectors=%u, cluster_count=%u, sectors_per_cluster=%u, fat_type=%i\n", data_offset, data_sectors, cluster_count, bpb.sectors_per_cluster, fat_type);
// TODO: Remove this debug stuff.
printf("Mounted FAT data_offset=%u, data_sectors=%u, cluster_count=%u, sectors_per_cluster=%u, fat_type=%i\n", data_offset, data_sectors, cluster_count, bpb.sectors_per_cluster, fat_type);
if ( !mount_path )
return 0;

View File

@ -22,20 +22,15 @@
#include <assert.h>
#include <endian.h>
#include <err.h> // TODO: Remove.
#include <errno.h>
#include <stddef.h>
#include <stdio.h> // TODO: Debug.
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "ext-constants.h"
#include "ext-structs.h"
#include "fat.h"
#include "block.h"
#include "blockgroup.h"
#include "device.h"
#include "filesystem.h"
#include "inode.h"
@ -140,14 +135,24 @@ uint16_t timespec_to_fat_date(struct timespec* ts)
return tm.tm_mday << 0 | (tm.tm_mon + 1) << 5 | (tm.tm_year - 80) << 9;
}
// TODO: Rename tenths to a better name.
void timespec_to_fat(const struct timespec* ts, uint16_t* date, uint16_t* time,
uint8_t* tenths)
{
struct tm tm;
gmtime_r(&ts->tv_sec, &tm);
// TODO: Endian.
*date = tm.tm_mday << 0 | (tm.tm_mon + 1) << 5 | (tm.tm_year - 80) << 9;
*time = (tm.tm_sec / 2) << 0 | tm.tm_min << 5 | tm.tm_hour << 11;
*tenths = ts->tv_nsec / 10000000 + (tm.tm_sec & 1 ? 100 : 0);
}
Filesystem::Filesystem(Device* device, const char* mount_path)
{
this->bpb_block = device->GetBlock(0);
assert(bpb_block); // TODO: This can fail.
this->bpb = (struct fat_bpb*) bpb_block->block_data;
this->sb = NULL; // TODO: Remove.
this->device = device;
this->block_groups = NULL; // TODO: Remove.
this->mount_path = mount_path;
this->mode_reg = S_IFREG | 0644;
this->mode_dir = S_IFDIR | 0755;
@ -181,8 +186,6 @@ Filesystem::Filesystem(Device* device, const char* mount_path)
fat_type == 12 ? 0xFFF : fat_type == 16 ? 0xFFFF : 0xFFFFFFF;
// TODO: Obtain and verify this from the fsinfo.
this->free_search = 0;
// TODO: Update to FAT:
//this->num_blocks = this->sb->s_blocks_count;
this->mru_inode = NULL;
this->lru_inode = NULL;
this->dirty_inode = NULL;
@ -238,30 +241,6 @@ void Filesystem::Sync()
device->Sync();
}
BlockGroup* Filesystem::GetBlockGroup(uint32_t group_id)
{
err(1, "deleteme: %s\n", __func__);
assert(group_id < num_groups);
if ( block_groups[group_id] )
return block_groups[group_id]->Refer(), block_groups[group_id];
size_t group_size = sizeof(ext_blockgrpdesc);
uint32_t first_block_id = sb->s_first_data_block + 1 /* superblock */;
uint32_t block_id = first_block_id + (group_id * group_size) / block_size;
uint32_t offset = (group_id * group_size) % block_size;
Block* block = device->GetBlock(block_id);
if ( !block )
return (BlockGroup*) NULL;
BlockGroup* group = new BlockGroup(this, group_id);
if ( !group ) // TODO: Use operator new nothrow!
return block->Unref(), (BlockGroup*) NULL;
group->data_block = block;
uint8_t* buf = group->data_block->block_data + offset;
group->data = (struct ext_blockgrpdesc*) buf;
return block_groups[group_id] = group;
}
Inode* Filesystem::GetInode(uint32_t inode_id, Block* dirent_block,
struct fat_dirent* dirent)
{
@ -329,7 +308,7 @@ void Filesystem::FreeCluster(uint32_t cluster)
if ( fat_type != 32 )
return;
Block* block = device->GetBlock(bpb->fat32_fsinfo);
if ( block )
if ( !block )
return;
struct fat_fsinfo* fsinfo = (struct fat_fsinfo*) block->block_data;
block->BeginWrite();
@ -346,86 +325,6 @@ void Filesystem::FreeCluster(uint32_t cluster)
block->Unref();
}
uint32_t Filesystem::AllocateBlock(BlockGroup* preferred)
{
err(1, "deleteme: %s\n", __func__);
if ( !device->write )
return errno = EROFS, 0;
if ( !sb->s_free_blocks_count )
return errno = ENOSPC, 0;
if ( preferred )
if ( uint32_t block_id = preferred->AllocateBlock() )
return block_id;
// TODO: This can be made faster by maintaining a linked list of block
// groups that definitely have free blocks.
for ( uint32_t group_id = 0; group_id < num_groups; group_id++ )
if ( uint32_t block_id = GetBlockGroup(group_id)->AllocateBlock() )
return block_id;
// TODO: This case should only be fit in the event of corruption. We should
// rebuild all these values upon filesystem mount instead so we know
// this can't happen. That also allows us to make the linked list
// requested above.
BeginWrite();
sb->s_free_blocks_count = 0;
FinishWrite();
return errno = ENOSPC, 0;
}
uint32_t Filesystem::AllocateInode(BlockGroup* preferred)
{
err(1, "deleteme: %s\n", __func__);
if ( !device->write )
return errno = EROFS, 0;
if ( !sb->s_free_inodes_count )
return errno = ENOSPC, 0;
if ( preferred )
if ( uint32_t inode_id = preferred->AllocateInode() )
return inode_id;
// TODO: This can be made faster by maintaining a linked list of block
// groups that definitely have free inodes.
for ( uint32_t group_id = 0; group_id < num_groups; group_id++ )
if ( uint32_t inode_id = GetBlockGroup(group_id)->AllocateInode() )
return inode_id;
// TODO: This case should only be fit in the event of corruption. We should
// rebuild all these values upon filesystem mount instead so we know
// this can't happen. That also allows us to make the linked list
// requested above.
BeginWrite();
sb->s_free_inodes_count = 0;
FinishWrite();
return errno = ENOSPC, 0;
}
void Filesystem::FreeBlock(uint32_t block_id)
{
err(1, "deleteme: %s\n", __func__);
assert(device->write);
assert(block_id);
assert(block_id < num_blocks);
uint32_t group_id = (block_id - sb->s_first_data_block) / sb->s_blocks_per_group;
assert(group_id < num_groups);
BlockGroup* group = GetBlockGroup(group_id);
if ( !group )
return;
group->FreeBlock(block_id);
group->Unref();
}
void Filesystem::FreeInode(uint32_t inode_id)
{
err(1, "deleteme: %s\n", __func__);
assert(device->write);
assert(inode_id);
assert(inode_id < num_inodes);
uint32_t group_id = (inode_id-1) / sb->s_inodes_per_group;
assert(group_id < num_groups);
BlockGroup* group = GetBlockGroup(group_id);
if ( !group )
return;
group->FreeInode(inode_id);
group->Unref();
}
uint32_t Filesystem::ReadFAT(uint32_t cluster)
{
// TODO: Bounds check.

View File

@ -23,11 +23,13 @@
bool is_8_3(const char* name);
void encode_8_3(const char* decoded, char encoded[8 + 3]);
void decode_8_3(const char encoded[8 + 3], char decoded[8 + 1 + 3 + 1]);
void timespec_to_fat(const struct timespec* ts, uint16_t* date, uint16_t* time,
uint8_t* tenths);
// TODO: Unify into the above.
uint8_t timespec_to_fat_tenths(struct timespec* ts);
uint16_t timespec_to_fat_time(struct timespec* ts);
uint16_t timespec_to_fat_date(struct timespec* ts);
class BlockGroup;
class Device;
class Inode;
@ -42,16 +44,13 @@ public:
public:
Block* bpb_block;
struct fat_bpb* bpb;
struct ext_superblock* sb; //TODO: Remove.
Device* device;
BlockGroup** block_groups;
const char* mount_path;
mode_t mode_reg;
mode_t mode_dir;
uid_t uid;
gid_t gid;
uint32_t block_size;
uint32_t inode_size; // TODO: Remove.
uint16_t bytes_per_sector;
uint16_t root_dirent_count;
uint32_t sectors_per_fat;
@ -66,9 +65,6 @@ public:
uint32_t eio_cluster;
uint32_t eof_cluster;
uint32_t free_search;
uint32_t num_blocks; // TODO: Remove, probably.
uint32_t num_groups; // TODO: Remove.
uint32_t num_inodes; // TODO: Remove, probably.
Inode* mru_inode;
Inode* lru_inode;
Inode* dirty_inode;
@ -76,15 +72,10 @@ public:
bool dirty;
public:
BlockGroup* GetBlockGroup(uint32_t group_id);
Inode* GetInode(uint32_t inode_id, Block* dirent_block = NULL,
struct fat_dirent* dirent = NULL);
uint32_t AllocateCluster();
void FreeCluster(uint32_t cluster);
uint32_t AllocateBlock(BlockGroup* preferred = NULL);
uint32_t AllocateInode(BlockGroup* preferred = NULL);
void FreeBlock(uint32_t block_id);
void FreeInode(uint32_t inode_id);
uint32_t ReadFAT(uint32_t cluster);
bool WriteFAT(uint32_t cluster, uint32_t value);
uint32_t CalculateFreeCount();

View File

@ -42,10 +42,6 @@
#include <fsmarshall.h>
#include "ext-constants.h"
#include "ext-structs.h" // TODO: Remove.
#include "blockgroup.h"
#include "block.h"
#include "device.h"
#include "fat.h"
@ -169,7 +165,6 @@ Inode* SafeGetInode(Filesystem* fs, ino_t ino)
{
if ( (uint32_t) ino != ino )
return errno = EBADF, (Inode*) NULL;
// TODO: Should check if the inode is not deleted.
return fs->GetInode((uint32_t) ino);
}
@ -178,7 +173,10 @@ void HandleRefer(int chl, struct fsm_req_refer* msg, Filesystem* fs)
(void) chl;
if ( Inode* inode = SafeGetInode(fs, (uint32_t) msg->ino) )
{
inode->RemoteRefer();
if ( inode->implied_reference )
inode->implied_reference--;
else
inode->RemoteRefer();
inode->Unref();
}
}
@ -195,9 +193,6 @@ void HandleUnref(int chl, struct fsm_req_unref* msg, Filesystem* fs)
void HandleSync(int chl, struct fsm_req_sync* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
Inode* inode = SafeGetInode(fs, msg->ino);
if ( !inode ) { RespondError(chl, errno); return; }
inode->Sync();
@ -217,59 +212,33 @@ void HandleStat(int chl, struct fsm_req_stat* msg, Filesystem* fs)
void HandleChangeMode(int chl, struct fsm_req_chmod* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
if ( !fs->device->write ) { RespondError(chl, EROFS); return; }
Inode* inode = SafeGetInode(fs, msg->ino);
if ( !inode ) { RespondError(chl, errno); return; }
uint32_t req_mode = ExtModeFromHostMode(msg->mode);
uint32_t old_mode = inode->Mode();
uint32_t new_mode = (old_mode & ~S_SETABLE) | (req_mode & S_SETABLE);
inode->SetMode(new_mode);
if ( !inode->ChangeMode(msg->mode) )
RespondError(chl, errno);
else
RespondSuccess(chl);
inode->Unref();
RespondSuccess(chl);
}
void HandleChangeOwner(int chl, struct fsm_req_chown* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
if ( !fs->device->write ) { RespondError(chl, EROFS); return; }
Inode* inode = SafeGetInode(fs, msg->ino);
if ( !inode ) { RespondError(chl, errno); return; }
if ( msg->uid != (uid_t) -1 )
inode->SetUserId((uint32_t) msg->uid);
if ( msg->gid != (gid_t) -1 )
inode->SetGroupId((uint32_t) msg->gid);
if ( !inode->ChangeOwner(msg->uid, msg->gid) )
RespondError(chl, errno);
else
RespondSuccess(chl);
inode->Unref();
RespondSuccess(chl);
}
void HandleUTimens(int chl, struct fsm_req_utimens* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
if ( !fs->device->write ) { RespondError(chl, EROFS); return; }
Inode* inode = SafeGetInode(fs, msg->ino);
if ( !inode ) { RespondError(chl, errno); return; }
if ( msg->times[0].tv_nsec != UTIME_OMIT ||
msg->times[1].tv_nsec != UTIME_OMIT )
{
time_t now = time(NULL);
inode->BeginWrite();
if ( msg->times[0].tv_nsec == UTIME_NOW )
inode->data->i_atime = now;
else if ( msg->times[0].tv_nsec != UTIME_OMIT )
inode->data->i_atime = msg->times[0].tv_sec;
if ( msg->times[1].tv_nsec == UTIME_NOW )
inode->data->i_mtime = now;
else if ( msg->times[1].tv_nsec != UTIME_OMIT )
inode->data->i_mtime = msg->times[1].tv_sec;
inode->FinishWrite();
}
inode->UTimens(msg->times);
inode->Unref();
RespondSuccess(chl);
}
@ -353,11 +322,11 @@ void HandleOpen(int chl, struct fsm_req_open* msg, Filesystem* fs)
if ( !result ) { RespondError(chl, errno); return; }
RespondOpen(chl, result->inode_id, result->Mode() & S_IFMT);
// TODO: This leaks a reference so the Inode keeps existing with meta data
// since unfortunately the automatic Refer() in the kernel is not implied.
// idk how to best solve that just yet, maybe add a count to the inode
// that causes that many Unrefs() to happen on the next HandleRefer().
//result->Unref();
// TODO: Unfortunately Open does not implicitly imply RemoteRefer so we need
// to try and pretend that it does so the inode isn't destroyed early.
result->implied_reference++;
result->RemoteRefer();
result->Unref();
}
void HandleMakeDir(int chl, struct fsm_req_mkdir* msg, Filesystem* fs)
@ -387,6 +356,7 @@ void HandleMakeDir(int chl, struct fsm_req_mkdir* msg, Filesystem* fs)
result->Unref();
}
// TODO: Encapsulate.
void HandleReadDir(int chl, struct fsm_req_readdirents* msg, Filesystem* fs)
{
Inode* inode = SafeGetInode(fs, msg->ino);
@ -483,9 +453,6 @@ void HandleIsATTY(int chl, struct fsm_req_isatty* msg, Filesystem* fs)
void HandleUnlink(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
Inode* inode = SafeGetInode(fs, msg->dirino);
if ( !inode ) { RespondError(chl, errno); return; }
@ -511,9 +478,6 @@ void HandleUnlink(int chl, struct fsm_req_unlink* msg, Filesystem* fs)
void HandleRemoveDir(int chl, struct fsm_req_rmdir* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
Inode* inode = SafeGetInode(fs, msg->dirino);
if ( !inode ) { RespondError(chl, errno); return; }
@ -539,9 +503,6 @@ void HandleRemoveDir(int chl, struct fsm_req_rmdir* msg, Filesystem* fs)
void HandleLink(int chl, struct fsm_req_link* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
Inode* inode = SafeGetInode(fs, msg->dirino);
if ( !inode ) { RespondError(chl, errno); return; }
Inode* dest = SafeGetInode(fs, msg->linkino);
@ -571,9 +532,6 @@ void HandleLink(int chl, struct fsm_req_link* msg, Filesystem* fs)
void HandleSymlink(int chl, struct fsm_req_symlink* msg, Filesystem* fs)
{
printf("ENOTSUP %s\n", __func__);
RespondError(chl, ENOTSUP); // TODO
return;
Inode* inode = SafeGetInode(fs, msg->dirino);
if ( !inode ) { RespondError(chl, errno); return; }
@ -620,8 +578,6 @@ void HandleReadlink(int chl, struct fsm_req_readlink* msg, Filesystem* fs)
void HandleRename(int chl, struct fsm_req_rename* msg, Filesystem* fs)
{
RespondError(chl, ENOTSUP); // TODO
return;
char* pathraw = (char*) &(msg[1]);
char* path = (char*) malloc(msg->oldnamelen+1 + msg->newnamelen+1);
if ( !path ) { RespondError(chl, errno); return; }
@ -679,29 +635,51 @@ void HandleTCGetBlob(int chl, struct fsm_req_tcgetblob* msg, Filesystem* fs)
memcpy(name, nameraw, msg->namelen);
name[msg->namelen] = '\0';
static const char index[] = "device-path\0filesystem-type\0filesystem-uuid\0mount-path\0";
static const char index[] =
"device-path\0filesystem-type\0filesystem-uuid\0mount-path\0"
"fat-size\0volume-id\0volume-label\0";
if ( !strcmp(name, "") )
RespondTCGetBlob(chl, index, sizeof(index) - 1);
else if ( !strcmp(name, "device-path") )
RespondTCGetBlob(chl, fs->device->path, strlen(fs->device->path));
else if ( !strcmp(name, "filesystem-type") )
RespondTCGetBlob(chl, "fat", strlen("fat"));
else if ( !strcmp(name, "fat-size") )
{
const char* str = fs->fat_type == 32 ? "32" :
fs->fat_type == 16 ? "16" : "12";
RespondTCGetBlob(chl, str, strlen(str));
}
else if ( !strcmp(name, "filesystem-uuid") )
{
unsigned char uuid[16];
if ( fs->fat_type == 32 )
{
memcpy(uuid, &fs->bpb->fat32_volume_id, 4);
memcpy(uuid + 4, &fs->bpb->fat32_volume_id, 11);
memcpy(uuid + 4, &fs->bpb->fat32_volume_label, 11);
}
else
{
memcpy(uuid, &fs->bpb->fat12_volume_id, 4);
memcpy(uuid + 4, &fs->bpb->fat12_volume_id, 11);
memcpy(uuid + 4, &fs->bpb->fat12_volume_label, 11);
}
uuid[15] = '\0';
RespondTCGetBlob(chl, uuid, sizeof(uuid));
}
else if ( !strcmp(name, "volume-id") )
{
if ( fs->fat_type == 32 )
RespondTCGetBlob(chl, &fs->bpb->fat32_volume_id, 4);
else
RespondTCGetBlob(chl, &fs->bpb->fat12_volume_id, 4);
}
else if ( !strcmp(name, "volume-label") )
{
if ( fs->fat_type == 32 )
RespondTCGetBlob(chl, &fs->bpb->fat32_volume_label, 11);
else
RespondTCGetBlob(chl, &fs->bpb->fat12_volume_label, 11);
}
else if ( !strcmp(name, "mount-path") )
RespondTCGetBlob(chl, fs->mount_path, strlen(fs->mount_path));
else
@ -714,14 +692,6 @@ void HandleIncomingMessage(int chl, struct fsm_msg_header* hdr, Filesystem* fs)
{
request_uid = hdr->uid;
request_gid = hdr->gid;
if ( (uint16_t) request_uid != request_uid ||
(uint16_t) request_gid != request_gid )
{
warn("id exceeded 16-bit: uid=%ju gid=%ju\n",
(uintmax_t) request_uid, (uintmax_t) request_gid);
RespondError(chl, EOVERFLOW);
return;
}
typedef void (*handler_t)(int, void*, Filesystem*);
handler_t handlers[FSM_MSG_NUM] = { NULL };
handlers[FSM_REQ_SYNC] = (handler_t) HandleSync;

File diff suppressed because it is too large Load Diff

View File

@ -37,29 +37,26 @@ public:
Inode* prev_dirty;
Inode* next_dirty;
Block* data_block;
struct fat_dirent* dirent; // TODO: Rename to data?
struct ext_inode* data; // TODO: Remove?
struct fat_dirent* dirent;
struct fat_dirent deleted_dirent;
uint32_t first_cluster;
Filesystem* filesystem;
size_t reference_count;
size_t remote_reference_count;
size_t implied_reference;
uint32_t inode_id;
bool dirty;
bool deleted;
public:
uint32_t Mode();
uint32_t UserId();
uint32_t GroupId();
uint64_t Size();
void SetMode(uint32_t mode);
void SetUserId(uint32_t user);
void SetGroupId(uint32_t group);
void SetSize(uint64_t new_size);
void UTimens(const struct timespec times[2]);
bool ChangeMode(mode_t mode);
bool ChangeOwner(uid_t uid, gid_t gid);
bool Truncate(uint64_t new_size);
bool FreeIndirect(uint64_t from, uint64_t offset, uint32_t block_id,
int indirection, uint64_t entry_span);
Block* GetBlock(uint64_t offset);
Block* GetBlockFromTable(Block* table, uint32_t index);
Block* GetClusterSector(uint32_t cluster, uint8_t sector);
bool Iterate(Block** block_ptr, uint32_t* cluster_ptr,
uint8_t* sector_ptr, uint16_t* offset);
@ -71,7 +68,6 @@ public:
Inode* UnlinkKeep(const char* elem, bool directories, bool force=false);
ssize_t ReadAt(uint8_t* buffer, size_t count, off_t offset);
ssize_t WriteAt(const uint8_t* buffer, size_t count, off_t offset);
bool UnembedInInode();
bool Rename(Inode* olddir, const char* oldname, const char* newname);
Inode* CreateDirectory(const char* path, mode_t mode);
bool RemoveDirectory(const char* path);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011-2018, 2021-2022 Jonas 'Sortie' Termansen.
* Copyright (c) 2011-2018, 2021-2023 Jonas 'Sortie' Termansen.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -233,6 +233,13 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
if ( !(kernel_options = strdup(cmdline ? cmdline : "")) )
Panic("Failed to allocate kernel command line");
#if defined(__i386__) || defined(__x86_64__)
// TODO: Detect EFI.
kernel_firmware = "bios";
#else
#warning "Name your system firmware here"
kernel_firmware = "unknown";
#endif
int argmax = 1;
argv = new char*[argmax + 1];
@ -288,6 +295,20 @@ extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo_p)
enable_network_drivers = true;
else if ( !strcmp(arg, "--no-random-seed") )
no_random_seed = true;
else if ( !strncmp(arg, "--firmware=", strlen("--firmware=")) )
{
const char* firmware = arg + strlen("--firmware=");
#if defined(__i386__) || defined(__x86_64__)
if ( !strcmp(firmware, "bios") || !strcmp(firmware, "pc") )
kernel_firmware = "bios";
else if ( !strcmp(firmware, "efi") )
kernel_firmware = "efi";
else
#endif
{
PanicF("Unsupported firmware option: %s", firmware);
}
}
else
{
Log::PrintF("\r\e[J");

View File

@ -34,20 +34,17 @@
namespace Sortix {
char* kernel_options;
const char* kernel_firmware;
static const char* KernelInfo(const char* req)
{
if ( strcmp(req, "name") == 0 ) { return BRAND_KERNEL_NAME; }
if ( strcmp(req, "version") == 0 ) { return VERSIONSTR; }
if ( strcmp(req, "tagline") == 0 ) { return BRAND_RELEASE_TAGLINE; }
if ( strcmp(req, "options") == 0 ) { return kernel_options; }
if ( strcmp(req, "builddate") == 0 ) { return __DATE__; }
if ( strcmp(req, "buildtime") == 0 ) { return __TIME__; }
#if defined(__i386__) || defined(__x86_64__)
if ( strcmp(req, "firmware") == 0 ) { return "bios"; }
#else
#warning "Name your system firmware here"
#endif
if ( strcmp(req, "name") == 0 ) return BRAND_KERNEL_NAME;
if ( strcmp(req, "version") == 0 ) return VERSIONSTR;
if ( strcmp(req, "tagline") == 0 ) return BRAND_RELEASE_TAGLINE;
if ( strcmp(req, "options") == 0 ) return kernel_options;
if ( strcmp(req, "builddate") == 0 ) return __DATE__;
if ( strcmp(req, "buildtime") == 0 ) return __TIME__;
if ( strcmp(req, "firmware") == 0 ) return kernel_firmware;
return NULL;
}

View File

@ -23,6 +23,7 @@
namespace Sortix {
extern char* kernel_options;
extern const char* kernel_firmware;
} // namespace Sortix

View File

@ -82,6 +82,33 @@ diff -Paur --no-dereference -- mtools.upstream/mcopy.c mtools/mcopy.c
}
return;
}
diff -Paur --no-dereference -- mtools.upstream/plain_io.c mtools/plain_io.c
--- mtools.upstream/plain_io.c
+++ mtools/plain_io.c
@@ -145,7 +145,10 @@
static int init_geom_with_reg(int fd, struct device *dev,
struct device *orig_dev,
struct MT_STAT *statbuf) {
+ // TODO: Actually use the geometry but the partition has to report it.
+#ifndef __sortix__
if(S_ISREG(statbuf->st_mode)) {
+#endif
/* Regular file (image file) */
mt_off_t sectors;
if(statbuf->st_size == 0) {
@@ -161,10 +164,12 @@
? UINT32_MAX
: (uint32_t) sectors;
return 0;
+#ifndef __sortix__
} else {
/* All the rest (devices, etc.) */
return init_geom(fd, dev, orig_dev, statbuf);
}
+#endif
}
static int file_geom(Stream_t *Stream, struct device *dev,
diff -Paur --no-dereference -- mtools.upstream/sysincludes.h mtools/sysincludes.h
--- mtools.upstream/sysincludes.h
+++ mtools/sysincludes.h

View File

@ -10,6 +10,7 @@
.Op Fl \-enable-em
.Op Fl \-disable-network-drivers
.Op Fl \-enable-network-drivers
.Op Fl \-firmware Ns = Ns Oo Sy bios "|" Sy efi "|" pc Oc
.Op Fl \-no-random-seed
.Op Fl \-
.Op Ar init ...
@ -64,6 +65,14 @@ driver.
.It Fl \-enable-network-drivers
Do initialize network drivers.
This is the default behavior.
.It Fl \-firmware Ns = Ns Oo Sy bios "|" Sy efi "|" pc Oc
Informs the kernel the system is booted using
.Sy bios or
.Sy efi .
The
.Sy pc
value is a synonym for
.Sy bios .
.It Fl \-no-random-seed
Don't warn if no random seed file was loaded by the bootloader (usually from
.Pa /boot/random.seed ) .

View File

@ -312,7 +312,7 @@ int main(int argc, char* argv[])
fetch_argv[0] = (char*) "tix-fetch";
fetch_argv[1] = (char*) "--collection";
fetch_argv[2] = params.collection;
fetch_argv[3] = (char*) "--port";
fetch_argv[3] = (char*) "--package";
fetch_argv[4] = (char*) "--";
int offset = 5;
for ( int i = 0; i < argc-2; i++ )

View File

@ -30,7 +30,7 @@ The date on which the current kernel was built.
.It Sy buildtime
The time at which the current kernel was built.
.It Sy firmware
The firmware of the system (e.g. "bios" or "uefi")
The firmware of the system (e.g. "bios" or "efi")
.El
.Sh EXIT STATUS
.Nm