Compare commits

..

46 Commits

Author SHA1 Message Date
38f799ce39
libos: Remove some shared pointers and change them to owned/live on the stack
All checks were successful
continuous-integration/drone/pr Build is passing
2023-08-08 16:34:38 +02:00
fac7a68445
wind: Spawn a new client process after startup
Also, create the socket after dropping privileges.
2023-08-08 16:34:38 +02:00
fdd9f6103b
apps: Add gclient 2023-08-08 16:34:26 +02:00
6a74546a71
libos: Add os::LocalClient 2023-08-08 16:19:57 +02:00
b3cc53f7e9
libui: Change 'into' to 'onto' 2023-08-08 16:19:57 +02:00
361e57b17c
libui: Document ui::Font 2023-08-08 16:19:57 +02:00
dfee0981b8
libui+wind: Move some static variables inside functions 2023-08-08 16:19:57 +02:00
b0c905a33e
wind: Generate random windows on keypresses 2023-08-08 16:19:57 +02:00
4d1d4342ae
wind: Make sure windows have a minimum size to fit the titlebar 2023-08-08 16:19:56 +02:00
6404d01a5e
libui: Properly cut off the last drawn character if necessary 2023-08-08 16:19:56 +02:00
a510c58de0
libui: Add Rect::contains(Rect) 2023-08-08 16:19:56 +02:00
632252e1d1
libui: Render font characters properly with no spacing, matching the width calculations 2023-08-08 16:19:56 +02:00
db7dc09844
wind: Render an actual TGA mouse cursor 2023-08-08 16:19:56 +02:00
d142969eb0
wind: Add a close button to windows using a TGA icon 2023-08-08 16:19:55 +02:00
0e24e6a79a
libui: Add support for TGA image loading 2023-08-08 16:19:55 +02:00
d7fc3356e6
libui: Add an interface to fill a Canvas with an array of pixels 2023-08-08 16:19:55 +02:00
d1b31ab6aa
wind: Add window titlebars using ui::Font 2023-08-08 16:19:55 +02:00
e72a1a3697
libui: Add PSF font loading and rendering 2023-08-08 16:19:55 +02:00
26a61a6069
libui: Add Color::GRAY 2023-08-08 16:19:55 +02:00
f87952a615
libui: Rename Rect::absolute to normalized and add a new absolute function 2023-08-08 16:19:55 +02:00
b2037e978f
libluna: Add assignment operators to Buffer 2023-08-08 16:19:55 +02:00
78763b97f8
wind: Reorder drag sequence 2023-08-08 16:19:54 +02:00
5c3b5aae85
libui: Add Rect::relative 2023-08-08 16:19:54 +02:00
2261ffb31d
libui: Remove redundant statement 2023-08-08 16:19:54 +02:00
5343903e54
libui: Add getters for separate color values 2023-08-08 16:19:54 +02:00
ae7b712792
libui: Remove unnecessary stuff 2023-08-08 16:19:54 +02:00
6fdb245759
base: Remove startup items not necessary for GUI startup 2023-08-08 16:19:54 +02:00
0fe9b63f0e
libui+wind: (Draggable) windows 2023-08-08 16:19:54 +02:00
3dbe8418a1
wind: Create a local server object 2023-08-08 16:19:54 +02:00
c5900b7663
libos: Add a new LocalServer class for local domain sockets 2023-08-08 16:19:53 +02:00
0a06978fee
kernel: Support listening sockets in poll() 2023-08-08 16:19:53 +02:00
be99376307
base: Start wind on startup instead of the shell 2023-08-08 16:19:53 +02:00
a261603655
wind: Add a simple display server skeleton using libui
No client functionality yet, but it's a start.
2023-08-08 16:19:53 +02:00
a122ff133e
libui: Add a GUI and graphics library 2023-08-08 16:19:53 +02:00
adec709fe7
kernel: Fix negative movement in the PS/2 mouse driver 2023-08-08 16:19:52 +02:00
919c71ff85
README: More features
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 16:19:38 +02:00
1caa2c0888
Update README.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 16:04:10 +02:00
8748364b7e
ports: Add a binutils port =D
All checks were successful
continuous-integration/drone/push Build is passing
I can't believe the fact that there is a working gas and ld on Luna. At least, for a hello world program anyway :)

objdump seems to have some problems with stack size in some cases, but apart from that, no crashes.

And that can easily be solved with either more stack preallocation or stack resizing in the kernel on page faults.
2023-08-08 16:00:31 +02:00
49662b6069
tools: Calculate the needed fs size dynamically 2023-08-08 15:43:20 +02:00
d96ff92461
libc: Add borrowed strtod implementation 2023-08-08 15:17:25 +02:00
bfb76b5625
kernel: Properly expose block device sizes with the new metadata API 2023-08-08 15:17:08 +02:00
8c13513bf4
libc: Add strcoll()
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 14:40:14 +02:00
37e9b25b62
apps: Add touch
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 14:34:58 +02:00
a92077d311
kernel+libc: Add all variants of utime
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 14:14:35 +02:00
1481a4736a
tmpfs: Update mtime on writes
All checks were successful
continuous-integration/drone/push Build is passing
2023-08-08 13:36:25 +02:00
4195e7f206
kernel+libc+stat: Add support for file times
All checks were successful
continuous-integration/drone/push Build is passing
The modification time is not updated though.
2023-08-08 13:33:40 +02:00
27 changed files with 589 additions and 19 deletions

View File

@ -1,5 +1,5 @@
# Luna # Luna
A very basic POSIX-based operating system for personal computers, written in C++. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg)](https://drone.cloudapio.eu/apio/Luna) A simple POSIX-based operating system for personal computers, written in C++. [![Build Status](https://drone.cloudapio.eu/api/badges/apio/Luna/status.svg)](https://drone.cloudapio.eu/apio/Luna)
## Another UNIX clone? ## Another UNIX clone?
[Yes, another UNIX clone](https://wiki.osdev.org/User:Sortie/Yes_Another_Unix_Clone). [Yes, another UNIX clone](https://wiki.osdev.org/User:Sortie/Yes_Another_Unix_Clone).
@ -8,16 +8,18 @@ A very basic POSIX-based operating system for personal computers, written in C++
- x86_64-compatible lightweight [kernel](kernel/). - x86_64-compatible lightweight [kernel](kernel/).
- Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/). - Preemptive multitasking, with a round-robin [scheduler](kernel/src/thread/).
- [Virtual file system](kernel/src/fs/) with a simple [tmpfs](kernel/src/fs/tmpfs/) and read-only [ext2](kernel/src/fs/ext2/) support. - [Virtual file system](kernel/src/fs/) with a simple [tmpfs](kernel/src/fs/tmpfs/) and read-only [ext2](kernel/src/fs/ext2/) support.
- Can [load ELF programs](kernel/src/thread/ELF.cpp) from the file system as userspace tasks. - Can [load ELF programs](kernel/src/binfmt/ELF.cpp), [shebang scripts](kernel/src/binfmt/Script.cpp) or [arbitrary binary formats](kernel/src/binfmt/BinaryFormat.h) (registered through kernel modules, which are not supported yet =D).
- Boots from an [ext2](apps/preinit.cpp) root filesystem (a bit slow for now). - Boots from an [ext2](apps/preinit.cpp) root filesystem (a bit slow for now).
- [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be mostly POSIX-compatible. - [System call](kernel/src/sys/) interface and [C Library](libc/), aiming to be almost POSIX-compatible.
- Support for [several third-party programs](ports/), including the [GNU binutils](ports/binutils/PACKAGE) suite of utilities.
- POSIX [signal](libc/src/signal.cpp) support. - POSIX [signal](libc/src/signal.cpp) support.
- Designed to be [portable](kernel/src/arch), no need to be restricted to x86_64. - Designed to be [portable](kernel/src/arch), no need to be restricted to x86_64.
- Designed around [UTF-8](libluna/include/luna/Utf8.h). - Everything is [UTF-8](libluna/include/luna/Utf8.h).
- [UNIX local domain sockets](kernel/src/net/UnixSocket.cpp), allowing for local IPC. - [UNIX local domain sockets](kernel/src/net/UnixSocket.cpp), allowing for local IPC.
- [POSIX shared memory](libc/include/sys/mman.h) support.
- Environment-agnostic [utility library](libluna/), which can be used in both kernel and userspace. - Environment-agnostic [utility library](libluna/), which can be used in both kernel and userspace.
- Return-oriented [error propagation](libluna/include/luna/Result.h), inspired by Rust and SerenityOS. - Return-oriented [error propagation](libluna/include/luna/Result.h), inspired by Rust and SerenityOS. No exceptions here :).
- Build system uses [CMake](CMakeLists.txt). - An extensive set of [standard Unix utilities](apps/), from [ls](apps/ls.cpp) to [uname](apps/uname.cpp) to [base64](apps/base64.cpp). Written in modern C++ and very small amounts of code, using Luna's practical [OS library](libos/).
## Setup ## Setup

View File

@ -46,4 +46,5 @@ luna_app(socket-test.cpp socket-test)
luna_app(socket-client.cpp socket-client) luna_app(socket-client.cpp socket-client)
luna_app(input.cpp input) luna_app(input.cpp input)
luna_app(shmem-test.cpp shmem-test) luna_app(shmem-test.cpp shmem-test)
luna_app(touch.cpp touch)
luna_app(gclient.cpp gclient) luna_app(gclient.cpp gclient)

View File

@ -2,7 +2,7 @@
#include <os/FileSystem.h> #include <os/FileSystem.h>
#include <os/Mode.h> #include <os/Mode.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <time.h>
static const char* file_type(mode_t mode) static const char* file_type(mode_t mode)
{ {
@ -36,10 +36,20 @@ Result<int> luna_main(int argc, char** argv)
char buf[11]; char buf[11];
os::format_mode(st.st_mode, buf); os::format_mode(st.st_mode, buf);
printf(" File: %s\n", path.chars()); char atime[256];
printf(" Size: %zu (%s)\n", st.st_size, file_type(st.st_mode)); strftime(atime, sizeof(atime), "%Y-%m-%d %H:%M:%S", gmtime(&st.st_atim.tv_sec));
printf("Inode: %lu Links: %lu\n", st.st_ino, st.st_nlink); char mtime[256];
printf(" Mode: (%#o/%s) UID: %u GID: %u\n", st.st_mode & ~S_IFMT, buf, st.st_uid, st.st_gid); strftime(mtime, sizeof(mtime), "%Y-%m-%d %H:%M:%S", gmtime(&st.st_mtim.tv_sec));
char ctime[256];
strftime(ctime, sizeof(ctime), "%Y-%m-%d %H:%M:%S", gmtime(&st.st_ctim.tv_sec));
printf(" File: %s\n", path.chars());
printf(" Size: %zu (%s)\n", st.st_size, file_type(st.st_mode));
printf(" Inode: %lu Links: %lu\n", st.st_ino, st.st_nlink);
printf(" Mode: (%#o/%s) UID: %u GID: %u\n", st.st_mode & ~S_IFMT, buf, st.st_uid, st.st_gid);
printf("Access: %s.%.9ld\n", atime, st.st_atim.tv_nsec);
printf("Modify: %s.%.9ld\n", mtime, st.st_mtim.tv_nsec);
printf("Change: %s.%.9ld\n", ctime, st.st_ctim.tv_nsec);
return 0; return 0;
} }

47
apps/touch.cpp Normal file
View File

@ -0,0 +1,47 @@
#include <errno.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <sys/stat.h>
Result<int> luna_main(int argc, char** argv)
{
Vector<StringView> files;
bool only_atime { false };
bool only_mtime { false };
bool no_create { false };
bool no_dereference { false };
os::ArgumentParser parser;
parser.add_description("Update the access and modification times of files."_sv);
parser.add_system_program_info("touch"_sv);
parser.set_vector_argument(files, "files", true);
parser.add_switch_argument(only_atime, 'a', ""_sv, "change only the access time"_sv);
parser.add_switch_argument(no_create, 'c', "no-create"_sv, "do not create new files"_sv);
parser.add_switch_argument(no_dereference, 'h', "no-dereference"_sv, "do not follow symbolic links"_sv);
parser.add_switch_argument(only_mtime, 'm', ""_sv, "change only the modification time"_sv);
TRY(parser.parse(argc, argv));
if (only_atime && only_mtime)
{
os::eprintln("%s: only one of -a and -m can be specified.", argv[0]);
parser.short_usage(argv[0]);
}
struct timespec times[2] = {
{ .tv_sec = 0, .tv_nsec = only_mtime ? UTIME_OMIT : UTIME_NOW },
{ .tv_sec = 0, .tv_nsec = only_atime ? UTIME_OMIT : UTIME_NOW },
};
for (auto& filename : files)
{
SharedPtr<os::File> file;
if (no_create) file = TRY(os::File::open(filename, os::File::ReadOnly));
else
file = TRY(os::File::open_or_create(filename, os::File::ReadOnly));
if (futimens(file->fd(), times, no_dereference ? AT_SYMLINK_NOFOLLOW : 0) < 0) return err(errno);
}
return 0;
}

View File

@ -57,6 +57,9 @@ namespace Ext2
inode->m_metadata.nlinks = inode->m_raw_inode.nlinks; inode->m_metadata.nlinks = inode->m_raw_inode.nlinks;
inode->m_metadata.uid = inode->m_raw_inode.uid; inode->m_metadata.uid = inode->m_raw_inode.uid;
inode->m_metadata.gid = inode->m_raw_inode.gid; inode->m_metadata.gid = inode->m_raw_inode.gid;
inode->m_metadata.atime = { .tv_sec = inode->m_raw_inode.atime, .tv_nsec = 0 };
inode->m_metadata.mtime = { .tv_sec = inode->m_raw_inode.mtime, .tv_nsec = 0 };
inode->m_metadata.ctime = { .tv_sec = inode->m_raw_inode.create_time, .tv_nsec = 0 };
#ifdef EXT2_DEBUG #ifdef EXT2_DEBUG
kdbgln("ext2: Read inode %lu with mode %#x (%#x + %#o), size %lu", inum, inode->m_raw_inode.mode, kdbgln("ext2: Read inode %lu with mode %#x (%#x + %#o), size %lu", inum, inode->m_raw_inode.mode,

View File

@ -1,4 +1,5 @@
#include "fs/tmpfs/FileSystem.h" #include "fs/tmpfs/FileSystem.h"
#include "arch/Timer.h"
#include "fs/devices/DeviceRegistry.h" #include "fs/devices/DeviceRegistry.h"
#include "fs/tmpfs/Inode.h" #include "fs/tmpfs/Inode.h"
#include <luna/Alloc.h> #include <luna/Alloc.h>
@ -26,6 +27,7 @@ namespace TmpFS
inode->set_fs(*this, {}); inode->set_fs(*this, {});
inode->set_inode_number(m_next_inode_number++, {}); inode->set_inode_number(m_next_inode_number++, {});
inode->m_metadata.mode = mode; inode->m_metadata.mode = mode;
inode->m_metadata.atime = inode->m_metadata.ctime = inode->m_metadata.mtime = *Timer::realtime_clock();
return (SharedPtr<VFS::Inode>)inode; return (SharedPtr<VFS::Inode>)inode;
} }
@ -35,6 +37,7 @@ namespace TmpFS
inode->set_fs(*this, {}); inode->set_fs(*this, {});
TRY(inode->set_link(link, {})); TRY(inode->set_link(link, {}));
inode->set_inode_number(m_next_inode_number++, {}); inode->set_inode_number(m_next_inode_number++, {});
inode->m_metadata.atime = inode->m_metadata.ctime = inode->m_metadata.mtime = *Timer::realtime_clock();
return (SharedPtr<VFS::Inode>)inode; return (SharedPtr<VFS::Inode>)inode;
} }
@ -49,6 +52,7 @@ namespace TmpFS
inode->set_fs(*this, {}); inode->set_fs(*this, {});
inode->set_inode_number(m_next_inode_number++, {}); inode->set_inode_number(m_next_inode_number++, {});
inode->m_metadata.mode = mode; inode->m_metadata.mode = mode;
inode->m_metadata.atime = inode->m_metadata.ctime = inode->m_metadata.mtime = *Timer::realtime_clock();
return (SharedPtr<VFS::Inode>)inode; return (SharedPtr<VFS::Inode>)inode;
} }
@ -65,6 +69,8 @@ namespace TmpFS
// device ID atm. // device ID atm.
inode->set_device_id(luna_dev_makedev(major, minor), {}); inode->set_device_id(luna_dev_makedev(major, minor), {});
inode->m_metadata.mode = mode; inode->m_metadata.mode = mode;
inode->m_metadata.atime = inode->m_metadata.ctime = inode->m_metadata.mtime = *Timer::realtime_clock();
inode->m_metadata.size = device->size();
return (SharedPtr<VFS::Inode>)inode; return (SharedPtr<VFS::Inode>)inode;
} }

View File

@ -45,6 +45,8 @@ namespace TmpFS
inode->did_link(); inode->did_link();
m_metadata.mtime = *Timer::realtime_clock();
return {}; return {};
} }
@ -61,6 +63,8 @@ namespace TmpFS
inode->did_unlink(); inode->did_unlink();
m_metadata.mtime = *Timer::realtime_clock();
return {}; return {};
} }
@ -114,6 +118,8 @@ namespace TmpFS
m_metadata.size = m_data_buffer.size(); m_metadata.size = m_data_buffer.size();
m_metadata.mtime = *Timer::realtime_clock();
return length; return length;
} }
@ -127,6 +133,8 @@ namespace TmpFS
m_metadata.size = m_data_buffer.size(); m_metadata.size = m_data_buffer.size();
m_metadata.mtime = *Timer::realtime_clock();
return {}; return {};
} }

View File

@ -4,9 +4,11 @@
#include "memory/MemoryManager.h" #include "memory/MemoryManager.h"
#include "sys/Syscall.h" #include "sys/Syscall.h"
#include "thread/Scheduler.h" #include "thread/Scheduler.h"
#include <bits/atfile.h>
#include <bits/fcntl.h> #include <bits/fcntl.h>
#include <bits/open-flags.h> #include <bits/open-flags.h>
#include <bits/seek.h> #include <bits/seek.h>
#include <bits/utime.h>
#include <luna/SafeArithmetic.h> #include <luna/SafeArithmetic.h>
#include <sys/types.h> #include <sys/types.h>
@ -262,3 +264,58 @@ Result<u64> sys_ftruncate(Registers*, SyscallArgs args)
return 0; return 0;
} }
Result<u64> sys_utimensat(Registers*, SyscallArgs args)
{
int dirfd = (int)args[0];
auto path = TRY(MemoryManager::strdup_from_user(args[1]));
const auto* times = (const struct timespec*)args[2];
int flags = (int)args[3];
auto* current = Scheduler::current();
auto inode = TRY(current->resolve_atfile(dirfd, path, flags & AT_EMPTY_PATH, !(flags & AT_SYMLINK_NOFOLLOW)));
struct timespec ktimes[2];
ktimes[0].tv_sec = ktimes[1].tv_sec = 0;
ktimes[0].tv_nsec = ktimes[1].tv_nsec = UTIME_NOW;
if (times && !MemoryManager::copy_from_user(times, ktimes, sizeof(ktimes))) return err(EFAULT);
// No permission checks are performed, since no actual modification is done, but the above checks are still
// performed.
if (ktimes[0].tv_nsec == UTIME_OMIT && ktimes[1].tv_nsec == UTIME_OMIT) return 0;
bool allow_write_access = ktimes[0].tv_nsec == UTIME_NOW && ktimes[1].tv_nsec == UTIME_NOW;
if (allow_write_access)
{
if (!VFS::can_write(inode, current->auth) && current->auth.euid != inode->metadata().uid &&
current->auth.euid != 0)
return err(EACCES);
}
else if (current->auth.euid != inode->metadata().uid && current->auth.euid != 0)
return err(EPERM);
auto metadata = inode->metadata();
if (ktimes[0].tv_nsec != UTIME_OMIT)
{
if (ktimes[0].tv_nsec == UTIME_NOW) metadata.atime = *Timer::realtime_clock();
else
{
if (ktimes[0].tv_nsec < 0 || ktimes[0].tv_nsec > 999'999'999) return err(EINVAL);
metadata.atime = ktimes[0];
}
}
if (ktimes[1].tv_nsec != UTIME_OMIT)
{
if (ktimes[1].tv_nsec == UTIME_NOW) metadata.mtime = *Timer::realtime_clock();
else
{
if (ktimes[1].tv_nsec < 0 || ktimes[1].tv_nsec > 999'999'999) return err(EINVAL);
metadata.mtime = ktimes[1];
}
}
TRY(inode->set_metadata(metadata));
return 0;
}

View File

@ -48,6 +48,9 @@ Result<u64> sys_fstatat(Registers*, SyscallArgs args)
kstat.st_size = metadata.size; kstat.st_size = metadata.size;
kstat.st_dev = inode->fs() ? inode->fs()->host_device_id() : 0; kstat.st_dev = inode->fs() ? inode->fs()->host_device_id() : 0;
kstat.st_rdev = metadata.devid; kstat.st_rdev = metadata.devid;
kstat.st_atim = metadata.atime;
kstat.st_mtim = metadata.mtime;
kstat.st_ctim = metadata.ctime;
if (!MemoryManager::copy_to_user_typed(st, &kstat)) return err(EFAULT); if (!MemoryManager::copy_to_user_typed(st, &kstat)) return err(EFAULT);

View File

@ -23,6 +23,8 @@ set(SOURCES
src/scanf.cpp src/scanf.cpp
src/signal.cpp src/signal.cpp
src/termios.cpp src/termios.cpp
src/utime.cpp
src/strtod.cpp
src/sys/stat.cpp src/sys/stat.cpp
src/sys/mman.cpp src/sys/mman.cpp
src/sys/wait.cpp src/sys/wait.cpp

View File

@ -3,6 +3,7 @@
#ifndef _BITS_STRUCT_STAT_H #ifndef _BITS_STRUCT_STAT_H
#define _BITS_STRUCT_STAT_H #define _BITS_STRUCT_STAT_H
#include <bits/timespec.h>
#include <sys/types.h> #include <sys/types.h>
struct stat struct stat
@ -15,10 +16,13 @@ struct stat
gid_t st_gid; gid_t st_gid;
off_t st_size; off_t st_size;
dev_t st_rdev; dev_t st_rdev;
// FIXME: Actually fill these fields in. struct timespec st_atim;
time_t st_atime; struct timespec st_mtim;
time_t st_mtime; struct timespec st_ctim;
time_t st_ctime;
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
}; };
#endif #endif

View File

@ -0,0 +1,9 @@
/* bits/utime.h: Definitions for UTIME_NOW and UTIME_OMIT. */
#ifndef _BITS_UTIME_H
#define _BITS_UTIME_H
#define UTIME_NOW -1
#define UTIME_OMIT -2
#endif

View File

@ -84,9 +84,11 @@ extern "C"
/* Parse a decimal integer from a string. */ /* Parse a decimal integer from a string. */
long long atoll(const char* s); long long atoll(const char* s);
double atof(const char*); /* Parse a floating-point number from a string. */
double atof(const char* str);
double strtod(const char*, char**); /* Parse a floating-point number from a string. */
double strtod(const char* str, char** endptr);
/* Parse an integer of the specified base from a string, storing the first non-number character in endptr if /* Parse an integer of the specified base from a string, storing the first non-number character in endptr if
* nonnull. */ * nonnull. */

View File

@ -95,6 +95,9 @@ extern "C"
/* Compare two fixed-size null-terminated strings, ignoring case. */ /* Compare two fixed-size null-terminated strings, ignoring case. */
int strncasecmp(const char* a, const char* b, size_t max); int strncasecmp(const char* a, const char* b, size_t max);
/* Compare two null-terminated strings according to the current locale. */
int strcoll(const char* a, const char* b);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -5,6 +5,8 @@
#include <bits/modes.h> #include <bits/modes.h>
#include <bits/struct_stat.h> #include <bits/struct_stat.h>
#include <bits/timespec.h>
#include <bits/utime.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef __cplusplus #ifdef __cplusplus
@ -41,6 +43,12 @@ extern "C"
/* Change the process's file creation mask. */ /* Change the process's file creation mask. */
mode_t umask(mode_t mask); mode_t umask(mode_t mask);
/* Change a file's access and modification timestamps, with nanosecond precision. */
int utimensat(int dirfd, const char* path, const struct timespec times[2], int flags);
/* Change a file's access and modification timestamps, with nanosecond precision. */
int futimens(int fd, const struct timespec times[2], int flags);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -16,6 +16,15 @@ extern "C"
/* Get the current time of day. */ /* Get the current time of day. */
__deprecated int gettimeofday(struct timeval* tp, void* timezone); __deprecated int gettimeofday(struct timeval* tp, void* timezone);
/* Change a file's access and modification timestamps, with microsecond precision. */
int utimes(const char* path, const struct timeval buf[2]);
/* Change a file descriptor's access and modification timestamps, with microsecond precision. */
int futimes(int fd, const struct timeval buf[2]);
/* Change a symlink's access and modification timestamps, with microsecond precision. */
int lutimes(const char* path, const struct timeval buf[2]);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

26
libc/include/utime.h Normal file
View File

@ -0,0 +1,26 @@
/* utime.h: The utime function. */
#ifndef _UTIME_H
#define _UTIME_H
#include <sys/types.h>
struct utimbuf
{
time_t actime;
time_t modtime;
};
#ifdef __cplusplus
extern "C"
{
#endif
/* Change a file's access and modification timestamps. */
int utime(const char* path, const struct utimbuf* buf);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -297,4 +297,9 @@ extern "C"
if (errno != EEXIST) return -1; if (errno != EEXIST) return -1;
} }
} }
double atof(const char* str)
{
return strtod(str, nullptr);
}
} }

View File

@ -9,6 +9,12 @@ extern "C"
extern "C++" const char* error_string(int); extern "C++" const char* error_string(int);
int strcoll(const char* a, const char* b)
{
// In the POSIX or C locales strcoll() is equivalent to strcmp().
return strcmp(a, b);
}
char* strerror(int errnum) char* strerror(int errnum)
{ {
return const_cast<char*>(error_string(errnum)); return const_cast<char*>(error_string(errnum));

141
libc/src/strtod.cpp Normal file
View File

@ -0,0 +1,141 @@
/* vi:set ts=8 sts=4 sw=4: */
/*
* strtod implementation.
* author: Yasuhiro Matsumoto
* license: public domain
*
* source from https://gist.github.com/mattn/1890186
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char* skipwhite(const char* q)
{
const char* p = q;
while (isspace(*p)) ++p;
return p;
}
extern "C"
{
double strtod(const char* str, char** end)
{
double d = 0.0;
int sign;
int n = 0;
const char *p, *a;
a = p = str;
p = skipwhite(p);
/* decimal part */
sign = 1;
if (*p == '-')
{
sign = -1;
++p;
}
else if (*p == '+')
++p;
if (isdigit(*p))
{
d = (double)(*p++ - '0');
while (*p && isdigit(*p))
{
d = d * 10.0 + (double)(*p - '0');
++p;
++n;
}
a = p;
}
else if (*p != '.')
goto done;
d *= sign;
/* fraction part */
if (*p == '.')
{
double f = 0.0;
double base = 0.1;
++p;
if (isdigit(*p))
{
while (*p && isdigit(*p))
{
f += base * (*p - '0');
base /= 10.0;
++p;
++n;
}
}
d += f * sign;
a = p;
}
/* exponential part */
if ((*p == 'E') || (*p == 'e'))
{
int e = 0;
++p;
sign = 1;
if (*p == '-')
{
sign = -1;
++p;
}
else if (*p == '+')
++p;
if (isdigit(*p))
{
while (*p == '0') ++p;
if (*p == '\0') --p;
e = (int)(*p++ - '0');
while (*p && isdigit(*p))
{
e = e * 10 + (int)(*p - '0');
++p;
}
e *= sign;
}
else if (!isdigit(*(a - 1)))
{
a = str;
goto done;
}
else if (*p == 0)
goto done;
if (d == 2.2250738585072011 && e == -308)
{
d = 0.0;
a = p;
errno = ERANGE;
goto done;
}
if (d == 2.2250738585072012 && e <= -308)
{
d *= 1.0e-308;
a = p;
goto done;
}
d *= __builtin_powi(10.0, e);
a = p;
}
else if (p > str && !isdigit(*(p - 1)))
{
a = str;
goto done;
}
done:
if (end) *end = const_cast<char*>(a);
return d;
}
}

View File

@ -52,4 +52,15 @@ extern "C"
{ {
return (mode_t)syscall(SYS_umask, mask); return (mode_t)syscall(SYS_umask, mask);
} }
int utimensat(int dirfd, const char* path, const struct timespec* times, int flags)
{
long rc = syscall(SYS_utimensat, dirfd, path, times, flags);
__errno_return(rc, int);
}
int futimens(int fd, const struct timespec* times, int flags)
{
return utimensat(fd, "", times, flags | AT_EMPTY_PATH);
}
} }

55
libc/src/utime.cpp Normal file
View File

@ -0,0 +1,55 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <utime.h>
extern "C"
{
int utime(const char* path, const struct utimbuf* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, 0);
struct timespec times[2] = {
{ .tv_sec = buf->actime, .tv_nsec = 0 },
{ .tv_sec = buf->modtime, .tv_nsec = 0 },
};
return utimensat(AT_FDCWD, path, times, 0);
}
int utimes(const char* path, const struct timeval* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, 0);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(AT_FDCWD, path, times, 0);
}
int futimes(int fd, const struct timeval* buf)
{
if (!buf) return utimensat(fd, "", nullptr, AT_EMPTY_PATH);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(fd, "", times, AT_EMPTY_PATH);
}
int lutimes(const char* path, const struct timeval* buf)
{
if (!buf) return utimensat(AT_FDCWD, path, nullptr, AT_SYMLINK_NOFOLLOW);
struct timespec times[2] = {
{ .tv_sec = buf[0].tv_sec, .tv_nsec = buf[0].tv_usec * 1000 },
{ .tv_sec = buf[1].tv_sec, .tv_nsec = buf[1].tv_usec * 1000 },
};
return utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
}
}

View File

@ -8,7 +8,7 @@
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \ _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \ _e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask) _e(setpgid) _e(isatty) \
_e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \ _e(getpgid) _e(socket) _e(bind) _e(connect) _e(listen) _e(accept) _e(poll) _e(msync) \
_e(truncate) _e(ftruncate) _e(truncate) _e(ftruncate) _e(utimensat)
enum Syscalls enum Syscalls
{ {

View File

@ -12,6 +12,7 @@ Try to keep this list in alphabetical order.
Name | Version | Description | URL Name | Version | Description | URL
---|---|--- | --- ---|---|--- | ---
bc | 6.6.0 | An implementation of the POSIX bc calculator | https://github.com/gavinhoward/bc bc | 6.6.0 | An implementation of the POSIX bc calculator | https://github.com/gavinhoward/bc
binutils | 2.39 | The GNU suite of binary utilities | https://www.gnu.org/software/binutils
minitar | 1.7.5 | Tiny and easy-to-use C library to read/write tar archives | https://git.cloudapio.eu/apio/minitar minitar | 1.7.5 | Tiny and easy-to-use C library to read/write tar archives | https://git.cloudapio.eu/apio/minitar
nasm | 2.16.01 | An assembler for the x86 CPU architecture | https://nasm.us nasm | 2.16.01 | An assembler for the x86 CPU architecture | https://nasm.us

30
ports/binutils/PACKAGE Normal file
View File

@ -0,0 +1,30 @@
# Basic information
name="binutils"
version="2.39"
# Download options
format="tar"
url="https://ftp.gnu.org/gnu/binutils/binutils-$version.tar.gz"
output="binutils-$version.tar.gz"
sha256sum="d12ea6f239f1ffe3533ea11ad6e224ffcb89eb5d01bbea589e9158780fa11f10"
# Build instructions
default_build_make=true
do_patch()
{
patch -ui $portdir/binutils.patch -p 1 -d $srcdir/..
}
do_configure()
{
$srcdir/configure --host=$LUNA_ARCH-luna --disable-nls --disable-werror --enable-warn-rwx-segments=no --prefix=/usr --enable-gold=no --enable-ld=yes --enable-gprofng=no
}
do_install()
{
make install
cd $installdir/usr/bin
$LUNA_ARCH-luna-strip size objdump ar strings ranlib objcopy addr2line readelf elfedit nm strip c++filt as gprof ld.bfd ld
}

View File

@ -0,0 +1,117 @@
diff --color -rN -u binutils-2.39/bfd/config.bfd build/binutils-2.39/bfd/config.bfd
--- a/binutils-2.39/bfd/config.bfd 2022-01-22 13:14:07.000000000 +0100
+++ b/binutils-2.39/bfd/config.bfd 2022-10-01 22:12:16.914033792 +0200
@@ -651,6 +651,11 @@
targ_selvecs="iamcu_elf32_vec i386_pei_vec"
targ64_selvecs="x86_64_elf64_vec x86_64_elf32_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec"
;;
+ i[3-7]86-*-luna*)
+ targ_defvec=i386_elf32_vec
+ targ_selvecs=
+ targ64_selvecs=x86_64_elf64_vec
+ ;;
i[3-7]86-*-redox*)
targ_defvec=i386_elf32_vec
targ_selvecs=
@@ -706,6 +711,11 @@
targ_selvecs="i386_elf32_vec iamcu_elf32_vec x86_64_elf32_vec i386_pei_vec x86_64_pe_vec x86_64_pei_vec l1om_elf64_vec k1om_elf64_vec"
want64=true
;;
+ x86_64-*-luna*)
+ targ_defvec=x86_64_elf64_vec
+ targ_selvecs=i386_elf32_vec
+ want64=true
+ ;;
x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin)
targ_defvec=x86_64_pe_vec
targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec l1om_elf64_vec k1om_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec"
diff --color -rN -u binutils-2.39/gas/configure.tgt build/binutils-2.39/gas/configure.tgt
--- a/binutils-2.39/gas/configure.tgt 2022-01-22 13:14:08.000000000 +0100
+++ b/binutils-2.39/gas/configure.tgt 2022-10-01 22:12.39.115093972 +0200
@@ -238,6 +238,7 @@
x86_64*-linux-gnux32) arch=x86_64:32 ;;
esac ;;
i386-*-lynxos*) fmt=elf em=lynx ;;
+ i386-*-luna*) fmt=elf em=gnu ;;
i386-*-redox*) fmt=elf ;;
i386-*-solaris*) fmt=elf em=solaris ;;
i386-*-freebsd* \
diff --color -rN -u binutils-2.39/ld/configure.tgt build/binutils-2.39/ld/configure.tgt
--- a/binutils-2.39/ld/configure.tgt 2022-01-22 15:19:36.000000000 +0100
+++ b/binutils-2.39/ld/configure.tgt 2022-10-01 22:15:04.853571062 +0200
@@ -329,6 +329,11 @@
targ64_extra_emuls="elf_x86_64 elf32_x86_64 elf_l1om elf_k1om"
targ64_extra_libpath="elf_x86_64 elf32_x86_64"
;;
+i[3-7]86-*-luna*)
+ targ_emul=elf_i386_luna
+ targ_extra_emuls=elf_i386
+ targ64_extra_emuls="elf_x86_64_luna elf_x86_64"
+ ;;
i[3-7]86-*-redox*) targ_emul=elf_i386
targ_extra_emuls=elf_x86_64
;;
@@ -967,6 +972,10 @@
targ_extra_libpath="elf_i386 elf32_x86_64 elf_l1om elf_k1om"
tdir_elf_i386=`echo ${targ_alias} | sed -e 's/x86_64/i386/'`
;;
+x86_64-*-luna*)
+ targ_emul=elf_x86_64_luna
+ targ_extra_emuls="elf_i386_luna elf_x86_64 elf_i386"
+ ;;
x86_64-*-redox*) targ_emul=elf_x86_64
targ_extra_emuls=elf_i386
;;
diff --color -rN -u binutils-2.39/ld/emulparams/elf_i386_luna.sh build/binutils-2.39/ld/emulparams/elf_i386_luna.sh
--- a/dev/null 1970-01-01 01:00:00.000000000 +0100
+++ b/binutils-2.39/ld/emulparams/elf_i386_luna.sh 2022-10-01 21:52:12.394068335 +0200
@@ -0,0 +1,3 @@
+source_sh ${srcdir}/emulparams/elf_i386.sh
+TEXT_START_ADDR=0x08000000
+MAXPAGESIZE=0x1000
\ No newline at end of file
diff --color -rN -u binutils-2.39/ld/emulparams/elf_x86_64_luna.sh build/binutils-2.39/ld/emulparams/elf_x86_64_luna.sh
--- a/dev/null 1970-01-01 01:00:00.000000000 +0100
+++ b/binutils-2.39/ld/emulparams/elf_x86_64_luna.sh 2022-10-01 21:53:00.411200592 +0200
@@ -0,0 +1,2 @@
+source_sh ${srcdir}/emulparams/elf_x86_64.sh
+MAXPAGESIZE=0x1000
\ No newline at end of file
diff --color -rN -u binutils-2.39/ld/Makefile.am build/binutils-2.39/ld/Makefile.am
--- a/binutils-2.39/ld/Makefile.am 2022-01-22 13:14:09.000000000 +0100
+++ b/binutils-2.39/ld/Makefile.am 2022-10-01 22:18:02.660263017 +0200
@@ -278,6 +278,7 @@
eelf32xtensa.c \
eelf32z80.c \
eelf_i386.c \
+ eelf_i386_luna.c \
eelf_i386_be.c \
eelf_i386_fbsd.c \
eelf_i386_haiku.c \
@@ -464,6 +465,7 @@
eelf_x86_64_fbsd.c \
eelf_x86_64_haiku.c \
eelf_x86_64_sol2.c \
+ eelf_x86_64_luna.c \
ehppa64linux.c \
ei386pep.c \
emmo.c
diff --color -rN -u binutils-2.39/ld/Makefile.in build/binutils-2.39/ld/Makefile.in
--- a/binutils-2.39/ld/Makefile.in 2022-02-09 12:49:03.000000000 +0100
+++ b/binutils-2.39/ld/Makefile.in 2022-10-01 22:17:46.740196925 +0200
@@ -769,6 +769,7 @@
eelf32xtensa.c \
eelf32z80.c \
eelf_i386.c \
+ eelf_i386_luna.c \
eelf_i386_be.c \
eelf_i386_fbsd.c \
eelf_i386_haiku.c \
@@ -954,6 +955,7 @@
eelf_x86_64_fbsd.c \
eelf_x86_64_haiku.c \
eelf_x86_64_sol2.c \
+ eelf_x86_64_luna.c \
ehppa64linux.c \
ei386pep.c \
emmo.c

View File

@ -7,6 +7,10 @@ cd $LUNA_ROOT
fakeroot -u -s $LUNA_ROOT/.fakeroot -- tools/install.sh fakeroot -u -s $LUNA_ROOT/.fakeroot -- tools/install.sh
fakeroot -u -i $LUNA_ROOT/.fakeroot -- genext2fs -d base -B 4096 -b 8192 -L luna-rootfs -N 2048 build/ext2fs.bin disk_space=$(du -s base | awk '{ print $1 }')
min_blocks=$(($disk_space / 4)) # This is just the blocks needed for all the files in the file system: this excludes space for the inode table, block group descriptors, etc.
blocks=$(($min_blocks + 1024)) # This is the actual number of blocks we're using.
fakeroot -u -i $LUNA_ROOT/.fakeroot -- genext2fs -d base -B 4096 -b $blocks -L luna-rootfs -N 1024 build/ext2fs.bin
mkbootimg luna.json Luna.iso mkbootimg luna.json Luna.iso