#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/wait.h>

#define NUM_BYTES 1000
#define NUM_FORKS 10
#define FILE_SIZE (NUM_FORKS*NUM_BYTES)
#define FILE_NAME "appended.dat"

int main(int argc, char** argv) {
    unlink(FILE_NAME);

    pid_t forks[NUM_FORKS];
    for (int i = 0; i < NUM_FORKS; i++) {
        pid_t child = fork();
        if (child == 0) { // child
            // open file
            int fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_APPEND,
                S_IRUSR | S_IWUSR);
            if (fd < 0) {
                perror("Error opening file");
            }

            // write bytes
            char b = 0x2a;
            int len = 0;
            do {
                //printf("write %d\n", getpid());
                ssize_t n = write(fd, &b, 1);
                if (n < 0) {
                    if (errno == EINTR) {
                        printf("%d interrupted\n", (int)getpid());
                        continue;
                    } else {
                        printf("%d error writing bytes\n", (int)getpid());
                        perror("Error writing byte");
                        exit(EXIT_FAILURE);
                    }
                }
                len++;
                usleep(1000);
            } while (len < NUM_BYTES);

            // close file
            close(fd);

            exit(EXIT_SUCCESS);
        } else {
            forks[i] = child;
        }
    }

    // wait for all forks
    for (int i = 0; i < NUM_FORKS; i++) {
        pid_t pid = waitpid(forks[i], NULL, 0);
        if (pid < 0) {
            perror("waitpid()");
        }
    }

    // check size of file
    int fd = open(FILE_NAME, O_RDONLY);
    struct stat buf;
    fstat(fd, &buf);
    close(fd);

    unlink(FILE_NAME);

    if (buf.st_size != FILE_SIZE) {
        printf("ERROR: file size %lld, expected %d\n",
            buf.st_size, FILE_SIZE);
        exit(EXIT_FAILURE);
    } else {
        printf("Success\n");
        exit(EXIT_SUCCESS);
    }
}
