#include <IO/Node.h>
Node::Node(FILE f) {
fd = f;
error = libc::statf(f, &info);
}
Node::Node(const char* filename, int mode) {
fd = libc::open(filename, mode);
if (fd < 0) {
if (fd != E_NOT_FOUND) error = libc::stat(filename, &info);
} else {
int i = libc::statf(fd, &info);
error = i;
if (error < 0) libc::close(fd);
}
}
Node::Node(FILE parent, const char* filename, int mode) {
fd = libc::open_relative(parent, filename, mode);
if (fd < 0) {
if (fd != E_NOT_FOUND) error = libc::stat_relative(parent, filename, &info);
} else {
int i = libc::statf(fd, &info);
error = i;
if (error < 0) libc::close(fd);
}
}
void Node::close() {
if (error == 0) libc::close(fd);
error = E_INVALID_FD;
}
////////
static void simplify_path(char* p) {
char *it = p;
char *member = it;
while (*it != 0) {
if (*it == '/') {
if (it == member && it != p) {
// two consecutive slashes
char *i = member;
while (1) {
i[0] = i[1];
if (i[0] == 0) break;
i++;
}
} else {
*it = 0;
if (libc::strcmp(member, ".") == 0) {
char *i = member;
while (1) {
i[0] = i[2];
if (i[0] == 0) break;
i++;
}
} else if (libc::strcmp(member, "..") == 0) {
*it = '/';
char* start = member - 2;
char* next = member + 3;
while (start > p && *start != '/') {
start--;
}
start++;
it = member = start;
while (1) {
*start = *next;
if (*start == 0) break;
start++;
next++;
}
} else {
*it = '/';
it++;
member = it;
}
}
} else {
it++;
}
}
}
String path_cat(const String &a, const String &b, bool trailing_slash) {
int len, la = a.size(), lb = b.size();
if (b[0] == '/') {
len = lb + 2;
} else {
len = la + lb + 3;
}
char buf[len];
if (b[0] == '/') {
libc::memcpy(buf, b.c_str(), lb);
if (buf[lb-1] != '/') {
buf[lb++] = '/';
}
buf[lb] = 0;
} else {
libc::memcpy(buf, a.c_str(), la);
if (buf[la-1] != '/') {
buf[la++] = '/';
}
libc::memcpy(buf + la, b.c_str(), lb);
if (buf[la + lb - 1] != '/') {
buf[la + lb] = '/';
lb++;
}
buf[la + lb] = 0;
}
simplify_path(buf);
if (!trailing_slash) {
int l = libc::strlen(buf);
if (buf[l-1] == '/') buf[l-1] = 0;
}
return String(buf);
}