#include 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); }