1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "cc4group.h"
#include "platform/platform.h"
bool catNormalFile(const char* const path, const off_t size)
{
int file = open(path, O_RDONLY);
if(file == -1)
{
fprintf(stderr, "ERROR: Reading \"%s\": %s\n", path, strerror(errno));
return false;
}
void* mappedFile = cc4group_mmap(NULL, size, PROT_READ, MAP_PRIVATE, file, 0);
if(close(file) == -1)
{
fprintf(stderr, "ERROR: Closing \"%s\": %s\n", path, strerror(errno));
}
if(mappedFile == MAP_FAILED)
{
fprintf(stderr, "ERROR: Mapping \"%s\" for reading: %s\n", path, strerror(errno));
return false;
}
if(write(STDOUT_FILENO, mappedFile, size) != size)
{
fprintf(stderr, "ERROR: Writing file contents of \"%s\" to stdout: %s\n", path, strerror(errno));
}
if(cc4group_munmap(mappedFile, size) == -1)
{
fprintf(stderr, "ERROR: Unmapping \"%s\": %s\n", path, strerror(errno));
}
return true;
}
bool catFileWithPathsAndSize(const char* const completePath, const char* const groupPath, off_t fileSize)
{
if(strcmp(groupPath, completePath) == 0)
{
return catNormalFile(completePath, fileSize);
}
const char* pathInGroup = completePath + strlen(groupPath) + 1;
CC4Group* group = cc4group.new();
if(!cc4group.openExisting(group, groupPath))
{
fprintf(stderr, "ERROR: Can not open group file \"%s\": %s\n", groupPath, cc4group.getErrorMessage(group));
return false;
}
const void* data;
size_t size;
bool success = cc4group.getEntryData(group, pathInGroup, &data, &size);
if(success)
{
if(write(STDOUT_FILENO, data, size) != (ssize_t)size)
{
fprintf(stderr, "ERROR: Writing file contents of \"%s\" to stdout: %s\n", completePath, strerror(errno));
}
}
else
{
fprintf(stderr, "ERROR: Reading \"%s\" from \"%s\": %s\n", pathInGroup, groupPath, strerror(ENOENT));
}
cc4group.delete(group);
return success;
}
bool catFile(const char* const completePath)
{
struct stat st;
char* groupPath = strdup(completePath);
char* slash;
for(slash = groupPath + strlen(groupPath); slash != NULL; slash = strrchr(groupPath, '/'))
{
*slash = '\0';
if(stat(groupPath, &st) == 0 && !S_ISDIR(st.st_mode))
{
break;
}
}
bool success;
if(slash == NULL)
{
fprintf(stderr, "ERROR: Reading \"%s\": %s\n", completePath, strerror(ENOENT));
success = false;
}
else
{
success = catFileWithPathsAndSize(completePath, groupPath, st.st_size);
}
free(groupPath);
return success;
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
fprintf(stderr, "USAGE: %s <entry path>...\n", argv[0]);
return EXIT_FAILURE;
}
bool success = true;
for(int i = 1; i < argc; ++i)
{
success &= catFile(argv[i]);
}
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
|