Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stuff next three nibbles of tv_sec into top of tv_nsec to fix y2038 #38

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ It should work under any POSIX OS that support either `openpty()` or the `grantp
- Supports a no-tty mode, relying on pipes instead of pseudottys, while still recording stdout/stderr
- Automatically detects whether to use pseudottys or pipes, also overridable from command-line
- Supports reporting the number of bytes that were output to the terminal on session exit
- Format extended to support dates up to 0xFFFFFFFFFFF

## compilation

Expand Down
24 changes: 14 additions & 10 deletions io.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>

Expand All @@ -65,7 +66,7 @@ static int is_little_endian(void)
char *p = (char *)&n;
char x[] = { 1, 0, 0, 0 };

assert(sizeof(int) == 4);
_Static_assert(sizeof(int) == 4, "Check relies on int size");

if (memcmp(p, x, 4) == 0)
{
Expand All @@ -81,7 +82,7 @@ static int is_little_endian(void)
}


static int convert_to_little_endian(int x)
static uint32_t convert_to_little_endian(uint32_t x)
{
if (is_little_endian())
{
Expand All @@ -96,15 +97,16 @@ static int convert_to_little_endian(int x)

int read_header(FILE *fp, Header *h)
{
int buf[3];
uint32_t buf[3], raw_usec;

if (fread_wrapper(buf, sizeof(int), 3, fp) == 0)
if (fread_wrapper(buf, sizeof(uint32_t), 3, fp) == 0)
{
return 0;
}

h->tv.tv_sec = convert_to_little_endian(buf[0]);
h->tv.tv_usec = convert_to_little_endian(buf[1]);
raw_usec = convert_to_little_endian(buf[1]);
h->tv.tv_sec = convert_to_little_endian(buf[0]) | ((raw_usec & 0xfff00000ull) << 12);
h->tv.tv_usec = raw_usec & 0x000fffffU;
h->len = convert_to_little_endian(buf[2]);

return 1;
Expand All @@ -113,13 +115,15 @@ int read_header(FILE *fp, Header *h)

int write_header(FILE *fp, Header *h)
{
int buf[3];
uint32_t buf[3];

buf[0] = convert_to_little_endian(h->tv.tv_sec);
buf[1] = convert_to_little_endian(h->tv.tv_usec);
// The reasonable range of tv_usec is [0, 999999], which is [0, 0x00`0F`42`3F]
// Thus, we can stuff 3 nibbles from tv_sec into the top bits, giving us a range of dates up to around year 559444
buf[0] = convert_to_little_endian(h->tv.tv_sec & 0xffffffffU);
buf[1] = convert_to_little_endian(h->tv.tv_usec | ((h->tv.tv_sec & 0x00000fff00000000ull) >> 12));
buf[2] = convert_to_little_endian(h->len);

if (fwrite_wrapper(buf, sizeof(int), 3, fp) == 0)
if (fwrite_wrapper(buf, sizeof(uint32_t), 3, fp) == 0)
{
return 0;
}
Expand Down