-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcctar.c
More file actions
173 lines (146 loc) · 3.74 KB
/
Copy pathcctar.c
File metadata and controls
173 lines (146 loc) · 3.74 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
https://codingchallenges.substack.com/p/coding-challenge-54-tar
In this coding challenge I will implement some of the functionalities of Unix tar command.
First will be to implement the -t option. Which from the man pages does the following: List archive contents to stdout. The long option form is --list.
*/
#include <unistd.h> // for getopt
#include <stdio.h> // for FILE
#include <stdlib.h> // for atoi
#include <math.h> // for pow in conversion from octal to decimal
void parse_tarball(FILE *file);
void list_filesizes(FILE *file);
void list_filenames(FILE *file);
int octal_to_decimal(int octal);
int main(int argc, char **argv) {
int tflag = 0;
int sflag = 0;
int opt;
FILE *tarballf = NULL;
opterr = 0;
while ((opt = getopt(argc, argv, "stf:")) != -1) {
switch(opt) {
case 't':
tflag = 1;
break;
case 's':
sflag = 1;
break;
case 'f':
tarballf = fopen(optarg, "rb");
if (tarballf == NULL) {
perror("Error opening file");
return 1;
}
break;
case '?':
if (optopt == 'f') {
printf("%s: Option -%c requires an argument.\n",argv[0], optopt);
return 1;
}
printf("Unknown option: %c\n", optopt);
break;
}
}
if (tarballf == NULL) {
tarballf = stdin;
}
if (tflag == 1) {
//parse_tarball(tarballf);
list_filenames(tarballf);
}
if (sflag == 1) {
list_filesizes(tarballf);
}
// do some actions then close it
if (tarballf != stdin) {
fclose(tarballf);
}
}
#define BUFF_SIZE 512
void parse_tarball(FILE *file) {
char buffer[BUFF_SIZE];
printf("%p\n", file);
while (!feof(file) && !ferror(file)) {
size_t bytes_read = fread(buffer, sizeof(*buffer), BUFF_SIZE, file);
if (bytes_read > 0) {
for (size_t i = 0; i < bytes_read; i++) {
printf("%c", buffer[i]);
}
}
else {
break;
}
}
printf("\n");
}
#define FILENAME_SIZE 100
//
void list_filenames(FILE *file) {
char buffer[FILENAME_SIZE];
while (!feof(file) && !ferror(file)) {
size_t bytes_read = fread(buffer, sizeof(*buffer), BUFF_SIZE, file);
if (bytes_read > 100) {
for (size_t i = 0; i < 100; i++) {
printf("%c", buffer[i]);
}
break;
}
else {
break;
}
}
printf("\n");
}
void list_filenames(FILE *file) {
char buffer[100];
int padded_size = 0;
while (!feof(file) && !ferror(file)) {
size_t bytes_read = fread(buffer, sizeof(*buffer), 100, file);
if (bytes_read == 0) {
// We're at the end of the file, so break the loop
break;
}
buffer[100] = '\0'; // Null-terminate the buffer
printf("%s", buffer);
int size_octal = atoi(buffer);
int size_decimal = octal_to_decimal(size_octal);
padded_size = (size_decimal + 511) / 512 * 512;
printf("Size in decimal: %d ", size_decimal);
printf("Padded Size: %d\n", padded_size);
fseek(file, 512 + padded_size - 11, SEEK_CUR);
}
}
void list_filesizes(FILE *file) {
char buffer[12];
int padded_size = 0;
fseek(file, 124, SEEK_CUR);
while (!feof(file) && !ferror(file)) {
size_t bytes_read = fread(buffer, sizeof(*buffer), 11, file);
if (bytes_read == 0) {
// We're at the end of the file, so break the loop
break;
}
buffer[11] = '\0'; // Null-terminate the buffer
printf("%s", buffer);
int size_octal = atoi(buffer);
int size_decimal = octal_to_decimal(size_octal);
padded_size = (size_decimal + 511) / 512 * 512;
printf("Size in decimal: %d ", size_decimal);
printf("Padded Size: %d\n", padded_size);
fseek(file, 512 + padded_size - 11, SEEK_CUR);
}
}
int octal_to_decimal(int octal) {
int decimal = 0;
int x = 0;
while (octal > 0)
{
// obtaining the right-most digit of num
int y = octal % 10;
// Since the right-most digits were previously scanned in the previous step, divide num by 10 to remove them.
octal /= 10;
decimal += y * pow(8, x);
++x;
}
return decimal;
}