chore: sync repo

This commit is contained in:
d0p1 🏳️‍⚧️ 2024-07-21 09:32:17 +00:00
parent 8781f567e6
commit 63c4d1bbc2
13 changed files with 4261 additions and 123 deletions

4
compile_flags.txt Normal file
View file

@ -0,0 +1,4 @@
-I.
-I/usr/include/fuse3
-Ilib
-DHAVE_CONFIG_H

1807
config.guess vendored Executable file

File diff suppressed because it is too large Load diff

1960
config.sub vendored Executable file

File diff suppressed because it is too large Load diff

BIN
hdd Normal file

Binary file not shown.

142
include/stupidfs.h Normal file
View file

@ -0,0 +1,142 @@
/**
* \file stupidfs.h
*
* StupidFS
* ```
*
* Boot blockSuper blockInodes...InodesData...Data
*
* ```
*/
#ifndef STPDFS_H
# define STPDFS_H 1
# include <stdint.h>
# include <stddef.h>
# define STPDFS_SB_MAGIC 0x44505453
# define STPDFS_SB_REV STPDFS_SB_REV_1
# define STPDFS_SB_REV_1 1
# define STPDFS_INO_ROOTDIR 1
# define STPDFS_BLOCK_SIZE_BITS 9
# define STPDFS_BLOCK_SIZE (1 << STPDFS_BLOCK_SIZE_BITS)
# define STPDFS_NAME_MAX 28
# define STPDFS_INODES_PER_BLOCK (STPDFS_BLOCK_SIZE / (sizeof(struct stpdfs_inode)))
# define STPDFS_ZONES_PER_BLOCK (STPDFS_BLOCK_SIZE / sizeof(uint32_t))
# define STPDFS_DIRENT_PER_BLOCK (STPDFS_BLOCK_SIZE / (sizeof(struct stpdfs_dirent)))
# define STPDFS_NDIR 7
# define STPDFS_ROOT_INO 1
# define STPDFS_INO_FLAG_ALOC (1 << 15)
# define STPDFS_INO_FLAG_LZP (1 << 1)
# define STPDFS_INO_FLAG_ENC (1 << 2)
# define STPDFS_S_IFMT 0xF000
# define STPDFS_S_IFSOCK 0xA000
# define STPDFS_S_IFLNK 0xC000
# define STPDFS_S_IFREG 0x8000
# define STPDFS_S_IFBLK 0x6000
# define STPDFS_S_IFDIR 0x4000
# define STPDFS_S_ISUID 0x0800
# define STPDFS_S_ISGID 0x0400
# define STPDFS_S_ISVTX 0x0200
# define STPDFS_S_IRWXU 0x01C0
# define STPDFS_S_IRUSR 0x0100
# define STPDFS_S_IWUSR 0x0080
# define STPDFS_S_IXUSR 0x0040
# define STPDFS_S_IRWXG 0x0038
# define STPDFS_S_IRGRP 0x0020
# define STPDFS_S_IWGRP 0x0010
# define STPDFS_S_IXGRP 0x0008
# define STPDFS_S_IRWXO 0x0007
# define STPDFS_S_IROTH 0x0004
# define STPDFS_S_IWOTH 0x0002
# define STPDFS_S_IXOTH 0x0001
typedef uint32_t stpd_zone_t; /**< zone number */
typedef uint32_t stpd_block_t; /**< block number */
typedef uint32_t stpd_ino_t; /**< i-node number */
/**
* \brief free block list
* ```
*
* block 99
*
* block 98
*
* ...
*
* block 2
*
* block 1
*
* block 0 block 99
*
* ...
*
* block 0 block 99
*
* ...
*
* block 0
*
* ```
*/
struct stpdfs_free {
stpd_block_t free[100];
uint8_t nfree;
} __attribute__((packed));
enum stpdfs_state {
STPDFS_CLEANLY_UNMOUNTED = 0,
STPDFS_ERROR = 1,
STPDFS_DIRTY = 1,
};
/**
* \brief StupidFS Superblock
*/
struct stpdfs_sb {
uint32_t magic; /**< MUST be \ref STPDFS_SB_MAGIC */
uint32_t isize; /**< size in block of the I list */
uint32_t fsize; /**< size in block of the entire volume */
struct stpdfs_free freelist; /**< \see stpdfs_free */
uint8_t revision; /**< MUST be \ref STPDFS_SB_REV */
uint16_t state; /**< \see stpdfs_state */
uint64_t time; /**< last time the superblock was modified */
} __attribute__((packed));
#define STPDFS_SB_SIZE sizeof(struct stpdfs_sb)
/**
* \brief StupidFS I-node
*/
struct stpdfs_inode {
uint16_t mode; /**< file mode */
uint16_t nlink; /**< link count */
uint16_t uid; /**< owner user id */
uint16_t gid; /**< group id */
uint16_t flags;
uint32_t size;
stpd_zone_t zones[10];
uint64_t actime;
uint64_t modtime;
} __attribute__((packed));
#define STPDFS_INODE_SIZE sizeof(struct inode)
struct stpdfs_dirent {
stpd_ino_t inode;
char filename[STPDFS_NAME_MAX];
};
#define STPDFS_DIRENT_SIZE sizeof(struct stpdfs_dirent)
#endif /* !STPDFS_H */

View file

@ -1,7 +1,8 @@
noinst_LIBRARIES = libstpdfs.a
libstpdfs_a_SOURCES = block.c \
inode.c \
dir.c
dir.c \
data.c \
superblock.c \
compression/lzp.c \
crypto/hchacha.c \

View file

@ -42,13 +42,13 @@ stpdfs_alloc_block(int fd, struct stpdfs_sb *sb)
sb->state = STPDFS_DIRTY; /* mark state dirty */
redo:
sb->nfree--;
blocknum = sb->free[sb->nfree];
if (sb->nfree == 0 && blocknum != 0)
sb->freelist.nfree--;
blocknum = sb->freelist.free[sb->freelist.nfree];
if (sb->freelist.nfree == 0 && blocknum != 0)
{
stpdfs_read(fd, blocknum, &freelist, sizeof(struct stpdfs_free));
memcpy(sb->free, &freelist, sizeof(uint32_t) * 100);
sb->nfree = freelist.nfree;
memcpy(sb->freelist.free, &freelist, sizeof(uint32_t) * 100);
sb->freelist.nfree = freelist.nfree;
goto redo;
}
@ -69,19 +69,19 @@ stpdfs_free_block(int fd, struct stpdfs_sb *sb, uint32_t blocknum)
sb->state = STPDFS_DIRTY; /* mark state dirty */
if (sb->nfree == 100)
if (sb->freelist.nfree == 100)
{
memcpy(&copy, sb->free, sizeof(uint32_t) * 100);
copy.nfree = sb->nfree;
memcpy(&copy, sb->freelist.free, sizeof(uint32_t) * 100);
copy.nfree = sb->freelist.nfree;
stpdfs_write(fd, blocknum, &copy, sizeof(struct stpdfs_free));
sb->nfree = 1;
sb->free[0] = blocknum;
sb->freelist.nfree = 1;
sb->freelist.free[0] = blocknum;
}
else
{
sb->free[sb->nfree++] = blocknum;
sb->freelist.free[sb->freelist.nfree++] = blocknum;
}
sb->time = time(NULL);

View file

@ -1,82 +1,180 @@
#include "stpdfs.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static void
write_indirect(int fd, struct stpdfs_sb *sb, struct stpdfs_inode *inode, size_t zone, uint8_t *buffer, size_t size)
static int
stpdfs_write_indirect(int fd, uint32_t blocknum, uint8_t *buffer, size_t size)
{
size_t i;
uint32_t zones[STPDFS_ZONES_PER_BLOCK];
size_t byte_read;
}
stpdfs_read(fd, blocknum, zones, sizeof(zones));
static void
write_zone(int fd, struct stpdfs_sb *sb, struct stpdfs_inode *inode, size_t zone, uint8_t *buffer, size_t size)
{
uint32_t zones[128];
if (zone < 7)
byte_read = 0;
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
if (inode->zones[zone] == 0)
{
inode->zones[zone] = stpdfs_alloc_block(fd, sb);
}
stpdfs_write(fd, inode->zones[zone], buffer, size);
stpdfs_read(fd, zones[i], buffer, STPDFS_BLOCK_SIZE);
byte_read += STPDFS_BLOCK_SIZE;
return;
}
if (zone < 135)
{
if (inode->zones[7] == 0)
if (byte_read >= size)
{
inode->zones[7] = stpdfs_alloc_block(fd, sb);
memset(zones, 0, 512);
stpdfs_write(fd, inode->zones[7], zones, 512);
return (byte_read);
}
stpdfs_read(fd, inode->zones[7], zones, 512);
if (zones[zone - 7] == 0)
{
zones[zone - 7] = stpdfs_alloc_block(fd, sb);
stpdfs_write(fd, inode->zones[7], zones, 512);
}
stpdfs_write(fd, zones[zone - 7], buffer, size);
return;
}
if (zone < 16519)
{
if (inode->zones[8] == 0)
{
inode->zones[8] = stpdfs_alloc_block(fd, sb);
memset(zones, 0, 512);
stpdfs_write(fd, inode->zones[7], zones, 512);
}
stpdfs_read(fd, inode->zones[8], zones, 512);
if (zones[(zone - 135) / 128] == 0)
{
zones[(zone - 135) / 128] = stpdfs_alloc_block(fd, sb);
}
}
return (byte_read);
}
int
stpdfs_write_data(int fd, struct stpdfs_sb *sb, struct stpdfs_inode *inode, uint8_t *buffer, size_t size)
stpdfs_write_data(int fd, struct stpdfs_sb *sb, struct stpdfs_inode *inode, uint8_t *data)
{
size_t idx;
uint32_t zonenum;
size_t max_zone;
size_t i;
size_t j;
size_t byte_write;
uint32_t zones1[STPDFS_ZONES_PER_BLOCK];
uint32_t zones2[STPDFS_ZONES_PER_BLOCK];
for (idx = 0; idx < size; idx += STPDFS_BLOCK_SIZE)
byte_write = 0;
for (i = 0; i < 7; i++)
{
max_zone = idx / STPDFS_BLOCK_SIZE;
for (zonenum = 0; zonenum < max_zone; zonenum++)
if (inode->zones[i] == 0)
{
write_zone(fd, sb, inode, zonenum, buffer + idx, ((idx + 1) * 512) > size ? size % 512 : 512);
inode->zones[i] = stpdfs_alloc_block(fd, sb);
}
stpdfs_write(fd, inode->zones[i], data + byte_write, (inode->size - byte_write) >= STPDFS_BLOCK_SIZE ? STPDFS_BLOCK_SIZE : (inode->size - byte_write));
byte_write += STPDFS_BLOCK_SIZE;
if (byte_write >= inode->size)
{
return (byte_write);
}
}
return (0)
/*
byte_read += stpdfs_write_indirect(fd, inode->zones[7], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
stpdfs_read(fd, inode->zones[8], zones1, sizeof(zones1));
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
byte_read += stpdfs_read_indirect(fd, zones1[i], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
}
stpdfs_read(fd, inode->zones[9], zones1, sizeof(zones1));
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
stpdfs_read(fd, zones1[i], zones2, sizeof(zones2));
for (j = 0; j < STPDFS_ZONES_PER_BLOCK; j++)
{
byte_read += stpdfs_read_indirect(fd, zones2[i], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
}
}*/
return (byte_write);
}
static int
stpdfs_read_indirect(int fd, uint32_t blocknum, uint8_t *buffer, size_t size)
{
size_t i;
uint32_t zones[STPDFS_ZONES_PER_BLOCK];
size_t byte_read;
stpdfs_read(fd, blocknum, zones, sizeof(zones));
byte_read = 0;
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
stpdfs_read(fd, zones[i], buffer, STPDFS_BLOCK_SIZE);
byte_read += STPDFS_BLOCK_SIZE;
if (byte_read >= size)
{
return (byte_read);
}
}
return (byte_read);
}
int
stpdfs_read_data(int fd, struct stpdfs_sb *sb, struct stpdfs_inode *inode, uint8_t **buffer)
{
size_t i;
size_t j;
size_t byte_read;
uint32_t zones1[STPDFS_ZONES_PER_BLOCK];
uint32_t zones2[STPDFS_ZONES_PER_BLOCK];
*buffer = (uint8_t *)malloc(inode->size + STPDFS_BLOCK_SIZE);
byte_read = 0;
for (i = 0; i < 7; i++)
{
stpdfs_read(fd, inode->zones[i], *buffer, STPDFS_BLOCK_SIZE);
byte_read += STPDFS_BLOCK_SIZE;
if (byte_read >= inode->size)
{
return (byte_read);
}
}
byte_read += stpdfs_read_indirect(fd, inode->zones[7], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
stpdfs_read(fd, inode->zones[8], zones1, sizeof(zones1));
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
byte_read += stpdfs_read_indirect(fd, zones1[i], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
}
stpdfs_read(fd, inode->zones[9], zones1, sizeof(zones1));
for (i = 0; i < STPDFS_ZONES_PER_BLOCK; i++)
{
stpdfs_read(fd, zones1[i], zones2, sizeof(zones2));
for (j = 0; j < STPDFS_ZONES_PER_BLOCK; j++)
{
byte_read += stpdfs_read_indirect(fd, zones2[i], *buffer + byte_read, inode->size - byte_read);
if (byte_read >= inode->size)
{
return (byte_read);
}
}
}
return (byte_read);
}

View file

@ -4,60 +4,15 @@
#include <stdlib.h>
int
stpdfs_dir_add_entry(int fd, uint8_t inonum, const char *name, uint32_t target)
stpdfs_dir_add_entry(int fd, struct stpdfs_sb *sb, uint32_t inonum, const char *name, uint32_t target)
{
struct stpdfs_inode inode;
struct stpdfs_dirent dirent[STPDFS_DIRENT_PER_BLOCK];
struct stpdfs_sb sb;
size_t max_zone;
size_t zone;
uint32_t blocknum;
stpdfs_read_superblock(fd, &sb);
stpdfs_read_inode(fd, inonum, &inode);
if (!(inode.mode & STPDFS_S_IFDIR))
{
return (-1);
}
max_zone = (inode.size + sizeof(struct stpdfs_dirent)) / STPDFS_DIRENT_PER_BLOCK;
zone = max_zone;
if (max_zone > 2113671)
{
}
if (max_zone > 16519)
{
}
else if (max_zone > 135)
{
}
else if (max_zone > 7)
{
}
else
{
if (inode.zones[max_zone] == 0)
{
inode.zones[max_zone] = stpdfs_alloc_block(fd, &sb);
}
blocknum = inode.zones[max_zone];
}
stpdfs_read(fd, blocknum, &dirent, sizeof(struct stpdfs_dirent) * STPDFS_DIRENT_PER_BLOCK);
dirent[inode.size % STPDFS_DIRENT_PER_BLOCK].inode = target;
memcpy(dirent[inode.size % STPDFS_DIRENT_PER_BLOCK].filename, name, STPDFS_NAME_MAX);
stpdfs_write(fd, blocknum, &dirent, sizeof(struct stpdfs_dirent) * STPDFS_DIRENT_PER_BLOCK);
inode.size += sizeof(struct stpdfs_dirent);
stpdfs_write_inode(fd, inonum, &inode);
stpdfs_write(fd, 1, &sb, sizeof(struct stpdfs_sb));
return (0);
}

View file

@ -8,7 +8,6 @@
*
* ```
*/
#include <cstdint>
#ifndef STPDFS_H
# define STPDFS_H 1
@ -27,8 +26,9 @@
# define STPDFS_NAME_MAX 28
# define STPDFS_INODES_PER_BLOCK (STPDFS_BLOCK_SIZE / (sizeof(struct stpdfs_inode)))
# define STPDFS_ZONES_PER_BLOCK (STPDFS_BLOCK_SIZE / sizeof(uint32_t))
# define STPDFS_DIRENT_PER_BLOCK (STPDFS_BLOCK_SIZE / (sizeof(struct stpdfs_dirent)))
# define STPDFS_NDIR 7
# define STPDFS_ROOT_INO 1
# define STPDFS_INO_FLAG_ALOC (1 << 15)
@ -43,9 +43,27 @@
# define STPDFS_S_IFBLK 0x6000
# define STPDFS_S_IFDIR 0x4000
# define STPDFS_S_ISUID 0x0800
# define STPDFS_S_ISGID 0x0400
# define STPDFS_S_ISVTX 0x0200
# define STPDFS_S_IRWXU 0x01C0
# define STPDFS_S_IRUSR 0x0100
# define STPDFS_S_IWUSR 0x0080
# define STPDFS_S_IXUSR 0x0040
# define STPDFS_S_IRWXG 0x0038
# define STPDFS_S_IRGRP 0x0020
# define STPDFS_S_IWGRP 0x0010
# define STPDFS_S_IXGRP 0x0008
# define STPDFS_S_IRWXO 0x0007
# define STPDFS_S_IROTH 0x0004
# define STPDFS_S_IWOTH 0x0002
# define STPDFS_S_IXOTH 0x0001
typedef uint32_t zone_t; /**< zone number */
typedef uint32_t block_t; /**< block number */
typedef uint32_t ino_t;
/**
* \brief free block list
@ -117,7 +135,7 @@ struct stpdfs_inode {
#define STPDFS_INODE_SIZE sizeof(struct inode)
struct stpdfs_dirent {
ino_t inode;
uint32_t inode;
char filename[STPDFS_NAME_MAX];
};

153
test-driver Executable file
View file

@ -0,0 +1,153 @@
#! /bin/sh
# test-driver - basic testsuite driver script.
scriptversion=2018-03-07.03; # UTC
# Copyright (C) 2011-2021 Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
usage_error ()
{
echo "$0: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
test-driver --test-name NAME --log-file PATH --trs-file PATH
[--expect-failure {yes|no}] [--color-tests {yes|no}]
[--enable-hard-errors {yes|no}] [--]
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
See the GNU Automake documentation for information.
END
}
test_name= # Used for reporting.
log_file= # Where to save the output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=no
color_tests=no
enable_hard_errors=yes
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "test-driver $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) enable_hard_errors=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
*) break;;
esac
shift
done
missing_opts=
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
if test x"$missing_opts" != x; then
usage_error "the following mandatory options are missing:$missing_opts"
fi
if test $# -eq 0; then
usage_error "missing argument"
fi
if test $color_tests = yes; then
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
red='' # Red.
grn='' # Green.
lgn='' # Light green.
blu='' # Blue.
mgn='' # Magenta.
std='' # No color.
else
red= grn= lgn= blu= mgn= std=
fi
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
trap "st=129; $do_exit" 1
trap "st=130; $do_exit" 2
trap "st=141; $do_exit" 13
trap "st=143; $do_exit" 15
# Test script is run here. We create the file first, then append to it,
# to ameliorate tests themselves also writing to the log file. Our tests
# don't, but others can (automake bug#35762).
: >"$log_file"
"$@" >>"$log_file" 2>&1
estatus=$?
if test $enable_hard_errors = no && test $estatus -eq 99; then
tweaked_estatus=1
else
tweaked_estatus=$estatus
fi
case $tweaked_estatus:$expect_failure in
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
0:*) col=$grn res=PASS recheck=no gcopy=no;;
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
esac
# Report the test outcome and exit status in the logs, so that one can
# know whether the test passed or failed simply by looking at the '.log'
# file, without the need of also peaking into the corresponding '.trs'
# file (automake bug#11814).
echo "$res $test_name (exit status: $estatus)" >>"$log_file"
# Report outcome to console.
echo "${col}${res}${std}: $test_name"
# Register the test result, and other relevant metadata.
echo ":test-result: $res" > $trs_file
echo ":global-test-result: $res" >> $trs_file
echo ":recheck: $recheck" >> $trs_file
echo ":copy-in-global-log: $gcopy" >> $trs_file
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View file

@ -124,7 +124,7 @@ mkfs()
super.revision = STPDFS_SB_REV;
super.isize = inodes / STPDFS_INODES_PER_BLOCK;
super.fsize = blocks;
super.nfree = 0;
super.freelist.nfree = 0;
/* write inodes */
lseek(fd, 2 * STPDFS_BLOCK_SIZE, SEEK_SET);
@ -150,7 +150,7 @@ mkfs()
inds[STPDFS_INO_ROOTDIR].actime = time(NULL);
inds[STPDFS_INO_ROOTDIR].size = sizeof(struct stpdfs_dirent) * 2;
inds[STPDFS_INO_ROOTDIR].flags = STPDFS_INO_FLAG_ALOC;
inds[STPDFS_INO_ROOTDIR].mode = STPDFS_S_IFDIR;
inds[STPDFS_INO_ROOTDIR].mode = STPDFS_S_IFDIR | STPDFS_S_IRUSR | STPDFS_S_IWUSR | STPDFS_S_IXUSR | STPDFS_S_IRGRP | STPDFS_S_IXGRP | STPDFS_S_IXOTH;
inds[STPDFS_INO_ROOTDIR].zones[0] = stpdfs_alloc_block(fd, &super);
inds[STPDFS_INO_ROOTDIR].size = sizeof(struct stpdfs_dirent) * 2;
stpdfs_read(fd, inds[STPDFS_INO_ROOTDIR].zones[0], rootdirent, sizeof(struct stpdfs_dirent) * 2);

BIN
tools/tools.stpd Executable file

Binary file not shown.