/*
* Copyright ©2026 Soham Pardeshi. All rights reserved.
* Permission is hereby granted to students registered for University of
* Washington CSE 333 for use solely during Summer Quarter 2026 for
* purposes of the course. No other use, copying, distribution, or
* modification is permitted without prior written consent. Copyrights
* for third-party components of this work must be honored. Instructors
* interested in reusing these course materials should contact the author.
*/
#include "fileutil.h"
#include <errno.h> // for errno, EINTR, EAGAIN
#include <fcntl.h> // for open, O_RDONLY
#include <unistd.h> // for read, close, lseek, SEEK_END
ssize_t FileSize(const char* filename) {
// Open the file in read-only mode.
int fd = open(filename, O_RDONLY);
if (fd == -1) {
return -1;
}
// Seek to the end of the file to find its size.
off_t size = lseek(fd, 0, SEEK_END);
// Close the file in all cases, including when lseek failed.
int close_res = close(fd);
if (size == -1 || close_res == -1) {
return -1;
}
return size;
}
ssize_t ReadFile(const char* filename, char* buf, size_t buflen,
size_t chunk_size) {
// Open the file in read-only mode.
int fd = open(filename, O_RDONLY);
if (fd == -1) {
return -1;
}
// 'buflen' is how many bytes the caller wants read into 'buf'; give that
// a clearer name for use in the loop below.
size_t target = buflen;
// Read until we've read 'target' bytes or hit the end of the file, asking
// for at most 'chunk_size' bytes on each read() call.
size_t bytes_read = 0;
while (bytes_read < target) {
// How many bytes to request this time: a full chunk, unless fewer than
// a chunk's worth of space is left in the buffer.
size_t bytes_remaining = target - bytes_read;
size_t to_read = chunk_size;
if (to_read > bytes_remaining) {
to_read = bytes_remaining;
}
// Attempt to read 'to_read' bytes from the file into the buffer.
ssize_t res = read(fd, buf + bytes_read, to_read);
// Case 1: End of file.
if (res == 0) {
break;
}
// Case 2: Error.
if (res == -1) {
if (errno == EINTR || errno == EAGAIN) {
continue; // recoverable error; try again
}
close(fd); // clean up before reporting the error
return -1;
}
bytes_read += res; // may be a partial read; keep looping
}
// Close the file and report how much we read.
if (close(fd) == -1) {
return -1;
}
return bytes_read;
}