Introduce old redir program
[lcapit-junk-code.git] / git / unpack-entry.c
blob7d7c451845fe650d254a0faec5651bf334cb6b1d
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <zlib.h>
7 #include <errno.h>
8 #include <sys/types.h>
10 static unsigned char stdin_next_byte(void)
12 ssize_t ret;
13 unsigned char b = 0;
15 ret = read(0, &b, sizeof(b));
16 if (ret != sizeof(b)) {
17 fprintf(stderr, "read(): ");
18 if (!ret)
19 fprintf(stderr, "EOF\n");
20 else if (ret < 0)
21 fprintf(stderr, "%s\n", strerror(errno));
22 else
23 fprintf(stderr, "read %d bytes (1 expected)\b", ret);
24 exit(1);
27 return b;
30 static int read_object_header(int *type, size_t *sizep)
32 size_t size;
33 unsigned shift;
34 unsigned char c;
36 c = stdin_next_byte();
37 *type = (c >> 4) & 7;
38 size = c & 15;
39 shift = 4;
40 while (c & 0x80) {
41 if (sizeof(long) * 8 <= shift) {
42 printf("don't know what happened\n");
43 exit(1);
45 c = stdin_next_byte();
46 size += (c & 0x7f) << shift;
47 shift += 7;
50 *sizep = size;
51 return 0;
54 static void show_object_header(int type, size_t size)
56 printf("type: ");
58 switch (type) {
59 case 0:
60 printf("None");
61 break;
62 case 1:
63 printf("commit");
64 break;
65 case 2:
66 printf("tree");
67 break;
68 case 3:
69 printf("blob");
70 break;
71 case 4:
72 printf("tag");
73 break;
74 case 6:
75 printf("ofs delta");
76 break;
77 case 7:
78 printf("ref delta");
79 break;
80 default:
81 printf("unknown: %d", type);
82 break;
84 printf(" {%d} size: %zd bytes\n", type, size);
87 static unsigned char *unpack_entry(size_t size)
89 int st;
90 z_stream stream;
91 unsigned char *buf, c;
93 buf = malloc(size + 1);
94 if (!buf)
95 return NULL;
96 buf[size] = 0;
98 memset(&stream, 0, sizeof(stream));
99 stream.next_out = buf;
100 stream.avail_out = size;
102 inflateInit(&stream);
103 do {
104 c = stdin_next_byte();
105 stream.next_in = &c;
106 stream.avail_in = 1;
107 st = inflate(&stream, Z_FINISH);
108 } while (st == Z_OK || st == Z_BUF_ERROR);
109 inflateEnd(&stream);
111 if ((st != Z_STREAM_END) || stream.total_out != size) {
112 free(buf);
113 fprintf(stderr, "ERROR: zlib: %s\n", stream.msg);
114 return NULL;
117 return buf;
120 int main(int argc, char *argv[])
122 int type;
123 size_t size;
124 unsigned char *obj;
125 unsigned long offset;
127 if (argc != 2) {
128 printf("unpack-pack-entry offset < packfile\n");
129 exit(1);
132 /* go to where the object is stored */
133 offset = strtoul(argv[1], (char **) NULL, 10);
134 if (lseek(0, offset, SEEK_SET) < 0) {
135 perror("lseek");
136 exit(1);
139 /* header */
140 read_object_header(&type, &size);
141 show_object_header(type, size);
143 if (type == 6 || type == 7) {
144 fprintf(stderr, "(no support to unpack delta objects)\n");
145 exit(1);
148 obj = unpack_entry(size);
149 if (!obj)
150 exit(1);
152 /* show the object */
153 fflush(stdout);
154 write(1, obj, size);
155 free(obj);
157 return 0;