mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:48:10 +00:00
Finally hook up the mkdir code to a syscall.
Added a /bin/mkdir that makes directories. How very neat :^) There are various limitations because of missing functionality.
This commit is contained in:
parent
303577df16
commit
de4604ac95
26 changed files with 238 additions and 132 deletions
|
@ -30,15 +30,32 @@ bool FileSystemPath::canonicalize(bool resolveSymbolicLinks)
|
||||||
canonicalParts.append(part);
|
canonicalParts.append(part);
|
||||||
}
|
}
|
||||||
if (canonicalParts.isEmpty()) {
|
if (canonicalParts.isEmpty()) {
|
||||||
m_string = "/";
|
m_string = m_basename = m_dirname = "/";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
StringBuilder builder;
|
|
||||||
for (auto& cpart : canonicalParts) {
|
m_basename = canonicalParts.last();
|
||||||
builder.append('/');
|
|
||||||
builder.append(move(cpart));
|
if (canonicalParts.size() == 1) {
|
||||||
|
m_dirname = "/";
|
||||||
|
} else {
|
||||||
|
StringBuilder builder;
|
||||||
|
for (size_t i = 0; i < canonicalParts.size() - 1; ++i) {
|
||||||
|
auto& cpart = canonicalParts[i];
|
||||||
|
builder.append('/');
|
||||||
|
builder.append(cpart);
|
||||||
|
}
|
||||||
|
m_dirname = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
StringBuilder builder;
|
||||||
|
for (auto& cpart : canonicalParts) {
|
||||||
|
builder.append('/');
|
||||||
|
builder.append(move(cpart));
|
||||||
|
}
|
||||||
|
m_string = builder.build();
|
||||||
}
|
}
|
||||||
m_string = builder.build();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,15 @@ public:
|
||||||
bool isValid() const { return m_isValid; }
|
bool isValid() const { return m_isValid; }
|
||||||
String string() const { return m_string; }
|
String string() const { return m_string; }
|
||||||
|
|
||||||
|
String basename() const { return m_basename; }
|
||||||
|
String dirname() const { return m_dirname; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool canonicalize(bool resolveSymbolicLinks = false);
|
bool canonicalize(bool resolveSymbolicLinks = false);
|
||||||
|
|
||||||
String m_string;
|
String m_string;
|
||||||
|
String m_dirname;
|
||||||
|
String m_basename;
|
||||||
bool m_isValid { false };
|
bool m_isValid { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,11 @@ void StringBuilder::append(String&& str)
|
||||||
m_strings.append(move(str));
|
m_strings.append(move(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StringBuilder::append(const String& str)
|
||||||
|
{
|
||||||
|
m_strings.append(str);
|
||||||
|
}
|
||||||
|
|
||||||
void StringBuilder::append(char ch)
|
void StringBuilder::append(char ch)
|
||||||
{
|
{
|
||||||
m_strings.append(StringImpl::create(&ch, 1));
|
m_strings.append(StringImpl::create(&ch, 1));
|
||||||
|
|
|
@ -10,6 +10,7 @@ public:
|
||||||
StringBuilder() { }
|
StringBuilder() { }
|
||||||
~StringBuilder() { }
|
~StringBuilder() { }
|
||||||
|
|
||||||
|
void append(const String&);
|
||||||
void append(String&&);
|
void append(String&&);
|
||||||
void append(char);
|
void append(char);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
enum IDECommand : byte {
|
enum IDECommand : byte {
|
||||||
IDENTIFY_DRIVE = 0xEC,
|
IDENTIFY_DRIVE = 0xEC,
|
||||||
READ_SECTORS = 0x21,
|
READ_SECTORS = 0x21,
|
||||||
|
WRITE_SECTORS = 0x30,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IDEStatus : byte {
|
enum IDEStatus : byte {
|
||||||
|
@ -64,11 +65,8 @@ bool IDEDiskDevice::readBlock(unsigned index, byte* out) const
|
||||||
|
|
||||||
bool IDEDiskDevice::writeBlock(unsigned index, const byte* data)
|
bool IDEDiskDevice::writeBlock(unsigned index, const byte* data)
|
||||||
{
|
{
|
||||||
(void) index;
|
write_sectors(index, 1, data);
|
||||||
(void) data;
|
return true;
|
||||||
kprintf("IDEDiskDevice: writeBlock not implemented()\n");
|
|
||||||
notImplemented();
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DISK_DEBUG
|
#ifdef DISK_DEBUG
|
||||||
|
@ -221,3 +219,48 @@ bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IDEDiskDevice::write_sectors(dword start_sector, word count, const byte* data)
|
||||||
|
{
|
||||||
|
LOCKER(m_lock);
|
||||||
|
dbgprintf("%s(%u): IDEDiskDevice::write_sectors request (%u sector(s) @ %u)\n",
|
||||||
|
current->name().characters(),
|
||||||
|
current->pid(),
|
||||||
|
count,
|
||||||
|
start_sector);
|
||||||
|
disableIRQ();
|
||||||
|
|
||||||
|
auto chs = lba_to_chs(start_sector);
|
||||||
|
|
||||||
|
while (IO::in8(IDE0_STATUS) & BUSY);
|
||||||
|
|
||||||
|
//dbgprintf("IDEDiskDevice: Writing %u sector(s) @ LBA %u (%u/%u/%u)\n", count, start_sector, chs.cylinder, chs.head, chs.sector);
|
||||||
|
|
||||||
|
IO::out8(0x1F2, count == 256 ? 0 : LSB(count));
|
||||||
|
IO::out8(0x1F3, chs.sector);
|
||||||
|
IO::out8(0x1F4, LSB(chs.cylinder));
|
||||||
|
IO::out8(0x1F5, MSB(chs.cylinder));
|
||||||
|
|
||||||
|
IO::out8(0x1F6, 0xA0 | chs.head); /* 0xB0 for 2nd device */
|
||||||
|
|
||||||
|
IO::out8(0x3F6, 0x08);
|
||||||
|
|
||||||
|
IO::out8(IDE0_COMMAND, WRITE_SECTORS);
|
||||||
|
|
||||||
|
while (!(IO::in8(IDE0_STATUS) & DRQ));
|
||||||
|
|
||||||
|
byte status = IO::in8(0x1f7);
|
||||||
|
if (status & DRQ) {
|
||||||
|
//dbgprintf("Sending %u bytes (status=%b), data=%p...\n", count * 512, status, data);
|
||||||
|
auto* data_as_words = (const word*)data;
|
||||||
|
for (dword i = 0; i < (count * 512) / 2; ++i) {
|
||||||
|
IO::out16(IDE0_DATA, data_as_words[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_interrupted = false;
|
||||||
|
enableIRQ();
|
||||||
|
wait_for_irq();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,8 @@ private:
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
bool wait_for_irq();
|
bool wait_for_irq();
|
||||||
bool read_sectors(dword start_sector, word count, byte* outbuf);
|
bool read_sectors(dword start_sector, word count, byte* buffer);
|
||||||
|
bool write_sectors(dword start_sector, word count, const byte* data);
|
||||||
|
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
word m_cylinders { 0 };
|
word m_cylinders { 0 };
|
||||||
|
|
|
@ -44,7 +44,8 @@ ELFLOADER_OBJS = \
|
||||||
AK_OBJS = \
|
AK_OBJS = \
|
||||||
../AK/String.o \
|
../AK/String.o \
|
||||||
../AK/StringImpl.o \
|
../AK/StringImpl.o \
|
||||||
../AK/StringBuilder.o
|
../AK/StringBuilder.o \
|
||||||
|
../AK/FileSystemPath.o
|
||||||
|
|
||||||
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(ELFLOADER_OBJS)
|
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(ELFLOADER_OBJS)
|
||||||
|
|
||||||
|
|
|
@ -1751,3 +1751,15 @@ int Process::sys$setgroups(size_t count, const gid_t* gids)
|
||||||
m_gids.set(gids[i]);
|
m_gids.set(gids[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Process::sys$mkdir(const char* pathname, mode_t mode)
|
||||||
|
{
|
||||||
|
if (!validate_read_str(pathname))
|
||||||
|
return -EFAULT;
|
||||||
|
if (strlen(pathname) >= 255)
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
int error;
|
||||||
|
if (!VFS::the().mkdir(pathname, mode, cwd_inode()->identifier(), error))
|
||||||
|
return error;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -172,6 +172,7 @@ public:
|
||||||
int sys$access(const char* pathname, int mode);
|
int sys$access(const char* pathname, int mode);
|
||||||
int sys$fcntl(int fd, int cmd, dword extra_arg);
|
int sys$fcntl(int fd, int cmd, dword extra_arg);
|
||||||
int sys$ioctl(int fd, unsigned request, unsigned arg);
|
int sys$ioctl(int fd, unsigned request, unsigned arg);
|
||||||
|
int sys$mkdir(const char* pathname, mode_t mode);
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
|
|
@ -175,6 +175,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
|
||||||
return current->sys$ioctl((int)arg1, (unsigned)arg2, (unsigned)arg3);
|
return current->sys$ioctl((int)arg1, (unsigned)arg2, (unsigned)arg3);
|
||||||
case Syscall::SC_fstat:
|
case Syscall::SC_fstat:
|
||||||
return current->sys$fstat((int)arg1, (Unix::stat*)arg2);
|
return current->sys$fstat((int)arg1, (Unix::stat*)arg2);
|
||||||
|
case Syscall::SC_mkdir:
|
||||||
|
return current->sys$mkdir((const char*)arg1, (mode_t)arg2);
|
||||||
default:
|
default:
|
||||||
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
__ENUMERATE_SYSCALL(access) \
|
__ENUMERATE_SYSCALL(access) \
|
||||||
__ENUMERATE_SYSCALL(fcntl) \
|
__ENUMERATE_SYSCALL(fcntl) \
|
||||||
__ENUMERATE_SYSCALL(ioctl) \
|
__ENUMERATE_SYSCALL(ioctl) \
|
||||||
|
__ENUMERATE_SYSCALL(mkdir) \
|
||||||
|
|
||||||
|
|
||||||
#define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
|
#define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
|
||||||
|
|
|
@ -29,6 +29,7 @@ cp -v ../Userland/mm mnt/bin/mm
|
||||||
cp -v ../Userland/kill mnt/bin/kill
|
cp -v ../Userland/kill mnt/bin/kill
|
||||||
cp -v ../Userland/tty mnt/bin/tty
|
cp -v ../Userland/tty mnt/bin/tty
|
||||||
cp -v ../Userland/strsignal mnt/bin/strsignal
|
cp -v ../Userland/strsignal mnt/bin/strsignal
|
||||||
|
cp -v ../Userland/mkdir mnt/bin/mkdir
|
||||||
sh sync-local.sh
|
sh sync-local.sh
|
||||||
cp -v kernel.map mnt/
|
cp -v kernel.map mnt/
|
||||||
umount mnt
|
umount mnt
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
__ERROR(ENOSYS, "No such syscall") \
|
__ERROR(ENOSYS, "No such syscall") \
|
||||||
__ERROR(ENOTIMPL, "Not implemented") \
|
__ERROR(ENOTIMPL, "Not implemented") \
|
||||||
__ERROR(EAFNOSUPPORT, "Address family not supported") \
|
__ERROR(EAFNOSUPPORT, "Address family not supported") \
|
||||||
|
__ERROR(EWHYTHO, "Failed without setting an error code (Bug!)") \
|
||||||
|
|
||||||
enum __errno_values {
|
enum __errno_values {
|
||||||
#undef __ERROR
|
#undef __ERROR
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -8,5 +9,11 @@ mode_t umask(mode_t mask)
|
||||||
return Syscall::invoke(Syscall::SC_umask, (dword)mask);
|
return Syscall::invoke(Syscall::SC_umask, (dword)mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mkdir(const char* pathname, mode_t mode)
|
||||||
|
{
|
||||||
|
int rc = Syscall::invoke(Syscall::SC_mkdir, (dword)pathname, (dword)mode);
|
||||||
|
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,6 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
mode_t umask(mode_t);
|
mode_t umask(mode_t);
|
||||||
int chmod(const char* pathname, mode_t);
|
int chmod(const char* pathname, mode_t);
|
||||||
|
int mkdir(const char* pathname, mode_t);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
1
Userland/.gitignore
vendored
1
Userland/.gitignore
vendored
|
@ -20,3 +20,4 @@ ft
|
||||||
ft2
|
ft2
|
||||||
strsignal
|
strsignal
|
||||||
fgrep
|
fgrep
|
||||||
|
mkdir
|
||||||
|
|
|
@ -18,7 +18,8 @@ OBJS = \
|
||||||
ft2.o \
|
ft2.o \
|
||||||
strsignal.o \
|
strsignal.o \
|
||||||
fgrep.o \
|
fgrep.o \
|
||||||
tty.o
|
tty.o \
|
||||||
|
mkdir.o
|
||||||
|
|
||||||
APPS = \
|
APPS = \
|
||||||
id \
|
id \
|
||||||
|
@ -40,7 +41,8 @@ APPS = \
|
||||||
ft2 \
|
ft2 \
|
||||||
strsignal \
|
strsignal \
|
||||||
fgrep \
|
fgrep \
|
||||||
tty
|
tty \
|
||||||
|
mkdir
|
||||||
|
|
||||||
ARCH_FLAGS =
|
ARCH_FLAGS =
|
||||||
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
|
||||||
|
@ -120,6 +122,9 @@ tty: tty.o
|
||||||
strsignal: strsignal.o
|
strsignal: strsignal.o
|
||||||
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
|
mkdir: mkdir.o
|
||||||
|
$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
|
||||||
|
|
||||||
.cpp.o:
|
.cpp.o:
|
||||||
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
|
21
Userland/mkdir.cpp
Normal file
21
Userland/mkdir.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("usage: mkdir <path>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int rc = mkdir(argv[1], 0755);
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("mkdir");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -11,31 +11,6 @@
|
||||||
|
|
||||||
//#define EXT2_DEBUG
|
//#define EXT2_DEBUG
|
||||||
|
|
||||||
class Ext2FS::CachedExt2InodeImpl : public Retainable<CachedExt2InodeImpl> {
|
|
||||||
public:
|
|
||||||
CachedExt2InodeImpl(OwnPtr<ext2_inode>&& e2i) : e2inode(move(e2i)) { }
|
|
||||||
~CachedExt2InodeImpl() { }
|
|
||||||
OwnPtr<ext2_inode> e2inode;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Ext2FS::CachedExt2Inode {
|
|
||||||
public:
|
|
||||||
const ext2_inode* operator->() const { return ptr->e2inode.ptr(); }
|
|
||||||
const ext2_inode& operator*() const { return *ptr->e2inode; }
|
|
||||||
ext2_inode* operator->() { return ptr->e2inode.ptr(); }
|
|
||||||
ext2_inode& operator*() { return *ptr->e2inode; }
|
|
||||||
bool operator!() const { return !ptr; }
|
|
||||||
operator bool() const { return !!ptr; }
|
|
||||||
CachedExt2Inode() { }
|
|
||||||
explicit CachedExt2Inode(OwnPtr<ext2_inode>&& e2inode)
|
|
||||||
: ptr(adopt(*new CachedExt2InodeImpl(move(e2inode))))
|
|
||||||
{ }
|
|
||||||
explicit CachedExt2Inode(RetainPtr<CachedExt2InodeImpl> p)
|
|
||||||
: ptr(p)
|
|
||||||
{ }
|
|
||||||
RetainPtr<CachedExt2InodeImpl> ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
RetainPtr<Ext2FS> Ext2FS::create(RetainPtr<DiskDevice>&& device)
|
RetainPtr<Ext2FS> Ext2FS::create(RetainPtr<DiskDevice>&& device)
|
||||||
{
|
{
|
||||||
return adopt(*new Ext2FS(move(device)));
|
return adopt(*new Ext2FS(move(device)));
|
||||||
|
@ -187,16 +162,8 @@ ByteBuffer Ext2FS::readBlockContainingInode(unsigned inode, unsigned& blockIndex
|
||||||
return readBlock(blockIndex);
|
return readBlock(blockIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Ext2FS::lookupExt2Inode(unsigned inode) const -> CachedExt2Inode
|
OwnPtr<ext2_inode> Ext2FS::lookupExt2Inode(unsigned inode) const
|
||||||
{
|
{
|
||||||
{
|
|
||||||
LOCKER(m_inodeCacheLock);
|
|
||||||
auto it = m_inodeCache.find(inode);
|
|
||||||
if (it != m_inodeCache.end()) {
|
|
||||||
return CachedExt2Inode{ (*it).value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned blockIndex;
|
unsigned blockIndex;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
auto block = readBlockContainingInode(inode, blockIndex, offset);
|
auto block = readBlockContainingInode(inode, blockIndex, offset);
|
||||||
|
@ -210,12 +177,7 @@ auto Ext2FS::lookupExt2Inode(unsigned inode) const -> CachedExt2Inode
|
||||||
dumpExt2Inode(*e2inode);
|
dumpExt2Inode(*e2inode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOCKER(m_inodeCacheLock);
|
return OwnPtr<ext2_inode>(e2inode);
|
||||||
if (m_inodeCache.size() >= 128)
|
|
||||||
m_inodeCache.removeOneRandomly();
|
|
||||||
auto cachedInode = adopt(*new CachedExt2InodeImpl(OwnPtr<ext2_inode>(e2inode)));
|
|
||||||
m_inodeCache.set(inode, cachedInode.copyRef());
|
|
||||||
return CachedExt2Inode{ cachedInode };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeMetadata Ext2FS::inodeMetadata(InodeIdentifier inode) const
|
InodeMetadata Ext2FS::inodeMetadata(InodeIdentifier inode) const
|
||||||
|
@ -528,7 +490,7 @@ bool Ext2FS::writeInode(InodeIdentifier inode, const ByteBuffer& data)
|
||||||
|
|
||||||
for (unsigned i = 0; i < list.size(); ++i) {
|
for (unsigned i = 0; i < list.size(); ++i) {
|
||||||
auto section = data.slice(i * blockSize(), blockSize());
|
auto section = data.slice(i * blockSize(), blockSize());
|
||||||
kprintf("section = %p (%u)\n", section.pointer(), section.size());
|
//kprintf("section = %p (%u)\n", section.pointer(), section.size());
|
||||||
bool success = writeBlock(list[i], section);
|
bool success = writeBlock(list[i], section);
|
||||||
ASSERT(success);
|
ASSERT(success);
|
||||||
}
|
}
|
||||||
|
@ -587,14 +549,14 @@ bool Ext2FS::deprecated_enumerateDirectoryInode(InodeIdentifier inode, Function<
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ext2FS::addInodeToDirectory(unsigned directoryInode, unsigned inode, const String& name, byte fileType)
|
bool Ext2FS::addInodeToDirectory(unsigned directoryInode, unsigned inode, const String& name, byte fileType, int& error)
|
||||||
{
|
{
|
||||||
auto e2inodeForDirectory = lookupExt2Inode(directoryInode);
|
auto e2inodeForDirectory = lookupExt2Inode(directoryInode);
|
||||||
ASSERT(e2inodeForDirectory);
|
ASSERT(e2inodeForDirectory);
|
||||||
ASSERT(isDirectory(e2inodeForDirectory->i_mode));
|
ASSERT(isDirectory(e2inodeForDirectory->i_mode));
|
||||||
|
|
||||||
//#ifdef EXT2_DEBUG
|
//#ifdef EXT2_DEBUG
|
||||||
kprintf("ext2fs: Adding inode %u with name '%s' to directory %u\n", inode, name.characters(), directoryInode);
|
dbgprintf("Ext2FS: Adding inode %u with name '%s' to directory %u\n", inode, name.characters(), directoryInode);
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
Vector<DirectoryEntry> entries;
|
Vector<DirectoryEntry> entries;
|
||||||
|
@ -608,7 +570,8 @@ bool Ext2FS::addInodeToDirectory(unsigned directoryInode, unsigned inode, const
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (nameAlreadyExists) {
|
if (nameAlreadyExists) {
|
||||||
kprintf("ext2fs: Name '%s' already exists in directory inode %u\n", name.characters(), directoryInode);
|
kprintf("Ext2FS: Name '%s' already exists in directory inode %u\n", name.characters(), directoryInode);
|
||||||
|
error = -EEXIST;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,18 +581,18 @@ bool Ext2FS::addInodeToDirectory(unsigned directoryInode, unsigned inode, const
|
||||||
|
|
||||||
bool Ext2FS::writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>&& entries)
|
bool Ext2FS::writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>&& entries)
|
||||||
{
|
{
|
||||||
kprintf("ext2fs: New directory inode %u contents to write:\n", directoryInode);
|
dbgprintf("Ext2FS: New directory inode %u contents to write:\n", directoryInode);
|
||||||
|
|
||||||
unsigned directorySize = 0;
|
unsigned directorySize = 0;
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
kprintf(" - %08u %s\n", entry.inode.index(), entry.name);
|
//kprintf(" - %08u %s\n", entry.inode.index(), entry.name);
|
||||||
directorySize += EXT2_DIR_REC_LEN(entry.name_length);
|
directorySize += EXT2_DIR_REC_LEN(entry.name_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned blocksNeeded = ceilDiv(directorySize, blockSize());
|
unsigned blocksNeeded = ceilDiv(directorySize, blockSize());
|
||||||
unsigned occupiedSize = blocksNeeded * blockSize();
|
unsigned occupiedSize = blocksNeeded * blockSize();
|
||||||
|
|
||||||
kprintf("ext2fs: directory size: %u (occupied: %u)\n", directorySize, occupiedSize);
|
dbgprintf("Ext2FS: directory size: %u (occupied: %u)\n", directorySize, occupiedSize);
|
||||||
|
|
||||||
auto directoryData = ByteBuffer::createUninitialized(occupiedSize);
|
auto directoryData = ByteBuffer::createUninitialized(occupiedSize);
|
||||||
|
|
||||||
|
@ -641,11 +604,11 @@ bool Ext2FS::writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>
|
||||||
if (i == entries.size() - 1)
|
if (i == entries.size() - 1)
|
||||||
recordLength += occupiedSize - directorySize;
|
recordLength += occupiedSize - directorySize;
|
||||||
|
|
||||||
kprintf("* inode: %u", entry.inode.index());
|
dbgprintf("* inode: %u", entry.inode.index());
|
||||||
kprintf(", name_len: %u", word(entry.name_length));
|
dbgprintf(", name_len: %u", word(entry.name_length));
|
||||||
kprintf(", rec_len: %u", word(recordLength));
|
dbgprintf(", rec_len: %u", word(recordLength));
|
||||||
kprintf(", file_type: %u", byte(entry.fileType));
|
dbgprintf(", file_type: %u", byte(entry.fileType));
|
||||||
kprintf(", name: %s\n", entry.name);
|
dbgprintf(", name: %s\n", entry.name);
|
||||||
|
|
||||||
stream << dword(entry.inode.index());
|
stream << dword(entry.inode.index());
|
||||||
stream << word(recordLength);
|
stream << word(recordLength);
|
||||||
|
@ -654,7 +617,7 @@ bool Ext2FS::writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>
|
||||||
stream << entry.name;
|
stream << entry.name;
|
||||||
|
|
||||||
unsigned padding = recordLength - entry.name_length - 8;
|
unsigned padding = recordLength - entry.name_length - 8;
|
||||||
kprintf(" *** pad %u bytes\n", padding);
|
//dbgprintf(" *** pad %u bytes\n", padding);
|
||||||
for (unsigned j = 0; j < padding; ++j) {
|
for (unsigned j = 0; j < padding; ++j) {
|
||||||
stream << byte(0);
|
stream << byte(0);
|
||||||
}
|
}
|
||||||
|
@ -772,7 +735,7 @@ bool Ext2FS::modifyLinkCount(InodeIndex inode, int delta)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto newLinkCount = e2inode->i_links_count + delta;
|
auto newLinkCount = e2inode->i_links_count + delta;
|
||||||
kprintf("changing inode %u link count from %u to %u\n", inode, e2inode->i_links_count, newLinkCount);
|
dbgprintf("Ext2FS: changing inode %u link count from %u to %u\n", inode, e2inode->i_links_count, newLinkCount);
|
||||||
e2inode->i_links_count = newLinkCount;
|
e2inode->i_links_count = newLinkCount;
|
||||||
|
|
||||||
return writeExt2Inode(inode, *e2inode);
|
return writeExt2Inode(inode, *e2inode);
|
||||||
|
@ -799,6 +762,18 @@ bool Ext2FS::writeExt2Inode(unsigned inode, const ext2_inode& e2inode)
|
||||||
auto block = readBlockContainingInode(inode, blockIndex, offset);
|
auto block = readBlockContainingInode(inode, blockIndex, offset);
|
||||||
if (!block)
|
if (!block)
|
||||||
return false;
|
return false;
|
||||||
|
{
|
||||||
|
LOCKER(m_inode_cache_lock);
|
||||||
|
auto it = m_inode_cache.find(inode);
|
||||||
|
if (it != m_inode_cache.end()) {
|
||||||
|
auto& cached_inode = *(*it).value;
|
||||||
|
LOCKER(cached_inode.m_lock);
|
||||||
|
cached_inode.m_raw_inode = e2inode;
|
||||||
|
cached_inode.populate_metadata();
|
||||||
|
if (cached_inode.is_directory())
|
||||||
|
cached_inode.m_lookup_cache.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(reinterpret_cast<ext2_inode*>(block.offsetPointer(offset)), &e2inode, inodeSize());
|
memcpy(reinterpret_cast<ext2_inode*>(block.offsetPointer(offset)), &e2inode, inodeSize());
|
||||||
writeBlock(blockIndex, block);
|
writeBlock(blockIndex, block);
|
||||||
return true;
|
return true;
|
||||||
|
@ -813,11 +788,11 @@ bool Ext2FS::isDirectoryInode(unsigned inode) const
|
||||||
|
|
||||||
Vector<Ext2FS::BlockIndex> Ext2FS::allocateBlocks(unsigned group, unsigned count)
|
Vector<Ext2FS::BlockIndex> Ext2FS::allocateBlocks(unsigned group, unsigned count)
|
||||||
{
|
{
|
||||||
kprintf("ext2fs: allocateBlocks(group: %u, count: %u)\n", group, count);
|
dbgprintf("Ext2FS: allocateBlocks(group: %u, count: %u)\n", group, count);
|
||||||
|
|
||||||
auto& bgd = blockGroupDescriptor(group);
|
auto& bgd = blockGroupDescriptor(group);
|
||||||
if (bgd.bg_free_blocks_count < count) {
|
if (bgd.bg_free_blocks_count < count) {
|
||||||
kprintf("ext2fs: allocateBlocks can't allocate out of group %u, wanted %u but only %u available\n", group, count, bgd.bg_free_blocks_count);
|
kprintf("ExtFS: allocateBlocks can't allocate out of group %u, wanted %u but only %u available\n", group, count, bgd.bg_free_blocks_count);
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,9 +808,9 @@ Vector<Ext2FS::BlockIndex> Ext2FS::allocateBlocks(unsigned group, unsigned count
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
kprintf("ext2fs: allocateBlock found these blocks:\n");
|
dbgprintf("Ext2FS: allocateBlock found these blocks:\n");
|
||||||
for (auto& bi : blocks) {
|
for (auto& bi : blocks) {
|
||||||
kprintf(" > %u\n", bi);
|
dbgprintf(" > %u\n", bi);
|
||||||
}
|
}
|
||||||
|
|
||||||
return blocks;
|
return blocks;
|
||||||
|
@ -843,11 +818,11 @@ Vector<Ext2FS::BlockIndex> Ext2FS::allocateBlocks(unsigned group, unsigned count
|
||||||
|
|
||||||
unsigned Ext2FS::allocateInode(unsigned preferredGroup, unsigned expectedSize)
|
unsigned Ext2FS::allocateInode(unsigned preferredGroup, unsigned expectedSize)
|
||||||
{
|
{
|
||||||
kprintf("ext2fs: allocateInode(preferredGroup: %u, expectedSize: %u)\n", preferredGroup, expectedSize);
|
dbgprintf("Ext2FS: allocateInode(preferredGroup: %u, expectedSize: %u)\n", preferredGroup, expectedSize);
|
||||||
|
|
||||||
unsigned neededBlocks = ceilDiv(expectedSize, blockSize());
|
unsigned neededBlocks = ceilDiv(expectedSize, blockSize());
|
||||||
|
|
||||||
kprintf("ext2fs: minimum needed blocks: %u\n", neededBlocks);
|
dbgprintf("Ext2FS: minimum needed blocks: %u\n", neededBlocks);
|
||||||
|
|
||||||
unsigned groupIndex = 0;
|
unsigned groupIndex = 0;
|
||||||
|
|
||||||
|
@ -866,11 +841,11 @@ unsigned Ext2FS::allocateInode(unsigned preferredGroup, unsigned expectedSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!groupIndex) {
|
if (!groupIndex) {
|
||||||
kprintf("ext2fs: allocateInode: no suitable group found for new inode with %u blocks needed :(\n", neededBlocks);
|
kprintf("Ext2FS: allocateInode: no suitable group found for new inode with %u blocks needed :(\n", neededBlocks);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("ext2fs: allocateInode: found suitable group [%u] for new inode with %u blocks needed :^)\n", groupIndex, neededBlocks);
|
dbgprintf("Ext2FS: allocateInode: found suitable group [%u] for new inode with %u blocks needed :^)\n", groupIndex, neededBlocks);
|
||||||
|
|
||||||
unsigned firstFreeInodeInGroup = 0;
|
unsigned firstFreeInodeInGroup = 0;
|
||||||
traverseInodeBitmap(groupIndex, [&firstFreeInodeInGroup] (unsigned firstInodeInBitmap, const Bitmap& bitmap) {
|
traverseInodeBitmap(groupIndex, [&firstFreeInodeInGroup] (unsigned firstInodeInBitmap, const Bitmap& bitmap) {
|
||||||
|
@ -884,12 +859,12 @@ unsigned Ext2FS::allocateInode(unsigned preferredGroup, unsigned expectedSize)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!firstFreeInodeInGroup) {
|
if (!firstFreeInodeInGroup) {
|
||||||
kprintf("ext2fs: firstFreeInodeInGroup returned no inode, despite bgd claiming there are inodes :(\n");
|
kprintf("Ext2FS: firstFreeInodeInGroup returned no inode, despite bgd claiming there are inodes :(\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned inode = firstFreeInodeInGroup;
|
unsigned inode = firstFreeInodeInGroup;
|
||||||
kprintf("ext2fs: found suitable inode %u\n", inode);
|
dbgprintf("Ext2FS: found suitable inode %u\n", inode);
|
||||||
|
|
||||||
// FIXME: allocate blocks if needed!
|
// FIXME: allocate blocks if needed!
|
||||||
|
|
||||||
|
@ -915,7 +890,7 @@ bool Ext2FS::setInodeAllocationState(unsigned inode, bool newState)
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
|
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
|
||||||
bool currentState = bitmap.get(bitIndex);
|
bool currentState = bitmap.get(bitIndex);
|
||||||
kprintf("ext2fs: setInodeAllocationState(%u) %u -> %u\n", inode, currentState, newState);
|
dbgprintf("ext2fs: setInodeAllocationState(%u) %u -> %u\n", inode, currentState, newState);
|
||||||
|
|
||||||
if (currentState == newState)
|
if (currentState == newState)
|
||||||
return true;
|
return true;
|
||||||
|
@ -925,7 +900,7 @@ bool Ext2FS::setInodeAllocationState(unsigned inode, bool newState)
|
||||||
|
|
||||||
// Update superblock
|
// Update superblock
|
||||||
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
|
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
|
||||||
kprintf("ext2fs: superblock free inode count %u -> %u\n", sb.s_free_inodes_count, sb.s_free_inodes_count - 1);
|
dbgprintf("Ext2FS: superblock free inode count %u -> %u\n", sb.s_free_inodes_count, sb.s_free_inodes_count - 1);
|
||||||
if (newState)
|
if (newState)
|
||||||
--sb.s_free_inodes_count;
|
--sb.s_free_inodes_count;
|
||||||
else
|
else
|
||||||
|
@ -938,7 +913,7 @@ bool Ext2FS::setInodeAllocationState(unsigned inode, bool newState)
|
||||||
--mutableBGD.bg_free_inodes_count;
|
--mutableBGD.bg_free_inodes_count;
|
||||||
else
|
else
|
||||||
++mutableBGD.bg_free_inodes_count;
|
++mutableBGD.bg_free_inodes_count;
|
||||||
kprintf("ext2fs: group free inode count %u -> %u\n", bgd.bg_free_inodes_count, bgd.bg_free_inodes_count - 1);
|
dbgprintf("Ext2FS: group free inode count %u -> %u\n", bgd.bg_free_inodes_count, bgd.bg_free_inodes_count - 1);
|
||||||
|
|
||||||
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
||||||
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
||||||
|
@ -959,7 +934,7 @@ bool Ext2FS::setBlockAllocationState(GroupIndex group, BlockIndex bi, bool newSt
|
||||||
ASSERT(block);
|
ASSERT(block);
|
||||||
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
|
auto bitmap = Bitmap::wrap(block.pointer(), block.size());
|
||||||
bool currentState = bitmap.get(bitIndex);
|
bool currentState = bitmap.get(bitIndex);
|
||||||
kprintf("ext2fs: setBlockAllocationState(%u) %u -> %u\n", bi, currentState, newState);
|
dbgprintf("Ext2FS: setBlockAllocationState(%u) %u -> %u\n", bi, currentState, newState);
|
||||||
|
|
||||||
if (currentState == newState)
|
if (currentState == newState)
|
||||||
return true;
|
return true;
|
||||||
|
@ -969,7 +944,7 @@ bool Ext2FS::setBlockAllocationState(GroupIndex group, BlockIndex bi, bool newSt
|
||||||
|
|
||||||
// Update superblock
|
// Update superblock
|
||||||
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
|
auto& sb = *reinterpret_cast<ext2_super_block*>(m_cachedSuperBlock.pointer());
|
||||||
kprintf("ext2fs: superblock free block count %u -> %u\n", sb.s_free_blocks_count, sb.s_free_blocks_count - 1);
|
dbgprintf("Ext2FS: superblock free block count %u -> %u\n", sb.s_free_blocks_count, sb.s_free_blocks_count - 1);
|
||||||
if (newState)
|
if (newState)
|
||||||
--sb.s_free_blocks_count;
|
--sb.s_free_blocks_count;
|
||||||
else
|
else
|
||||||
|
@ -982,7 +957,7 @@ bool Ext2FS::setBlockAllocationState(GroupIndex group, BlockIndex bi, bool newSt
|
||||||
--mutableBGD.bg_free_blocks_count;
|
--mutableBGD.bg_free_blocks_count;
|
||||||
else
|
else
|
||||||
++mutableBGD.bg_free_blocks_count;
|
++mutableBGD.bg_free_blocks_count;
|
||||||
kprintf("ext2fs: group free block count %u -> %u\n", bgd.bg_free_blocks_count, bgd.bg_free_blocks_count - 1);
|
dbgprintf("Ext2FS: group free block count %u -> %u\n", bgd.bg_free_blocks_count, bgd.bg_free_blocks_count - 1);
|
||||||
|
|
||||||
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
||||||
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
||||||
|
@ -991,7 +966,7 @@ bool Ext2FS::setBlockAllocationState(GroupIndex group, BlockIndex bi, bool newSt
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeIdentifier Ext2FS::create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t mode)
|
InodeIdentifier Ext2FS::create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, int& error)
|
||||||
{
|
{
|
||||||
ASSERT(parentInode.fsid() == id());
|
ASSERT(parentInode.fsid() == id());
|
||||||
ASSERT(isDirectoryInode(parentInode.index()));
|
ASSERT(isDirectoryInode(parentInode.index()));
|
||||||
|
@ -1003,11 +978,11 @@ InodeIdentifier Ext2FS::create_directory(InodeIdentifier parentInode, const Stri
|
||||||
|
|
||||||
// NOTE: When creating a new directory, make the size 1 block.
|
// NOTE: When creating a new directory, make the size 1 block.
|
||||||
// There's probably a better strategy here, but this works for now.
|
// There's probably a better strategy here, but this works for now.
|
||||||
auto inode = create_inode(parentInode, name, mode, blockSize());
|
auto inode = create_inode(parentInode, name, mode, blockSize(), error);
|
||||||
if (!inode.isValid())
|
if (!inode.isValid())
|
||||||
return { };
|
return { };
|
||||||
|
|
||||||
kprintf("ext2fs: makeDirectory: created new directory named '%s' with inode %u\n", name.characters(), inode.index());
|
dbgprintf("Ext2FS: create_directory: created new directory named '%s' with inode %u\n", name.characters(), inode.index());
|
||||||
|
|
||||||
Vector<DirectoryEntry> entries;
|
Vector<DirectoryEntry> entries;
|
||||||
entries.append({ ".", inode, EXT2_FT_DIR });
|
entries.append({ ".", inode, EXT2_FT_DIR });
|
||||||
|
@ -1021,34 +996,35 @@ InodeIdentifier Ext2FS::create_directory(InodeIdentifier parentInode, const Stri
|
||||||
|
|
||||||
auto& bgd = const_cast<ext2_group_desc&>(blockGroupDescriptor(groupIndexFromInode(inode.index())));
|
auto& bgd = const_cast<ext2_group_desc&>(blockGroupDescriptor(groupIndexFromInode(inode.index())));
|
||||||
++bgd.bg_used_dirs_count;
|
++bgd.bg_used_dirs_count;
|
||||||
kprintf("ext2fs: incremented bg_used_dirs_count %u -> %u\n", bgd.bg_used_dirs_count - 1, bgd.bg_used_dirs_count);
|
dbgprintf("Ext2FS: incremented bg_used_dirs_count %u -> %u\n", bgd.bg_used_dirs_count - 1, bgd.bg_used_dirs_count);
|
||||||
|
|
||||||
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
unsigned blocksToWrite = ceilDiv(m_blockGroupCount * (unsigned)sizeof(ext2_group_desc), blockSize());
|
||||||
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
unsigned firstBlockOfBGDT = blockSize() == 1024 ? 2 : 1;
|
||||||
writeBlocks(firstBlockOfBGDT, blocksToWrite, m_cachedBlockGroupDescriptorTable);
|
writeBlocks(firstBlockOfBGDT, blocksToWrite, m_cachedBlockGroupDescriptorTable);
|
||||||
|
|
||||||
|
error = 0;
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeIdentifier Ext2FS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size)
|
InodeIdentifier Ext2FS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
|
||||||
{
|
{
|
||||||
ASSERT(parentInode.fsid() == id());
|
ASSERT(parentInode.fsid() == id());
|
||||||
ASSERT(isDirectoryInode(parentInode.index()));
|
ASSERT(isDirectoryInode(parentInode.index()));
|
||||||
|
|
||||||
//#ifdef EXT2_DEBUG
|
dbgprintf("Ext2FS: Adding inode '%s' (mode %o) to parent directory %u:\n", name.characters(), mode, parentInode.index());
|
||||||
kprintf("ext2fs: Adding inode '%s' (mode %o) to parent directory %u:\n", name.characters(), mode, parentInode.index());
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
// NOTE: This doesn't commit the inode allocation just yet!
|
// NOTE: This doesn't commit the inode allocation just yet!
|
||||||
auto inode = allocateInode(0, 0);
|
auto inode = allocateInode(0, 0);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
kprintf("ext2fs: createInode: allocateInode failed\n");
|
kprintf("Ext2FS: createInode: allocateInode failed\n");
|
||||||
|
error = -ENOSPC;
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto blocks = allocateBlocks(groupIndexFromInode(inode), ceilDiv(size, blockSize()));
|
auto blocks = allocateBlocks(groupIndexFromInode(inode), ceilDiv(size, blockSize()));
|
||||||
if (blocks.isEmpty()) {
|
if (blocks.isEmpty()) {
|
||||||
kprintf("ext2fs: createInode: allocateBlocks failed\n");
|
kprintf("Ext2FS: createInode: allocateBlocks failed\n");
|
||||||
|
error = -ENOSPC;
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,11 +1045,9 @@ InodeIdentifier Ext2FS::create_inode(InodeIdentifier parentInode, const String&
|
||||||
fileType = EXT2_FT_SYMLINK;
|
fileType = EXT2_FT_SYMLINK;
|
||||||
|
|
||||||
// Try adding it to the directory first, in case the name is already in use.
|
// Try adding it to the directory first, in case the name is already in use.
|
||||||
bool success = addInodeToDirectory(parentInode.index(), inode, name, fileType);
|
bool success = addInodeToDirectory(parentInode.index(), inode, name, fileType, error);
|
||||||
if (!success) {
|
if (!success)
|
||||||
kprintf("ext2fs: failed to add inode to directory :(\n");
|
|
||||||
return { };
|
return { };
|
||||||
}
|
|
||||||
|
|
||||||
// Looks like we're good, time to update the inode bitmap and group+global inode counters.
|
// Looks like we're good, time to update the inode bitmap and group+global inode counters.
|
||||||
success = setInodeAllocationState(inode, true);
|
success = setInodeAllocationState(inode, true);
|
||||||
|
@ -1107,7 +1081,7 @@ InodeIdentifier Ext2FS::create_inode(InodeIdentifier parentInode, const String&
|
||||||
// FIXME: Implement writing out indirect blocks!
|
// FIXME: Implement writing out indirect blocks!
|
||||||
ASSERT(blocks.size() < EXT2_NDIR_BLOCKS);
|
ASSERT(blocks.size() < EXT2_NDIR_BLOCKS);
|
||||||
|
|
||||||
kprintf("[XXX] writing %zu blocks to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
|
dbgprintf("Ext2FS: writing %zu blocks to i_block array\n", min((size_t)EXT2_NDIR_BLOCKS, blocks.size()));
|
||||||
for (unsigned i = 0; i < min((size_t)EXT2_NDIR_BLOCKS, blocks.size()); ++i) {
|
for (unsigned i = 0; i < min((size_t)EXT2_NDIR_BLOCKS, blocks.size()); ++i) {
|
||||||
e2inode->i_block[i] = blocks[i];
|
e2inode->i_block[i] = blocks[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,9 +51,6 @@ private:
|
||||||
typedef unsigned BlockIndex;
|
typedef unsigned BlockIndex;
|
||||||
typedef unsigned GroupIndex;
|
typedef unsigned GroupIndex;
|
||||||
typedef unsigned InodeIndex;
|
typedef unsigned InodeIndex;
|
||||||
class CachedExt2Inode;
|
|
||||||
class CachedExt2InodeImpl;
|
|
||||||
|
|
||||||
explicit Ext2FS(RetainPtr<DiskDevice>&&);
|
explicit Ext2FS(RetainPtr<DiskDevice>&&);
|
||||||
|
|
||||||
const ext2_super_block& superBlock() const;
|
const ext2_super_block& superBlock() const;
|
||||||
|
@ -64,7 +61,7 @@ private:
|
||||||
unsigned blocksPerGroup() const;
|
unsigned blocksPerGroup() const;
|
||||||
unsigned inodeSize() const;
|
unsigned inodeSize() const;
|
||||||
|
|
||||||
CachedExt2Inode lookupExt2Inode(unsigned) const;
|
OwnPtr<ext2_inode> lookupExt2Inode(unsigned) const;
|
||||||
bool writeExt2Inode(unsigned, const ext2_inode&);
|
bool writeExt2Inode(unsigned, const ext2_inode&);
|
||||||
ByteBuffer readBlockContainingInode(unsigned inode, unsigned& blockIndex, unsigned& offset) const;
|
ByteBuffer readBlockContainingInode(unsigned inode, unsigned& blockIndex, unsigned& offset) const;
|
||||||
|
|
||||||
|
@ -76,9 +73,9 @@ private:
|
||||||
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
|
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
|
||||||
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||||
virtual Unix::ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, Unix::size_t count, byte* buffer, FileDescriptor*) const override;
|
virtual Unix::ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, Unix::size_t count, byte* buffer, FileDescriptor*) const override;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t) override;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||||
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const override;
|
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const override;
|
||||||
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const override;
|
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const override;
|
||||||
|
|
||||||
|
@ -95,7 +92,7 @@ private:
|
||||||
template<typename F> void traverseInodeBitmap(unsigned groupIndex, F) const;
|
template<typename F> void traverseInodeBitmap(unsigned groupIndex, F) const;
|
||||||
template<typename F> void traverseBlockBitmap(unsigned groupIndex, F) const;
|
template<typename F> void traverseBlockBitmap(unsigned groupIndex, F) const;
|
||||||
|
|
||||||
bool addInodeToDirectory(unsigned directoryInode, unsigned inode, const String& name, byte fileType);
|
bool addInodeToDirectory(unsigned directoryInode, unsigned inode, const String& name, byte fileType, int& error);
|
||||||
bool writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>&&);
|
bool writeDirectoryInode(unsigned directoryInode, Vector<DirectoryEntry>&&);
|
||||||
bool setInodeAllocationState(unsigned inode, bool);
|
bool setInodeAllocationState(unsigned inode, bool);
|
||||||
bool setBlockAllocationState(GroupIndex, BlockIndex, bool);
|
bool setBlockAllocationState(GroupIndex, BlockIndex, bool);
|
||||||
|
@ -109,9 +106,6 @@ private:
|
||||||
mutable ByteBuffer m_cachedSuperBlock;
|
mutable ByteBuffer m_cachedSuperBlock;
|
||||||
mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
|
mutable ByteBuffer m_cachedBlockGroupDescriptorTable;
|
||||||
|
|
||||||
mutable SpinLock m_inodeCacheLock;
|
|
||||||
mutable HashMap<unsigned, RetainPtr<CachedExt2InodeImpl>> m_inodeCache;
|
|
||||||
|
|
||||||
mutable SpinLock m_inode_cache_lock;
|
mutable SpinLock m_inode_cache_lock;
|
||||||
mutable HashMap<BlockIndex, RetainPtr<Ext2FSInode>> m_inode_cache;
|
mutable HashMap<BlockIndex, RetainPtr<Ext2FSInode>> m_inode_cache;
|
||||||
};
|
};
|
||||||
|
|
|
@ -107,7 +107,7 @@ ByteBuffer FS::readEntireInode(InodeIdentifier inode, FileDescriptor* handle) co
|
||||||
}
|
}
|
||||||
|
|
||||||
FS::DirectoryEntry::DirectoryEntry(const char* n, InodeIdentifier i, byte ft)
|
FS::DirectoryEntry::DirectoryEntry(const char* n, InodeIdentifier i, byte ft)
|
||||||
: name_length(strlen(name))
|
: name_length(strlen(n))
|
||||||
, inode(i)
|
, inode(i)
|
||||||
, fileType(ft)
|
, fileType(ft)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,8 +45,8 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) = 0;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) = 0;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) = 0;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t) = 0;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) = 0;
|
||||||
|
|
||||||
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const = 0;
|
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "SyntheticFileSystem.h"
|
#include "SyntheticFileSystem.h"
|
||||||
#include "FileDescriptor.h"
|
#include "FileDescriptor.h"
|
||||||
|
#include <LibC/errno_numbers.h>
|
||||||
#include <AK/StdLib.h>
|
#include <AK/StdLib.h>
|
||||||
|
|
||||||
#ifndef SERENITY
|
#ifndef SERENITY
|
||||||
|
@ -152,13 +153,14 @@ bool SynthFS::set_mtime(InodeIdentifier, dword timestamp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeIdentifier SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size)
|
InodeIdentifier SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
|
||||||
{
|
{
|
||||||
(void) parentInode;
|
(void) parentInode;
|
||||||
(void) name;
|
(void) name;
|
||||||
(void) mode;
|
(void) mode;
|
||||||
(void) size;
|
(void) size;
|
||||||
kprintf("FIXME: Implement SyntheticFileSystem::createDirectoryInode().\n");
|
(void) error;
|
||||||
|
kprintf("FIXME: Implement SyntheticFileSystem::create_inode().\n");
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,11 +207,9 @@ Unix::ssize_t SynthFS::read_inode_bytes(InodeIdentifier inode, Unix::off_t offse
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeIdentifier SynthFS::create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t)
|
InodeIdentifier SynthFS::create_directory(InodeIdentifier, const String&, Unix::mode_t, int& error)
|
||||||
{
|
{
|
||||||
(void) parentInode;
|
error = -EROFS;
|
||||||
(void) name;
|
|
||||||
kprintf("FIXME: Implement SyntheticFileSystem::makeDirectory().\n");
|
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,9 @@ public:
|
||||||
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
|
virtual bool writeInode(InodeIdentifier, const ByteBuffer&) override;
|
||||||
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
virtual InodeMetadata inodeMetadata(InodeIdentifier) const override;
|
||||||
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
virtual bool set_mtime(InodeIdentifier, dword timestamp) override;
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size) override;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||||
virtual Unix::ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, Unix::size_t count, byte* buffer, FileDescriptor*) const override;
|
virtual Unix::ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, Unix::size_t count, byte* buffer, FileDescriptor*) const override;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t) override;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||||
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const override;
|
virtual InodeIdentifier find_parent_of_inode(InodeIdentifier) const override;
|
||||||
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const override;
|
virtual RetainPtr<CoreInode> get_inode(InodeIdentifier) const override;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "VirtualFileSystem.h"
|
#include "VirtualFileSystem.h"
|
||||||
#include "FileDescriptor.h"
|
#include "FileDescriptor.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
#include <AK/FileSystemPath.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <AK/kmalloc.h>
|
#include <AK/kmalloc.h>
|
||||||
#include <AK/kstdio.h>
|
#include <AK/kstdio.h>
|
||||||
|
@ -419,22 +420,34 @@ RetainPtr<FileDescriptor> VFS::open(const String& path, int& error, int options,
|
||||||
return FileDescriptor::create(move(vnode));
|
return FileDescriptor::create(move(vnode));
|
||||||
}
|
}
|
||||||
|
|
||||||
RetainPtr<FileDescriptor> VFS::create(const String& path, InodeIdentifier base)
|
RetainPtr<FileDescriptor> VFS::create(const String& path, InodeIdentifier base, int& error)
|
||||||
{
|
{
|
||||||
// FIXME: Do the real thing, not just this fake thing!
|
// FIXME: Do the real thing, not just this fake thing!
|
||||||
(void) path;
|
(void) path;
|
||||||
(void) base;
|
(void) base;
|
||||||
m_root_vnode->fileSystem()->create_inode(m_root_vnode->fileSystem()->rootInode(), "empty", 0100644, 0);
|
m_root_vnode->fileSystem()->create_inode(m_root_vnode->fileSystem()->rootInode(), "empty", 0100644, 0, error);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RetainPtr<FileDescriptor> VFS::mkdir(const String& path, InodeIdentifier base)
|
bool VFS::mkdir(const String& path, mode_t mode, InodeIdentifier base, int& error)
|
||||||
{
|
{
|
||||||
// FIXME: Do the real thing, not just this fake thing!
|
error = EWHYTHO;
|
||||||
(void) path;
|
// FIXME: This won't work nicely across mount boundaries.
|
||||||
(void) base;
|
FileSystemPath p(path);
|
||||||
m_root_vnode->fileSystem()->create_directory(m_root_vnode->fileSystem()->rootInode(), "mydir", 0400755);
|
if (!p.isValid()) {
|
||||||
return nullptr;
|
error = -EINVAL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dbgprintf("VFS::mkdir: '%s' in '%s'\n", p.basename().characters(), p.dirname().characters());
|
||||||
|
auto parent_dir = resolve_path(p.dirname(), error, m_root_vnode->inode);
|
||||||
|
if (!parent_dir.isValid())
|
||||||
|
return false;
|
||||||
|
auto new_dir = base.fileSystem()->create_directory(parent_dir, p.basename(), mode, error);
|
||||||
|
if (new_dir.isValid()) {
|
||||||
|
error = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InodeIdentifier VFS::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error)
|
InodeIdentifier VFS::resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error)
|
||||||
|
|
|
@ -115,8 +115,8 @@ public:
|
||||||
|
|
||||||
RetainPtr<FileDescriptor> open(CharacterDevice&, int options);
|
RetainPtr<FileDescriptor> open(CharacterDevice&, int options);
|
||||||
RetainPtr<FileDescriptor> open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier());
|
RetainPtr<FileDescriptor> open(const String& path, int& error, int options = 0, InodeIdentifier base = InodeIdentifier());
|
||||||
RetainPtr<FileDescriptor> create(const String& path, InodeIdentifier base = InodeIdentifier());
|
RetainPtr<FileDescriptor> create(const String& path, InodeIdentifier base, int& error);
|
||||||
RetainPtr<FileDescriptor> mkdir(const String& path, InodeIdentifier base = InodeIdentifier());
|
bool mkdir(const String& path, mode_t mode, InodeIdentifier base, int& error);
|
||||||
|
|
||||||
bool touch(const String&path);
|
bool touch(const String&path);
|
||||||
|
|
||||||
|
@ -136,7 +136,6 @@ private:
|
||||||
bool is_vfs_root(InodeIdentifier) const;
|
bool is_vfs_root(InodeIdentifier) const;
|
||||||
|
|
||||||
void traverse_directory_inode(CoreInode&, Function<bool(const FS::DirectoryEntry&)>);
|
void traverse_directory_inode(CoreInode&, Function<bool(const FS::DirectoryEntry&)>);
|
||||||
InodeIdentifier resolve_path(const String& path, int& error, CoreInode& base, int options = 0);
|
|
||||||
InodeIdentifier resolve_path(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0);
|
InodeIdentifier resolve_path(const String& path, int& error, InodeIdentifier base = InodeIdentifier(), int options = 0);
|
||||||
InodeIdentifier resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error);
|
InodeIdentifier resolveSymbolicLink(InodeIdentifier base, InodeIdentifier symlinkInode, int& error);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue