aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2022-10-23 22:53:01 +0000
committerdam <dam@gudinoff>2022-10-23 22:53:01 +0000
commit3a590dd7c156b1bdf4a119921ee39035b2ec1626 (patch)
tree941a6b7fb9d3262420b10d2fd1838edd12bc69f2
parented0f749430982ac5435c61d1d80c7c74767a8051 (diff)
downloadtask-time-tracker-3a590dd7c156b1bdf4a119921ee39035b2ec1626.tar.zst
task-time-tracker-3a590dd7c156b1bdf4a119921ee39035b2ec1626.zip
Added protection to overflow on malloc argument. Decided not to implement logging.
-rw-r--r--main.c26
-rw-r--r--readme.md5
2 files changed, 17 insertions, 14 deletions
diff --git a/main.c b/main.c
index 10d5142..733778a 100644
--- a/main.c
+++ b/main.c
@@ -63,10 +63,14 @@ const char DB_FILE_SIGN[] = DB_FILE_SIGN_STR;
const size_t DB_FILE_SIGN_LENGTH = sizeof(DB_FILE_SIGN_STR)-1;
const size_t SIZEOF_TASK_ST = sizeof(task_st);
const size_t SIZEOF_DATABASE_ST = sizeof(database_st);
+const size_t SIZEOF_CHAR = sizeof(char);
+const size_t SIZEOF_INT64 = sizeof(int64_t);
const int64_t SECONDS_IN_MINUTE = (int64_t)60;
const int64_t SECONDS_IN_HOUR = (int64_t)60*SECONDS_IN_MINUTE;
const int64_t SECONDS_IN_DAY = (int64_t)24*SECONDS_IN_HOUR;
const int64_t SECONDS_IN_YEAR = (int64_t)365*SECONDS_IN_DAY;
+const size_t MAX_DATABASE_TASKS = (PTRDIFF_MAX < (SIZE_MAX / SIZEOF_TASK_ST)) ? PTRDIFF_MAX : (SIZE_MAX / SIZEOF_TASK_ST);
+
database_st database = { .tasks = NULL };
database_st archive = { .tasks = NULL };
@@ -93,7 +97,7 @@ bool is_file_accessible(const char *path) {
// Given an UTF8 encoded string, truncate it to length without breaking any UTF8 character.
// The string should have capacity for at least length number of items.
// The terminating null byte ('\0') is included in length.
-// The function returns the amount of items that got discarded counting from length.
+// Returns the amount of items discarded.
size_t truncate_string_utf8(char *string, size_t length) {
// Check for special cases where no truncation is required.
@@ -237,12 +241,13 @@ task_st *get_selected_task(database_st *db) {
return task;
}
+
// Creates new task returned in the pointer. If necessary, expands database capacity.
// Returns success.
bool create_task(database_st *db, task_st **task) {
assert(db != NULL);
- if (db->count == PTRDIFF_MAX) {
+ if (db->count == MAX_DATABASE_TASKS) {
fprintf(stderr, "Database reached maximum capacity.\n");
return false;
}
@@ -251,7 +256,7 @@ bool create_task(database_st *db, task_st **task) {
size_t current_capacity = db->capacity;
if((db->count + 1) > current_capacity) {
size_t new_capacity = current_capacity == 0 ? 2 :
- current_capacity > PTRDIFF_MAX >> 1 ? PTRDIFF_MAX :
+ current_capacity > MAX_DATABASE_TASKS >> 1 ? MAX_DATABASE_TASKS :
current_capacity << 1;
task_st *new_tasks = realloc(db->tasks, new_capacity * SIZEOF_TASK_ST);
@@ -443,7 +448,7 @@ void update_total_times(database_st *db) {
int64_t *d4 = &db->total_times[4];
int64_t *d5 = &db->total_times[5];
int64_t *d6 = &db->total_times[6];
- memset(db->total_times, 0, NUM_WEEK_DAYS * sizeof(int64_t));
+ memset(db->total_times, 0, NUM_WEEK_DAYS * SIZEOF_INT64);
for (size_t idx = 0; idx < db->count; idx++) {
int64_t *times = db->tasks[idx].times;
@@ -513,7 +518,7 @@ bool store_database(const database_st *db, const char *path) {
return false;
}
- fwrite(DB_FILE_SIGN, sizeof(char), DB_FILE_SIGN_LENGTH, file);
+ fwrite(DB_FILE_SIGN, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
fwrite(db, SIZEOF_DATABASE_ST, 1, file);
fwrite(db->tasks, SIZEOF_TASK_ST, db->count, file);
@@ -536,7 +541,7 @@ bool load_database(database_st *db, const char *path) {
// Validate file signature.
char file_signature[DB_FILE_SIGN_LENGTH];
- fread(&file_signature, sizeof(char), DB_FILE_SIGN_LENGTH, file);
+ fread(&file_signature, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file);
if (strncmp(file_signature, DB_FILE_SIGN, DB_FILE_SIGN_LENGTH) != 0) {
fprintf(stderr, "Invalid file signature.\n");
fclose(file);
@@ -547,7 +552,7 @@ bool load_database(database_st *db, const char *path) {
fread(db, SIZEOF_DATABASE_ST, 1, file);
// Restore database capacity.
- db->tasks = calloc(db->capacity, SIZEOF_TASK_ST);
+ db->tasks = malloc(db->capacity * SIZEOF_TASK_ST);
// Read database entries.
fread(db->tasks, SIZEOF_TASK_ST, db->count, file);
@@ -685,7 +690,7 @@ bool append_to_csv(task_st *task, const char *path) {
char last_char;
fseek(file, -1, SEEK_END);
- fread(&last_char, sizeof(char), 1, file);
+ fread(&last_char, SIZEOF_CHAR, 1, file);
if (last_char != '\n') {
fprintf(file, "\n");
}
@@ -708,7 +713,6 @@ bool append_to_csv(task_st *task, const char *path) {
return true;
}
-
#define INPUT_TIMEOUT_MS 1000
#define INPUT_AWAIT_INF -1
@@ -1139,6 +1143,7 @@ int main(int argc, char *argv[]) {
load_database(&database, db_file_path);
+ flushinp();
ungetch(KEY_RESIZE);
for (int key; (key = getch()) != 'q'; ) {
@@ -1188,6 +1193,7 @@ int main(int argc, char *argv[]) {
db->selected_task = selected_task - db->tasks;
// Force rename action.
+ flushinp();
ungetch(KEY_F(2));
break;
}
@@ -1526,6 +1532,8 @@ int main(int argc, char *argv[]) {
break;
}
+ // TODO Should I change the selected_task directly?
+
case KEY_HOME: {
if (db->count > 0) {
db->selected_task = 0;
diff --git a/readme.md b/readme.md
index b89a593..4fef661 100644
--- a/readme.md
+++ b/readme.md
@@ -1,10 +1,6 @@
Task Time Tracker
=================
-# notes
-- Only one task may be active;
-- The log will be a circular array. During app startup the array will be loaded from a csv file. The log array should have a fixed length. Each string in the array should also have fixed length. Loading and storing it to a file will be implemented using readline and writeline operations. In order for the log file to be CSV compatible, we must always use the same format when writing to the log array. Best approach is to use a function that enfores the CSV format. The log should be written to a file every 5 minutes (not set in stone), if required; such may be done using a `log_is_dirty` flag. A possible structure for the log entries is: {uint64_t timestamp; uint8_t action[16]; uint8_t task_name[MAX_TASK_NAME+1]; uint8_t notes[16]; }.
-
# know-how
- [ncurses colors](https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/color.html#COLORBASICS)
- [pprintf](https://cplusplus.com/reference/cstdio/printf/)
@@ -55,7 +51,6 @@ Task Time Tracker
- [x] Add/remove time using keys: `F3`;
- [x] Add/remove time for any day of week;
- [x] Total times may saturate, but before that the user will see the infinite symbol. Solution: Provide user with possibility to refresh totals.
-- [ ] Implement logs as described above.
- [ ] Improve the way we save the changes made to the database:
- When operating on the archive, will we keep the saves synchronous?
- Maybe add a cooldown timer and save changes after it times out?