Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@ UPROGS=\
$U/_logstress\
$U/_forphan\
$U/_dorphan\
$U/_date\
$U/_birthday\

$U/_birthday: $U/birthday.o $U/time.o $(ULIB)
$(LD) $(LDFLAGS) -T $U/user.ld -o $U/_birthday $U/birthday.o $U/time.o $(ULIB)

$U/_date: $U/date.o $U/time.o $(ULIB)
$(LD) $(LDFLAGS) -T $U/user.ld -o $U/_date $U/date.o $U/time.o $(ULIB)

fs.img: mkfs/mkfs README.md $(UPROGS)
mkfs/mkfs fs.img README.md $(UPROGS)
Expand Down
31 changes: 31 additions & 0 deletions docs/birthday-date.md

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would maybe try to make the .md file more organized and easy to read

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---- FogOSv2 Birthday, Date, Time Help Guide ----
-- Running --
Run make, make qemu.

-- Makefile --
Add 'birthday' and 'date' to UPROGS.
Build 'birthday' and 'date' with 'time' object.

-- Kernel Activity --
Clock is a necessary system call.

-- Birthday --
birthday | birthday with no flags. If the birthday is set, then it will tell the user "happy
happy", otherwise it will tell the user not yet!
birthday '-s' [MM/DD] | birthday with -s flag will set the birthday. Must be in MM/DD format
where both are integers.

-- Date --
date | only command for date. This will return the date in format: MMM DD HH:MM:SS PDT YYYY
Note: MMM is a string. The rest are integers besides PDT.

-- Time --
time.c and time.h are required for date and time to work. Time is not a usable command.

-- Testing --
To test, try:
1. Calling 'birthday' before it is set.
2. Setting 'birthday' with parameters M/DD.
3. Setting 'birthday' with an impossible date.
4. Setting 'birthday' with today's date and calling it.
5. Setting 'birthday' with your birthday and calling it.
3 changes: 3 additions & 0 deletions kernel/memlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@
// TRAPFRAME (p->trapframe, used by the trampoline)
// TRAMPOLINE (the same page as in the kernel)
#define TRAPFRAME (TRAMPOLINE - PGSIZE)

// goldfish real time clock memory adress
#define GOLD_RTC 0x101000
2 changes: 2 additions & 0 deletions kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ extern uint64 sys_unlink(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_clock(void);

// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
Expand All @@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_clock] sys_clock,
};

void
Expand Down
1 change: 1 addition & 0 deletions kernel/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_clock 22
9 changes: 9 additions & 0 deletions kernel/sysproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,12 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}

uint64
sys_clock(void)
{
volatile uint32 *clock = (uint32 *) GOLD_RTC;
uint32 top = clock[0];
uint32 btm = clock[1];
return ((uint64) btm << 32) | top;
}
3 changes: 3 additions & 0 deletions kernel/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ kvmmake(void)
// PLIC
kvmmap(kpgtbl, PLIC, PLIC, 0x4000000, PTE_R | PTE_W);

// map golfish real time clock
kvmmap(kpgtbl, GOLD_RTC, GOLD_RTC, PGSIZE, PTE_R);

// map kernel text executable and read-only.
kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X);

Expand Down
Binary file added user/birthday
Binary file not shown.
133 changes: 133 additions & 0 deletions user/birthday.c

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: could handle wrong format input

Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "kernel/fcntl.h"
#include "kernel/param.h"
#include "time.h"

static const int days_per_month[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};

int validate_birthdate(char buf[]) {
if (strlen(buf) != 5) { // not MM/DD
return 0;
}

int i = 0, month = 0, day = 0;
while (buf[i] != '\0') {
if ((buf[i] == '/') ||(buf[i] >= '1' && buf[i] <= '9')) {
if (i < 2) {
month = month * 10 + (buf[i] - '0');
} else if (i > 2) {
day = day * 10 + (buf[i] - '0');
}
}
++i;
}

if ((month < 1) || (month > 12) || (day > days_per_month[month-1] && month != 2 && day != 29) || (day < 1)) {
return 0;
}

return 1;
}

void print_usage() {
printf("Usage:\n");
printf("birthday # if set, check if it's your birthday\n");
printf("birthday -s MM/DD # (re)set birthday\n");
}

int main(int argc, char *argv[]) {
/*
birthday command in use
$birthday - No arguments, if birthday is set, return predefined
statements. else, ask to set birthday.
$birthday -s [MM/DD] - Set birthday
*/

struct stat st; // check if birthday file exists
int fd; // for open, write, close
char buf[MAXPATH]; // for write

int month = 0, day = 0, i = 0; // for comparisons

int exists = (stat("birthday.txt", &st) == 0);

// proper length and checking flag
if ((argc == 3) && (argv[1][0] == '-' && argv[1][1] == 's')) {
if (!validate_birthdate(argv[2])) {
print_usage();
return -1;
}

fd = open("birthday.txt", O_CREATE | O_RDWR | O_TRUNC);
if (fd < 0) { // error
return -1;
}
write(fd, argv[2], strlen(argv[2]));
close(fd);
return 0;
}
if (argc == 1 && exists) {
fd = open("birthday.txt", O_RDWR);
if (fd < 0) { // error
return -1;
}
int n = read(fd, buf, sizeof(buf) - 1);

if(n < 0){
close(fd);
return -1;
}
buf[n] = '\0';

while (buf[i] != '\0') {
if (i < 2) {
month = month * 10 + (buf[i] - '0');
} else if (i > 2) {
day = day * 10 + (buf[i] - '0');
}
++i;
}

uint64 c = clock() / 1000000000ULL;
uint64 local_date = c - (7 * 3600);
datetime date = to_datetime(local_date);

if (date.month == month && date.day == day) {
printf(
" ( (\n"
" ( ) ( ) (\n"
" ( Y Y ( )\n"
" ( ) | | | | Y\n"
" Y | | | | | |\n"
" | | | |.-----| |---.___ | |\n"
" | | .--| |,~~~~~| |~~~,,,,'-| |\n"
" | |-,,~~'-'___ '-' ~~| |._\n"
" .| |~ // ___ '-',,'.\n"
" /,'-' <_// // _ __ ~,\\\n"
" / ; ,-, \\_> <<_______________;_)\n"
" | ; {(_)} _, . |================|\n"
" | '-._ ~~,,, | ,, |\n"
" | '-.__ ~~~~~~~~~~~|________________| \n"
" |\\ `'----------|\n"
" | '=._ |\n"
" : '=.__ |\n"
" \\ `'==========|\n"
"snd '-._ |\n"
" '-.__ |\n"
" ``''--------|\n"
);
printf("Happy Birthday!\n");
} else {
printf("Uh oh. It's not your birthday yet :(\n");
}
return 0;
}

print_usage(); // otherwise, fail.
return -1;
}
Binary file added user/date
Binary file not shown.
21 changes: 21 additions & 0 deletions user/date.c

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Date has a weird formatting:
Screenshot 2025-10-01 at 9 05 25 PM

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "time.h"

static const char* month_name[] = {
"Jan", "Feb", "Mar", "Apr", "May", "June",
"July", "Aug", "Sep", "Oct", "Nov", "Dec"
};

int main() {
uint64 c = clock() / 1000000000ULL;
uint64 local_date = c - (7 * 3600);
datetime date = to_datetime(local_date);

printf("%s %d %d:%d:%d PDT %d\n",
month_name[date.month-1], date.day,
date.hour, date.minute, date.second,
date.year);
return 0;
}
61 changes: 61 additions & 0 deletions user/time.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"
#include "time.h"

int is_leap(int year) {
return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}

static const int days_per_month[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};

datetime to_datetime(uint64 timestamp) {
datetime date;
// 86400 seconds in a day
uint64 secs = timestamp % 86400; // seconds passed today
uint64 days = timestamp / 86400; // number of days since Jan 1, 1970

date.hour = secs / 3600; // gets the hour
if (date.hour > 12) {
date.hour -= 12; // i don't like military time.
}
date.minute = (secs % 3600) / 60; // remaining minutes
date.second = secs % 60; // remaining seconds

// unix time starts in 1970
date.year = 1970;

while (1) {
int days_per_yr = is_leap(date.year) ? 366 : 365;
if (days >= days_per_yr) {
// subtract days until it fits within a year
days -= days_per_yr;
date.year++;
} else {
break;
}
}

int month = 0;
while (1) {
int m_days = days_per_month[month];
if (month == 1 && is_leap(date.year)) {
m_days = 29;
}
if (days >= m_days) {
// subtract days until it fits in a month
days -= m_days;
month++;
} else {
break;
}
}
date.month = month + 1; // corrects month
date.day = days + 1; // corrects day

return date;
}

18 changes: 18 additions & 0 deletions user/time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef TIME_H
#define TIME_H

#include "kernel/types.h"

typedef struct datetime {
int year;
int month;
int day;
int hour;
int minute;
int second;
} datetime;

int is_leap(int year);
datetime to_datetime(uint64 timestamp);

#endif
1 change: 1 addition & 0 deletions user/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int getpid(void);
char* sys_sbrk(int,int);
int pause(int);
int uptime(void);
int clock(void);

// ulib.c
int stat(const char*, struct stat*);
Expand Down
1 change: 1 addition & 0 deletions user/usys.pl
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ sub entry {
entry("sbrk");
entry("pause");
entry("uptime");
entry("clock");