-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlist.c
More file actions
207 lines (161 loc) · 3.73 KB
/
list.c
File metadata and controls
207 lines (161 loc) · 3.73 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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include "list.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
nptr create_node(const char *w, const int len) {
nptr newNode = (nptr)malloc(sizeof(linked_list_node));
if (newNode == 0) {
return 0;
}
newNode->next = 0;
newNode->data = w;
newNode->len = len;
return newNode;
}
nptr create_node_normalized(const char *w, const int len) {
int normalized_len = len;
// Remove trailing slashes (but keep root "/" as is)
while (normalized_len > 1 && w[normalized_len - 1] == '/') {
normalized_len--;
}
return create_node(w, normalized_len);
}
char *copy_data(char *buf, nptr node, int max_len) {
if (node == 0) {
return 0;
}
if (node->len == 0) {
return 0;
}
// Validate path length
if (node->len >= max_len) {
fprintf(stderr, "Path too long (max %d chars): ", max_len - 1);
for (int i = 0; i < (node->len < 50 ? node->len : 50); i++) {
fprintf(stderr, "%c", node->data[i]);
}
if (node->len > 50) {
fprintf(stderr, "...");
}
fprintf(stderr, "\n");
return 0;
}
int len = max_len - 1;
int ix = 0;
if (node->len < len) {
len = node->len;
}
for (; ix < len; ix++) {
buf[ix] = node->data[ix];
}
for (; ix < max_len; ix++) {
buf[ix] = 0;
}
return buf;
}
int valid_path(nptr node) {
char buf[PATH_MAX];
char *path = copy_data(buf, node, PATH_MAX);
if (path == 0) {
return 0;
}
if (path[0] != '/') {
return 0;
}
struct stat sbuf;
if (0 == stat(buf, &sbuf)) {
switch (sbuf.st_mode & S_IFMT) {
case S_IFDIR:
return 1;
}
} else {
// For debugging purposes, we could distinguish between:
// ENOENT - path does not exist
// EACCES - permission denied
// ENOTDIR - component of path is not a directory
// But for this utility, we treat all failures as invalid paths
}
return 0;
}
int valid_path_verbose(nptr node) {
char buf[PATH_MAX];
char *path = copy_data(buf, node, PATH_MAX);
if (path == 0) {
return 0;
}
if (path[0] != '/') {
return 0;
}
struct stat sbuf;
if (0 == stat(buf, &sbuf)) {
switch (sbuf.st_mode & S_IFMT) {
case S_IFDIR:
return 1;
default:
return 0; // Not a directory
}
} else {
// Could check errno here for specific error types:
// ENOENT, EACCES, ENOTDIR, ENAMETOOLONG, etc.
return -1; // stat() error
}
}
void print_node(nptr node) {
if (node == 0) {
fprintf(stderr, "<nil>\n");
return;
}
for (int ix = 0; ix < node->len; ix++) {
fprintf(stdout, "%c", node->data[ix]);
}
}
int compare_node(nptr lhs, nptr rhs) {
if (lhs == rhs) {
return 0;
}
if (lhs == 0) {
return -1;
}
if (rhs == 0) {
return 1;
}
// Quick length comparison for early exit (optimization for duplicates)
if (lhs->len != rhs->len) {
return (lhs->len < rhs->len) ? -1 : 1;
}
// Lengths are equal, compare character by character
for (int ix = 0; ix < lhs->len; ix++) {
if (lhs->data[ix] != rhs->data[ix]) {
return (lhs->data[ix] < rhs->data[ix]) ? -1 : 1;
}
}
return 0; // Strings are identical
}
int compare_data(nptr lhs, const char *w, const int len) {
nptr t = create_node_normalized(w, len);
if (t == 0) {
return -1; // Memory allocation failed, treat as mismatch
}
int c = compare_node(lhs, t);
free(t);
return c;
}
nptr add_node(nptr node, const char *w, const int len) {
nptr nn = create_node_normalized(w, len);
if (nn == 0) {
return 0; // Memory allocation failed
}
while (node != 0) {
if (0 == compare_node(node, nn)) {
free(nn);
return node;
}
if (node->next == 0) {
node->next = nn;
break;
}
node = node->next;
}
return nn;
}