// shareoff.c — ¿quién comparte el offset de un archivo abierto?
//
// Uso: ./shareoff ARCHIVO      (lo crea con 26 letras y lo sobrescribe)
//
// Tres casos:
//   fork(): padre e hijo comparten la entrada de la tabla de archivos abiertos.
//   dup():  dos descriptores del mismo proceso, una sola entrada.
//   open() dos veces: dos entradas, cada una con su propio offset.
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

static long where(int fd) { return (long)lseek(fd, 0, SEEK_CUR); }

static void read_n(int fd, int n, const char *who) {
    char buf[32];
    ssize_t r = read(fd, buf, n);
    printf("  %s lee %zd bytes: \"%.*s\"\n", who, r, (int)r, buf);
}

int main(int argc, char *argv[]) {
    if (argc != 2) { fprintf(stderr, "uso: %s ARCHIVO\n", argv[0]); return 1; }
    int fd = open(argv[1], O_CREAT | O_TRUNC | O_WRONLY, 0644);
    if (fd < 0) { perror("open"); return 1; }
    if (write(fd, "abcdefghijklmnopqrstuvwxyz", 26) != 26) { perror("write"); return 1; }
    close(fd);

    printf("1) fork():\n");
    fd = open(argv[1], O_RDONLY);
    fflush(stdout);           // no duplicar el buffer
    pid_t pid = fork();
    if (pid == 0) {           // hijo: lee 10 bytes
        read_n(fd, 10, "hijo ");
        exit(0);
    }
    waitpid(pid, NULL, 0);    // padre: espera al hijo
    printf("  offset del padre: %ld\n", where(fd));
    read_n(fd, 5, "padre");   // sigue donde quedó
    close(fd);

    printf("2) dup():\n");
    fd = open(argv[1], O_RDONLY);
    int fd2 = dup(fd);
    read_n(fd, 5, "fd   ");
    printf("  offset de fd=%d: %ld, de fd2=%d: %ld\n", fd, where(fd), fd2, where(fd2));
    close(fd);
    close(fd2);

    printf("3) open() dos veces:\n");
    int a = open(argv[1], O_RDONLY);
    int b = open(argv[1], O_RDONLY);
    read_n(a, 5, "a    ");
    printf("  offset de a=%d: %ld, de b=%d: %ld\n", a, where(a), b, where(b));
    read_n(b, 5, "b    ");
    close(a);
    close(b);
    return 0;
}
