first rev of some stupid code for reading/writing cpio archives
[rcpio.git] / reader.c
1 #define _GNU_SOURCE
2
3 #include <stdio.h>
4 #include <sys/mman.h>
5 #include <ctype.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <sys/stat.h>
12 #include <string.h>
13
14 #include "cpio-fmt.h"
15
16 static int extract_num(const char *num, int len)
17 {
18     char buffer[len];
19
20     memcpy(buffer, num, len);
21     buffer[len] = '\0';
22
23     return strtoul(buffer, NULL, 16);
24 }
25
26 static void printf_header(const struct cpio_hdr *hdr)
27 {
28    printf("   c_magic %6.6s        c_ino %8.8s      c_mode %8.8o       c_uid %8.8s      c_gid %8.8s\n",
29                         hdr->c_magic,
30                         hdr->c_ino,
31                         extract_num(hdr->c_mode, 8),
32                         hdr->c_uid,
33                         hdr->c_gid);
34
35     printf("   c_nlink %8.8s    c_mtime %8.8s  c_filesize %8.8s  c_namesize %8.8s c_checksum %8.8s\n",
36                         hdr->c_nlink,
37                         hdr->c_mtime,
38                         hdr->c_filesize,
39                         hdr->c_namesize,
40                         hdr->c_checksum);
41
42     printf("c_devmajor %8.8s c_devminor %8.8s c_rdevmajor %8.8s c_rdevminor %8.8s\n",
43                         hdr->c_devmajor,
44                         hdr->c_devminor,
45                         hdr->c_rdevmajor,
46                         hdr->c_rdevminor);
47 }
48
49
50 static void printf_stat(const struct stat *st)
51 {
52     printf("st_ino %lx    st_mode %o     st_uid %x st_gid %x\n",
53             st->st_ino, st->st_mode, st->st_uid, st->st_gid);
54
55     printf("st_nlink %x\n", st->st_nlink);
56     printf("major %x minor %x\n", major(st->st_rdev), minor(st->st_rdev));
57 #if 0
58     dev_t     st_dev;     /* ID of device containing file */
59     ino_t     st_ino;     /* inode number */
60     mode_t    st_mode;    /* protection */
61     nlink_t   st_nlink;   /* number of hard links */
62     uid_t     st_uid;     /* user ID of owner */
63     gid_t     st_gid;     /* group ID of owner */
64     dev_t     st_rdev;    /* device ID (if special file) */
65     off_t     st_size;    /* total size, in bytes */
66     blksize_t st_blksize; /* blocksize for filesystem I/O */
67     blkcnt_t  st_blocks;  /* number of blocks allocated */
68     time_t    st_atime;   /* time of last access */
69     time_t    st_mtime;   /* time of last modification */
70     time_t    st_ctime;   /* time of last status change */
71 #endif
72 }
73
74 static void * print_record(void *ptr)
75 {
76     struct stat st;
77     struct cpio_hdr *h = ptr;
78     int namesize, filesize;
79     char *str = (char *)(h + 1);
80
81     if (memcmp(CPIO_MAGIC, h->c_magic, sizeof(CPIO_MAGIC)-1) != 0) {
82         printf("bad magic\n");
83         exit(1);
84     }
85
86     namesize = extract_num(h->c_namesize, 8);
87     filesize = extract_num(h->c_filesize, 8);
88
89     printf("**** [%*.*s] ****************************************************\n", namesize-1, namesize-1, str);
90     printf_header(ptr);
91
92     printf("\n");
93     if (stat(str, &st) >= 0) {
94         printf_stat(&st);
95     }
96     printf("\n");
97
98     return ptr + pad(namesize + sizeof(struct cpio_hdr)) + pad(filesize);
99 }
100
101 static void print_files(void *ptr, int len)
102 {
103     void *end = ptr + len;
104     while ((ptr = print_record(ptr))) {
105         if (ptr >= end)
106             break;
107     }
108 }
109
110 int main(int argc, char *argv[])
111 {
112     struct stat st;
113     void *ptr;
114     int fd;
115
116     if (argc != 2) {
117         printf("%s <file>\n", argv[0]);
118         exit(1);
119     }
120
121     fd = open(argv[1], O_RDONLY);
122     if (fd < 0) {
123         perror("open");
124         exit(1);
125     }
126
127     if (fstat(fd, &st) < 0) {
128         perror("stat");
129         exit(1);
130     }
131
132     ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
133     if (ptr == MAP_FAILED) {
134         perror("mmap");
135         exit(1);
136     }
137     print_files(ptr, st.st_size);
138     munmap(ptr, st.st_size);
139     return 0;
140 }