vrfileman
diff src/fs.cc @ 2:282da6123fd4
lalalala
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Feb 2015 12:51:10 +0200 |
parents | 9e3d77dad51b |
children | d487181ee1d9 |
line diff
1.1 --- a/src/fs.cc Sat Jan 31 20:01:35 2015 +0200 1.2 +++ b/src/fs.cc Sun Feb 01 12:51:10 2015 +0200 1.3 @@ -2,13 +2,17 @@ 1.4 #include <string.h> 1.5 #include <ctype.h> 1.6 #include <errno.h> 1.7 +#include <algorithm> 1.8 #include <alloca.h> 1.9 #include <unistd.h> 1.10 #include <dirent.h> 1.11 +#include <sys/stat.h> 1.12 #include "fs.h" 1.13 1.14 +static bool childcmpless(const FSNode *aptr, const FSNode *bptr); 1.15 static char *clean_path(char *path); 1.16 static char *filename(char *path); 1.17 +static FSNode::Type st_mode_to_type(mode_t mode); 1.18 1.19 FSNode::FSNode() 1.20 { 1.21 @@ -25,7 +29,9 @@ 1.22 path = name = 0; 1.23 parent = 0; 1.24 expanded = false; 1.25 + sorted = true; 1.26 uid = gid = mode = 0; 1.27 + type = UNKNOWN; 1.28 } 1.29 1.30 void FSNode::destroy() 1.31 @@ -44,6 +50,32 @@ 1.32 destroy(); 1.33 } 1.34 1.35 +void FSNode::set_type(Type type) 1.36 +{ 1.37 + this->type = type; 1.38 +} 1.39 + 1.40 +FSNode::Type FSNode::get_type() const 1.41 +{ 1.42 + return type; 1.43 +} 1.44 + 1.45 +bool FSNode::is_file() const 1.46 +{ 1.47 + return type != DIRECTORY; 1.48 +} 1.49 + 1.50 +bool FSNode::is_directory() const 1.51 +{ 1.52 + return type == DIRECTORY; 1.53 +} 1.54 + 1.55 +void FSNode::sort_children() 1.56 +{ 1.57 + std::sort(children.begin(), children.end(), childcmpless); 1.58 + sorted = true; 1.59 +} 1.60 + 1.61 void FSNode::set_path(const char *path) 1.62 { 1.63 delete [] this->path; 1.64 @@ -77,25 +109,146 @@ 1.65 } 1.66 } 1.67 1.68 -#if 0 1.69 -FSDir *create_fsdir(const char *path) 1.70 +const char *FSNode::get_path() const 1.71 { 1.72 - char *pathbuf; 1.73 + return path; 1.74 +} 1.75 1.76 - FSDir *node = new FSDir; 1.77 - node->name = std::string(filename(path)); 1.78 +const char *FSNode::get_name() const 1.79 +{ 1.80 + return name; 1.81 +} 1.82 + 1.83 +bool FSNode::add_child(FSNode *node) 1.84 +{ 1.85 + if(node->parent == this) { 1.86 + return true; 1.87 + } 1.88 + 1.89 + if(node->parent) { 1.90 + node->parent->remove_child(node); 1.91 + } 1.92 + node->parent = this; 1.93 + 1.94 + try { 1.95 + children.push_back(node); 1.96 + } 1.97 + catch(...) { 1.98 + return false; 1.99 + } 1.100 + 1.101 + sorted = false; 1.102 + return true; 1.103 +} 1.104 + 1.105 +bool FSNode::remove_child(FSNode *node) 1.106 +{ 1.107 + int cidx = find_child(node); 1.108 + if(cidx == -1) { 1.109 + return false; 1.110 + } 1.111 + children.erase(children.begin() + cidx); 1.112 + 1.113 + if(node->parent != this) { 1.114 + fprintf(stderr, "FSNode::remove_child(): target node doesn't have this node as parent\n"); 1.115 + // let's not touch it if this happens... 1.116 + } else { 1.117 + node->parent = 0; 1.118 + } 1.119 + return true; 1.120 +} 1.121 + 1.122 +int FSNode::find_child(FSNode *node) const 1.123 +{ 1.124 + for(size_t i=0; i<children.size(); i++) { 1.125 + if(children[i] == node) { 1.126 + return i; 1.127 + } 1.128 + } 1.129 + return -1; 1.130 +} 1.131 + 1.132 +int FSNode::find_child(const char *name) const 1.133 +{ 1.134 + FSNode key; 1.135 + key.name = (char*)name; 1.136 + 1.137 + if(!sorted) { 1.138 + ((FSNode*)this)->sort_children(); 1.139 + } 1.140 + 1.141 + std::vector<FSNode*>::const_iterator it; 1.142 + it = std::lower_bound(children.begin(), children.end(), &key, childcmpless); 1.143 + if(it == children.end() || strcmp((*it)->name, name) != 0) { 1.144 + return -1; 1.145 + } 1.146 + return std::distance(children.begin(), it); 1.147 +} 1.148 + 1.149 +FSNode *FSNode::get_parent() 1.150 +{ 1.151 + return parent; 1.152 +} 1.153 + 1.154 +const FSNode *FSNode::get_parent() const 1.155 +{ 1.156 + return parent; 1.157 +} 1.158 + 1.159 +int FSNode::get_child_count() const 1.160 +{ 1.161 + return (int)children.size(); 1.162 +} 1.163 + 1.164 +FSNode *FSNode::get_child(int n) 1.165 +{ 1.166 + if(!sorted) { 1.167 + sort_children(); 1.168 + } 1.169 + return children[n]; 1.170 +} 1.171 + 1.172 +const FSNode *FSNode::get_child(int n) const 1.173 +{ 1.174 + if(!sorted) { 1.175 + ((FSNode*)this)->sort_children(); 1.176 + } 1.177 + return children[n]; 1.178 +} 1.179 + 1.180 +bool FSNode::expand() 1.181 +{ 1.182 + expanded = true; 1.183 + return true; 1.184 +} 1.185 + 1.186 +bool FSNode::is_expanded() const 1.187 +{ 1.188 + return expanded; 1.189 +} 1.190 + 1.191 + 1.192 +// ---- FSDir ---- 1.193 +FSDir::FSDir() 1.194 +{ 1.195 + type = DIRECTORY; 1.196 +} 1.197 + 1.198 +bool FSDir::expand() 1.199 +{ 1.200 + if(expanded) return true; 1.201 1.202 DIR *dir = opendir(path); 1.203 if(!dir) { 1.204 - fprintf(stderr, "failed to open dir: %s: %s\n", path, strerror(errno)); 1.205 - return 0; 1.206 + fprintf(stderr, "FSDir::expand() failed to open dir: %s: %s\n", path, strerror(errno)); 1.207 + return false; 1.208 } 1.209 1.210 - pathbuf = (char*)alloca(strlen(path) + NAME_MAX + 2); 1.211 + char *pathbuf = (char*)alloca(strlen(path) + NAME_MAX + 2); 1.212 1.213 struct dirent *ent; 1.214 while((ent = readdir(dir))) { 1.215 - sprintf(pathbuf, "%s/%s", path, ent->d_ent); 1.216 + sprintf(pathbuf, "%s/%s", path, ent->d_name); 1.217 1.218 struct stat st; 1.219 if(stat(pathbuf, &st) == -1) { 1.220 @@ -103,18 +256,49 @@ 1.221 continue; 1.222 } 1.223 1.224 - if(S_ISDIR(st.st_type)) { 1.225 - FSDir *subdir = new FSDir; 1.226 - subdir->name = std::string(ent->d_ent); 1.227 - add_subdir(node, subdir); 1.228 + FSNode *child; 1.229 + if(S_ISDIR(st.st_mode)) { 1.230 + child = new FSDir; 1.231 } else { 1.232 - FSFile *file = new FSFile; 1.233 - file->name = std::string(ent->d_ent); 1.234 - file->parent = node; 1.235 + FSFile *file = new FSFile; 1.236 + file->set_size(st.st_size); 1.237 + file->set_type(st_mode_to_type(st.st_mode)); 1.238 + child = file; 1.239 } 1.240 + add_child(child); 1.241 + child->set_name(ent->d_name); 1.242 } 1.243 + 1.244 + closedir(dir); 1.245 + 1.246 + expanded = true; 1.247 + return true; 1.248 } 1.249 -#endif 1.250 + 1.251 +// ---- FSFile ---- 1.252 + 1.253 +FSFile::FSFile() 1.254 +{ 1.255 + type = UNKNOWN; 1.256 + size = 0; 1.257 +} 1.258 + 1.259 +void FSFile::set_size(unsigned long s) 1.260 +{ 1.261 + size = s; 1.262 +} 1.263 + 1.264 +unsigned long FSFile::get_size() const 1.265 +{ 1.266 + return size; 1.267 +} 1.268 + 1.269 +// ---- static helpers ---- 1.270 + 1.271 +static bool childcmpless(const FSNode *aptr, const FSNode *bptr) 1.272 +{ 1.273 + return strcmp(aptr->get_name(), bptr->get_name()) < 0; 1.274 +} 1.275 1.276 static char *clean_path(char *path) 1.277 { 1.278 @@ -144,3 +328,25 @@ 1.279 } 1.280 return path; 1.281 } 1.282 + 1.283 +static FSNode::Type st_mode_to_type(mode_t mode) 1.284 +{ 1.285 + switch(mode & S_IFMT) { 1.286 + case S_IFDIR: 1.287 + return FSNode::DIRECTORY; 1.288 + case S_IFREG: 1.289 + return FSNode::REGFILE; 1.290 + case S_IFLNK: 1.291 + return FSNode::LINK; 1.292 + case S_IFBLK: 1.293 + case S_IFCHR: 1.294 + return FSNode::DEVICE; 1.295 + case S_IFSOCK: 1.296 + return FSNode::SOCKET; 1.297 + case S_IFIFO: 1.298 + return FSNode::FIFO; 1.299 + default: 1.300 + break; 1.301 + } 1.302 + return FSNode::UNKNOWN; 1.303 +}