Kernel/BAN: move unix time conversion to BAN and add stat to Shell
This commit is contained in:
parent
770f7716a0
commit
f8a2c60c8d
|
@ -0,0 +1,71 @@
|
||||||
|
#include <BAN/Time.h>
|
||||||
|
|
||||||
|
namespace BAN
|
||||||
|
{
|
||||||
|
|
||||||
|
static constexpr bool is_leap_year(uint64_t year)
|
||||||
|
{
|
||||||
|
if (year % 400 == 0)
|
||||||
|
return true;
|
||||||
|
if (year % 100 == 0)
|
||||||
|
return false;
|
||||||
|
if (year % 4 == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr uint64_t leap_days_since_epoch(const BAN::Time& time)
|
||||||
|
{
|
||||||
|
uint64_t leap_years = 0;
|
||||||
|
for (uint32_t year = 1970; year < time.year; year++)
|
||||||
|
if (is_leap_year(year))
|
||||||
|
leap_years++;
|
||||||
|
if (is_leap_year(time.year) && time.month >= 3)
|
||||||
|
leap_years++;
|
||||||
|
return leap_years;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr uint64_t month_days[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||||
|
|
||||||
|
uint64_t to_unix_time(const BAN::Time& time)
|
||||||
|
{
|
||||||
|
uint64_t years = time.year - 1970;
|
||||||
|
uint64_t days = years * 365 + month_days[time.month - 1] + leap_days_since_epoch(time) + (time.day - 1);
|
||||||
|
uint64_t hours = days * 24 + time.hour;
|
||||||
|
uint64_t minutes = hours * 60 + time.minute;
|
||||||
|
uint64_t seconds = minutes * 60 + time.second;
|
||||||
|
return seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::Time from_unix_time(uint64_t unix_time)
|
||||||
|
{
|
||||||
|
BAN::Time time {};
|
||||||
|
|
||||||
|
time.second = unix_time % 60; unix_time /= 60;
|
||||||
|
time.minute = unix_time % 60; unix_time /= 60;
|
||||||
|
time.hour = unix_time % 24; unix_time /= 24;
|
||||||
|
|
||||||
|
uint64_t total_days = unix_time;
|
||||||
|
|
||||||
|
time.week_day = (total_days + 4) % 7 + 1;
|
||||||
|
|
||||||
|
time.year = 1970;
|
||||||
|
while (total_days >= 365U + is_leap_year(time.year))
|
||||||
|
{
|
||||||
|
total_days -= 365U + is_leap_year(time.year);
|
||||||
|
time.year++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_leap_day = is_leap_year(time.year) && total_days == month_days[2];
|
||||||
|
bool had_leap_day = is_leap_year(time.year) && total_days > month_days[2];
|
||||||
|
|
||||||
|
for (time.month = 1; time.month < 12; time.month++)
|
||||||
|
if (total_days < month_days[time.month] + (is_leap_day || had_leap_day))
|
||||||
|
break;
|
||||||
|
|
||||||
|
time.day = total_days - month_days[time.month - 1] + !had_leap_day;
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ $(ARCH_FREEOBJS) \
|
||||||
BAN/Memory.o \
|
BAN/Memory.o \
|
||||||
BAN/String.o \
|
BAN/String.o \
|
||||||
BAN/StringView.o \
|
BAN/StringView.o \
|
||||||
|
BAN/Time.o \
|
||||||
|
|
||||||
HOSTEDOBJS=\
|
HOSTEDOBJS=\
|
||||||
$(ARCH_HOSTEDOBJS) \
|
$(ARCH_HOSTEDOBJS) \
|
||||||
|
|
|
@ -9,15 +9,18 @@ namespace BAN
|
||||||
|
|
||||||
struct Time
|
struct Time
|
||||||
{
|
{
|
||||||
uint8_t second;
|
uint32_t year;
|
||||||
uint8_t minute;
|
|
||||||
uint8_t hour;
|
|
||||||
uint8_t week_day;
|
|
||||||
uint8_t day;
|
|
||||||
uint8_t month;
|
uint8_t month;
|
||||||
int year;
|
uint8_t day;
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t minute;
|
||||||
|
uint8_t second;
|
||||||
|
uint8_t week_day;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint64_t to_unix_time(const BAN::Time&);
|
||||||
|
BAN::Time from_unix_time(uint64_t);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace BAN::Formatter
|
namespace BAN::Formatter
|
||||||
|
|
|
@ -6,6 +6,5 @@ namespace RTC
|
||||||
{
|
{
|
||||||
|
|
||||||
BAN::Time get_current_time();
|
BAN::Time get_current_time();
|
||||||
uint64_t get_unix_time();
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -334,7 +334,7 @@ namespace Kernel
|
||||||
if (error_or.error().get_error_code() != ENOENT)
|
if (error_or.error().get_error_code() != ENOENT)
|
||||||
return error_or.error();
|
return error_or.error();
|
||||||
|
|
||||||
uint64_t current_time = RTC::get_unix_time();
|
uint64_t current_time = BAN::to_unix_time(RTC::get_current_time());
|
||||||
|
|
||||||
Ext2::Inode ext2_inode;
|
Ext2::Inode ext2_inode;
|
||||||
ext2_inode.mode = mode;
|
ext2_inode.mode = mode;
|
||||||
|
|
|
@ -87,41 +87,4 @@ namespace RTC
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_leap_year(uint64_t year)
|
|
||||||
{
|
|
||||||
if (year % 400 == 0)
|
|
||||||
return true;
|
|
||||||
if (year % 100 == 0)
|
|
||||||
return false;
|
|
||||||
if (year % 4 == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t leap_days_since_epoch(const BAN::Time& time)
|
|
||||||
{
|
|
||||||
uint64_t leap_years = 0;
|
|
||||||
for (int year = 1970; year < time.year; year++)
|
|
||||||
if (is_leap_year(year))
|
|
||||||
leap_years++;
|
|
||||||
if (is_leap_year(time.year))
|
|
||||||
if (time.month >= 3 || (time.month == 2 && time.day == 29))
|
|
||||||
leap_years++;
|
|
||||||
return leap_years;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t get_unix_time()
|
|
||||||
{
|
|
||||||
auto time = get_current_time();
|
|
||||||
|
|
||||||
uint64_t month_days[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
|
||||||
|
|
||||||
uint64_t years = time.year - 1970;
|
|
||||||
uint64_t days = years * 365 + month_days[time.month - 1] + time.day + leap_days_since_epoch(time) - 1;
|
|
||||||
uint64_t hours = days * 24 + time.hour;
|
|
||||||
uint64_t minutes = hours * 60 + time.minute;
|
|
||||||
uint64_t seconds = minutes * 60 + time.second;
|
|
||||||
return seconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -425,6 +425,43 @@ argument_done:
|
||||||
}
|
}
|
||||||
TTY_PRINTLN("");
|
TTY_PRINTLN("");
|
||||||
}
|
}
|
||||||
|
else if (arguments.front() == "stat")
|
||||||
|
{
|
||||||
|
if (arguments.size() != 2)
|
||||||
|
return BAN::Error::from_c_string("usage: 'stat path'");
|
||||||
|
|
||||||
|
stat st;
|
||||||
|
TRY(Process::current()->stat(arguments[1], &st));
|
||||||
|
|
||||||
|
auto mode_string = [](mode_t mode)
|
||||||
|
{
|
||||||
|
static char buffer[11] {};
|
||||||
|
buffer[0] = (mode & Inode::Mode::IFDIR) ? 'd' : '-';
|
||||||
|
buffer[1] = (mode & Inode::Mode::IRUSR) ? 'r' : '-';
|
||||||
|
buffer[2] = (mode & Inode::Mode::IWUSR) ? 'w' : '-';
|
||||||
|
buffer[3] = (mode & Inode::Mode::IXUSR) ? 'x' : '-';
|
||||||
|
buffer[4] = (mode & Inode::Mode::IRGRP) ? 'r' : '-';
|
||||||
|
buffer[5] = (mode & Inode::Mode::IWGRP) ? 'w' : '-';
|
||||||
|
buffer[6] = (mode & Inode::Mode::IXGRP) ? 'x' : '-';
|
||||||
|
buffer[7] = (mode & Inode::Mode::IROTH) ? 'r' : '-';
|
||||||
|
buffer[8] = (mode & Inode::Mode::IWOTH) ? 'w' : '-';
|
||||||
|
buffer[9] = (mode & Inode::Mode::IXOTH) ? 'x' : '-';
|
||||||
|
return (const char*)buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* type =
|
||||||
|
(st.st_mode & Inode::Mode::IFREG) ? "regular file" :
|
||||||
|
(st.st_mode & Inode::Mode::IFDIR) ? "directory" :
|
||||||
|
"other";
|
||||||
|
|
||||||
|
TTY_PRINTLN(" File: {}", arguments[1]);
|
||||||
|
TTY_PRINTLN(" Size: {}\tBlocks: {}\tIO Block: {}\t {}", st.st_size, st.st_blocks, st.st_blksize, type);
|
||||||
|
TTY_PRINTLN("Device: {},{}\tInode: {}\tLinks: {}", st.st_dev, st.st_rdev, st.st_ino, st.st_nlink);
|
||||||
|
TTY_PRINTLN("Access: ({}/{})\tUid: {}\tGid: {}", st.st_mode, mode_string(st.st_mode), st.st_uid, st.st_gid);
|
||||||
|
TTY_PRINTLN("Access: {}", BAN::from_unix_time(st.st_atime));
|
||||||
|
TTY_PRINTLN("Modify: {}", BAN::from_unix_time(st.st_mtime));
|
||||||
|
TTY_PRINTLN("Change: {}", BAN::from_unix_time(st.st_ctime));
|
||||||
|
}
|
||||||
else if (arguments.front() == "cd")
|
else if (arguments.front() == "cd")
|
||||||
{
|
{
|
||||||
if (arguments.size() > 2)
|
if (arguments.size() > 2)
|
||||||
|
|
Loading…
Reference in New Issue