/*
 * 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 <errno.h>    // errno, EINTR
#include <fcntl.h>    // open, O_RDONLY
#include <stdio.h>    // printf, fprintf, perror
#include <stdlib.h>   // EXIT_FAILURE, EXIT_SUCCESS
#include <unistd.h>   // read, close

// ReadAll: read exactly n bytes from fd into buf.
//
// A single read() can come up short (especially on pipes and sockets),
// so we loop, advancing by however many bytes actually landed, and retry
// when the call is interrupted (EINTR). Returns the number of bytes read
// (n on success; fewer only if we hit EOF or a real error).
int ReadAll(int fd, char* buf, int n) {
  int bytes_left = n;
  int result;
  while (bytes_left > 0) {
    result = read(fd, buf + (n - bytes_left), bytes_left);
    if (result == -1) {
      if (errno != EINTR) {
        break;          // a real error
      }
      continue;         // EINTR: just retry
    } else if (result == 0) {
      break;            // EOF: nothing left to read
    }
    bytes_left -= result;
  }
  return n - bytes_left;
}

int main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: ./readN <file>\n");
    return EXIT_FAILURE;
  }

  int fd = open(argv[1], O_RDONLY);
  if (fd == -1) {
    perror("open");
    return EXIT_FAILURE;
  }

  char buf[16];
  int got = ReadAll(fd, buf, sizeof(buf));
  printf("read %d bytes\n", got);

  close(fd);
  return EXIT_SUCCESS;
}