1 1.1 agc /* 2 1.1 agc * Copyright 2007 Alistair Crooks. All rights reserved. 3 1.1 agc * 4 1.1 agc * Redistribution and use in source and binary forms, with or without 5 1.1 agc * modification, are permitted provided that the following conditions 6 1.1 agc * are met: 7 1.1 agc * 1. Redistributions of source code must retain the above copyright 8 1.1 agc * notice, this list of conditions and the following disclaimer. 9 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright 10 1.1 agc * notice, this list of conditions and the following disclaimer in the 11 1.1 agc * documentation and/or other materials provided with the distribution. 12 1.1 agc * 3. The name of the author may not be used to endorse or promote 13 1.1 agc * products derived from this software without specific prior written 14 1.1 agc * permission. 15 1.1 agc * 16 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 1.1 agc * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 1.1 agc * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 1.1 agc * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 22 1.1 agc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 agc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 1.1 agc * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 1.1 agc * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 1.1 agc * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 agc */ 28 1.1 agc #include <sys/types.h> 29 1.1 agc #include <sys/stat.h> 30 1.1 agc 31 1.1 agc #include <ctype.h> 32 1.1 agc #include <dirent.h> 33 1.1 agc #include <err.h> 34 1.1 agc #include <errno.h> 35 1.1 agc #include <fcntl.h> 36 1.1 agc #include <fuse.h> 37 1.1 agc #include <signal.h> 38 1.1 agc #include <stdio.h> 39 1.1 agc #include <stdlib.h> 40 1.1 agc #include <string.h> 41 1.1 agc #include <time.h> 42 1.1 agc #include <unistd.h> 43 1.1 agc 44 1.1 agc #include "virtdir.h" 45 1.1 agc #include "defs.h" 46 1.1 agc 47 1.1 agc #ifndef PREFIX 48 1.1 agc #define PREFIX "" 49 1.1 agc #endif 50 1.1 agc 51 1.1 agc #ifndef DEF_CONF_FILE 52 1.1 agc #define DEF_CONF_FILE "/etc/icfs.conf" 53 1.1 agc #endif 54 1.1 agc 55 1.1 agc DEFINE_ARRAY(strv_t, char *); 56 1.1 agc 57 1.1 agc static struct stat vfs; /* stat info of directory */ 58 1.1 agc static virtdir_t tree; /* virtual directory tree */ 59 1.1 agc static int verbose; /* how chatty are we? */ 60 1.1 agc 61 1.1 agc 62 1.1 agc 63 1.1 agc 64 1.1 agc 65 1.1 agc /********************************************************************/ 66 1.1 agc 67 1.1 agc /* convert a string to lower case */ 68 1.1 agc static char * 69 1.1 agc strtolower(const char *path, char *name, size_t size) 70 1.1 agc { 71 1.1 agc const char *cp; 72 1.1 agc char *np; 73 1.1 agc 74 1.1 agc for (cp = path, np = name ; (int)(np - name) < size ; np++, cp++) { 75 1.1 agc *np = tolower((unsigned)*cp); 76 1.1 agc } 77 1.1 agc return name; 78 1.1 agc } 79 1.1 agc 80 1.1 agc /* add a name and its lower case entry */ 81 1.1 agc static void 82 1.1 agc add_entry(virtdir_t *tp, const char *name, uint8_t type) 83 1.1 agc { 84 1.1 agc char icname[MAXPATHLEN]; 85 1.1 agc char *root; 86 1.1 agc int len; 87 1.1 agc 88 1.1 agc root = virtdir_rootdir(&tree); 89 1.1 agc len = strlen(root); 90 1.1 agc strtolower(&name[len], icname, sizeof(icname)); 91 1.1 agc virtdir_add(tp, &name[len], strlen(name) - len, type, icname, 92 1.1 agc strlen(icname)); 93 1.1 agc } 94 1.1 agc 95 1.1 agc /* file system operations start here */ 96 1.1 agc 97 1.1 agc /* perform the stat operation */ 98 1.1 agc static int 99 1.1 agc icfs_getattr(const char *path, struct stat *st) 100 1.1 agc { 101 1.1 agc virt_dirent_t *ep; 102 1.1 agc char name[MAXPATHLEN]; 103 1.1 agc 104 1.1 agc (void) memset(st, 0x0, sizeof(*st)); 105 1.1 agc if (strcmp(path, "/") == 0) { 106 1.1 agc st->st_mode = S_IFDIR | 0755; 107 1.1 agc st->st_nlink = 2; 108 1.1 agc return 0; 109 1.1 agc } 110 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 111 1.1 agc return -ENOENT; 112 1.1 agc } 113 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 114 1.1 agc if (stat(name, st) < 0) { 115 1.1 agc return -errno; 116 1.1 agc } 117 1.1 agc return 0; 118 1.1 agc } 119 1.1 agc 120 1.1 agc /* readdir operation */ 121 1.1 agc static int 122 1.1 agc icfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, 123 1.1 agc off_t offset, struct fuse_file_info *fi) 124 1.1 agc { 125 1.1 agc virt_dirent_t *ep; 126 1.1 agc VIRTDIR *dirp; 127 1.1 agc char name[MAXPATHLEN]; 128 1.1 agc 129 1.1 agc (void) fi; 130 1.1 agc 131 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 132 1.1 agc return -ENOENT; 133 1.1 agc } 134 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 135 1.1 agc if ((dirp = openvirtdir(&tree, ep->name)) == NULL) { 136 1.1 agc return -ENOENT; 137 1.1 agc } 138 1.1 agc filler(buf, ".", NULL, 0); 139 1.1 agc filler(buf, "..", NULL, 0); 140 1.1 agc while ((ep = readvirtdir(dirp)) != NULL) { 141 1.1 agc strtolower(ep->d_name, name, sizeof(name)); 142 1.1 agc (void) filler(buf, name, NULL, 0); 143 1.1 agc } 144 1.1 agc (void) closevirtdir(dirp); 145 1.1 agc return 0; 146 1.1 agc } 147 1.1 agc 148 1.1 agc /* open the file in the file system */ 149 1.1 agc static int 150 1.1 agc icfs_open(const char *path, struct fuse_file_info *fi) 151 1.1 agc { 152 1.1 agc return 0; 153 1.1 agc } 154 1.1 agc 155 1.1 agc /* read the file's contents in the file system */ 156 1.1 agc static int 157 1.1 agc icfs_read(const char *path, char *buf, size_t size, off_t offset, 158 1.1 agc struct fuse_file_info * fi) 159 1.1 agc { 160 1.1 agc virt_dirent_t *ep; 161 1.1 agc char name[MAXPATHLEN]; 162 1.1 agc int fd; 163 1.1 agc int cc; 164 1.1 agc 165 1.1 agc (void) fi; 166 1.1 agc 167 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 168 1.1 agc return -ENOENT; 169 1.1 agc } 170 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 171 1.1 agc if ((fd = open(name, O_RDONLY, 0666)) < 0) { 172 1.1 agc return -ENOENT; 173 1.1 agc } 174 1.1 agc if (lseek(fd, offset, SEEK_SET) < 0) { 175 1.1 agc (void) close(fd); 176 1.1 agc return -EBADF; 177 1.1 agc } 178 1.1 agc if ((cc = read(fd, buf, size)) < 0) { 179 1.1 agc (void) close(fd); 180 1.1 agc return -errno; 181 1.1 agc } 182 1.1 agc (void) close(fd); 183 1.1 agc return cc; 184 1.1 agc } 185 1.1 agc 186 1.1 agc /* write the file's contents in the file system */ 187 1.1 agc static int 188 1.1 agc icfs_write(const char *path, const char *buf, size_t size, off_t offset, 189 1.1 agc struct fuse_file_info * fi) 190 1.1 agc { 191 1.1 agc virt_dirent_t *ep; 192 1.1 agc char name[MAXPATHLEN]; 193 1.1 agc int fd; 194 1.1 agc int cc; 195 1.1 agc 196 1.1 agc (void) fi; 197 1.1 agc 198 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 199 1.1 agc return -ENOENT; 200 1.1 agc } 201 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 202 1.1 agc if ((fd = open(name, O_WRONLY, 0666)) < 0) { 203 1.1 agc return -ENOENT; 204 1.1 agc } 205 1.1 agc if (lseek(fd, offset, SEEK_SET) < 0) { 206 1.1 agc (void) close(fd); 207 1.1 agc return -EBADF; 208 1.1 agc } 209 1.1 agc if ((cc = write(fd, buf, size)) < 0) { 210 1.1 agc (void) close(fd); 211 1.1 agc return -errno; 212 1.1 agc } 213 1.1 agc (void) close(fd); 214 1.1 agc return cc; 215 1.1 agc } 216 1.1 agc 217 1.1 agc /* fill in the statvfs struct */ 218 1.1 agc static int 219 1.1 agc icfs_statfs(const char *path, struct statvfs *st) 220 1.1 agc { 221 1.1 agc (void) memset(st, 0x0, sizeof(*st)); 222 1.1 agc st->f_bsize = st->f_frsize = st->f_iosize = 512; 223 1.1 agc st->f_owner = vfs.st_uid; 224 1.1 agc st->f_files = 1; 225 1.1 agc return 0; 226 1.1 agc } 227 1.1 agc 228 1.1 agc /* "remove" a file */ 229 1.1 agc static int 230 1.1 agc icfs_unlink(const char *path) 231 1.1 agc { 232 1.1 agc virt_dirent_t *ep; 233 1.1 agc char name[MAXPATHLEN]; 234 1.1 agc 235 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 236 1.1 agc return -ENOENT; 237 1.1 agc } 238 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 239 1.1 agc if (unlink(name) < 0) { 240 1.1 agc return -errno; 241 1.1 agc } 242 1.1 agc /* XXX - delete entry */ 243 1.1 agc return 0; 244 1.1 agc } 245 1.1 agc 246 1.1 agc /* check the access on a file */ 247 1.1 agc static int 248 1.1 agc icfs_access(const char *path, int acc) 249 1.1 agc { 250 1.1 agc virt_dirent_t *ep; 251 1.1 agc char name[MAXPATHLEN]; 252 1.1 agc 253 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 254 1.1 agc return -ENOENT; 255 1.1 agc } 256 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 257 1.1 agc if (access(name, acc) < 0) { 258 1.1 agc return -errno; 259 1.1 agc } 260 1.1 agc return 0; 261 1.1 agc } 262 1.1 agc 263 1.1 agc /* change the mode of a file */ 264 1.1 agc static int 265 1.1 agc icfs_chmod(const char *path, mode_t mode) 266 1.1 agc { 267 1.1 agc virt_dirent_t *ep; 268 1.1 agc char name[MAXPATHLEN]; 269 1.1 agc 270 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 271 1.1 agc return -ENOENT; 272 1.1 agc } 273 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 274 1.1 agc if (chmod(name, mode) < 0) { 275 1.1 agc return -errno; 276 1.1 agc } 277 1.1 agc return 0; 278 1.1 agc } 279 1.1 agc 280 1.1 agc /* change the owner and group of a file */ 281 1.1 agc static int 282 1.1 agc icfs_chown(const char *path, uid_t uid, gid_t gid) 283 1.1 agc { 284 1.1 agc virt_dirent_t *ep; 285 1.1 agc char name[MAXPATHLEN]; 286 1.1 agc 287 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 288 1.1 agc return -ENOENT; 289 1.1 agc } 290 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 291 1.1 agc if (lchown(name, uid, gid) < 0) { 292 1.1 agc return -errno; 293 1.1 agc } 294 1.1 agc return 0; 295 1.1 agc } 296 1.1 agc 297 1.1 agc /* "rename" a file */ 298 1.1 agc static int 299 1.1 agc icfs_rename(const char *from, const char *to) 300 1.1 agc { 301 1.1 agc #if 0 302 1.1 agc char fromname[MAXPATHLEN]; 303 1.1 agc char toname[MAXPATHLEN]; 304 1.1 agc 305 1.1 agc virt_dirent_t *ep; 306 1.1 agc 307 1.1 agc if ((ep = virtdir_find_tgt(&tree, from, strlen(from))) == NULL) { 308 1.1 agc return -ENOENT; 309 1.1 agc } 310 1.1 agc (void) snprintf(toname, sizeof(toname), "%s%s", dirs.v[0], to); 311 1.1 agc if (!mkdirs(toname)) { 312 1.1 agc return -ENOENT; 313 1.1 agc } 314 1.1 agc if (rename(fromname, toname) < 0) { 315 1.1 agc return -EPERM; 316 1.1 agc } 317 1.1 agc #endif 318 1.1 agc return 0; 319 1.1 agc } 320 1.1 agc 321 1.1 agc /* create a file */ 322 1.1 agc static int 323 1.1 agc icfs_create(const char *path, mode_t mode, struct fuse_file_info *fi) 324 1.1 agc { 325 1.1 agc virt_dirent_t *ep; 326 1.1 agc char *slash; 327 1.1 agc char name[MAXPATHLEN]; 328 1.1 agc int fd; 329 1.1 agc 330 1.1 agc if ((slash = strrchr(path, '/')) == NULL) { 331 1.1 agc return -ENOENT; 332 1.1 agc } 333 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, (int)(slash - path) - 1)) == NULL) { 334 1.1 agc return -ENOENT; 335 1.1 agc } 336 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s%s", virtdir_rootdir(&tree), ep->name, slash); 337 1.1 agc if ((fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { 338 1.1 agc return -EPERM; 339 1.1 agc } 340 1.1 agc (void) close(fd); 341 1.1 agc add_entry(&tree, name, 'f'); 342 1.1 agc return 0; 343 1.1 agc } 344 1.1 agc 345 1.1 agc /* create a special node */ 346 1.1 agc static int 347 1.1 agc icfs_mknod(const char *path, mode_t mode, dev_t d) 348 1.1 agc { 349 1.1 agc virt_dirent_t *ep; 350 1.1 agc char *slash; 351 1.1 agc char name[MAXPATHLEN]; 352 1.1 agc 353 1.1 agc if ((slash = strrchr(path, '/')) == NULL) { 354 1.1 agc return -ENOENT; 355 1.1 agc } 356 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, (int)(slash - path) - 1)) == NULL) { 357 1.1 agc return -ENOENT; 358 1.1 agc } 359 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s/%s", virtdir_rootdir(&tree), ep->name, slash + 1); 360 1.1 agc if (mknod(name, mode, d) < 0) { 361 1.1 agc return -EPERM; 362 1.1 agc } 363 1.1 agc add_entry(&tree, name, ((mode & S_IFMT) == S_IFCHR) ? 'c' : 'b'); 364 1.1 agc return 0; 365 1.1 agc } 366 1.1 agc 367 1.1 agc /* create a directory */ 368 1.1 agc static int 369 1.1 agc icfs_mkdir(const char *path, mode_t mode) 370 1.1 agc { 371 1.1 agc virt_dirent_t *ep; 372 1.1 agc char *slash; 373 1.1 agc char name[MAXPATHLEN]; 374 1.1 agc 375 1.1 agc if ((slash = strrchr(path, '/')) == NULL) { 376 1.1 agc return -ENOENT; 377 1.1 agc } 378 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, (int)(slash - path) - 1)) == NULL) { 379 1.1 agc return -EEXIST; 380 1.1 agc } 381 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s/%s", virtdir_rootdir(&tree), ep->name, slash + 1); 382 1.1 agc if (mkdir(name, mode) < 0) { 383 1.1 agc return -EPERM; 384 1.1 agc } 385 1.1 agc add_entry(&tree, name, 'd'); 386 1.1 agc return 0; 387 1.1 agc } 388 1.1 agc 389 1.1 agc /* create a symbolic link */ 390 1.1 agc static int 391 1.1 agc icfs_symlink(const char *path, const char *tgt) 392 1.1 agc { 393 1.1 agc virt_dirent_t *ep; 394 1.1 agc char *slash; 395 1.1 agc char name[MAXPATHLEN]; 396 1.1 agc 397 1.1 agc if ((slash = strrchr(path, '/')) == NULL) { 398 1.1 agc return -ENOENT; 399 1.1 agc } 400 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, (int)(slash - path) - 1)) == NULL) { 401 1.1 agc return -EEXIST; 402 1.1 agc } 403 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s/%s", virtdir_rootdir(&tree), ep->name, slash + 1); 404 1.1 agc if (symlink(name, tgt) < 0) { 405 1.1 agc return -EPERM; 406 1.1 agc } 407 1.1 agc add_entry(&tree, name, 'l'); 408 1.1 agc return 0; 409 1.1 agc } 410 1.1 agc 411 1.1 agc /* create a link */ 412 1.1 agc static int 413 1.1 agc icfs_link(const char *path, const char *tgt) 414 1.1 agc { 415 1.1 agc virt_dirent_t *ep; 416 1.1 agc char *slash; 417 1.1 agc char name[MAXPATHLEN]; 418 1.1 agc 419 1.1 agc if ((slash = strrchr(path, '/')) == NULL) { 420 1.1 agc return -ENOENT; 421 1.1 agc } 422 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, (int)(slash - path) - 1)) == NULL) { 423 1.1 agc return -EEXIST; 424 1.1 agc } 425 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s/%s", virtdir_rootdir(&tree), ep->name, slash + 1); 426 1.1 agc if (link(name, tgt) < 0) { 427 1.1 agc return -errno; 428 1.1 agc } 429 1.1 agc add_entry(&tree, name, 'f'); /* XXX */ 430 1.1 agc return 0; 431 1.1 agc } 432 1.1 agc 433 1.1 agc /* read the contents of a symbolic link */ 434 1.1 agc static int 435 1.1 agc icfs_readlink(const char *path, char *buf, size_t size) 436 1.1 agc { 437 1.1 agc virt_dirent_t *ep; 438 1.1 agc char name[MAXPATHLEN]; 439 1.1 agc 440 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 441 1.1 agc return -ENOENT; 442 1.1 agc } 443 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 444 1.1 agc if (readlink(name, buf, size) < 0) { 445 1.1 agc return -errno; 446 1.1 agc } 447 1.1 agc return 0; 448 1.1 agc } 449 1.1 agc 450 1.1 agc /* remove a directory */ 451 1.1 agc static int 452 1.1 agc icfs_rmdir(const char *path) 453 1.1 agc { 454 1.1 agc virt_dirent_t *ep; 455 1.1 agc char name[MAXPATHLEN]; 456 1.1 agc 457 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 458 1.1 agc return -ENOENT; 459 1.1 agc } 460 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 461 1.1 agc if (rmdir(name) < 0) { 462 1.1 agc return -errno; 463 1.1 agc } 464 1.1 agc /* XXX - delete entry */ 465 1.1 agc return 0; 466 1.1 agc } 467 1.1 agc 468 1.1 agc /* truncate a file */ 469 1.1 agc static int 470 1.1 agc icfs_truncate(const char *path, off_t size) 471 1.1 agc { 472 1.1 agc virt_dirent_t *ep; 473 1.1 agc char name[MAXPATHLEN]; 474 1.1 agc 475 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 476 1.1 agc return -ENOENT; 477 1.1 agc } 478 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 479 1.1 agc if (truncate(name, size) < 0) { 480 1.1 agc return -errno; 481 1.1 agc } 482 1.1 agc return 0; 483 1.1 agc } 484 1.1 agc 485 1.1 agc /* set utimes on a file */ 486 1.1 agc static int 487 1.1 agc icfs_utime(const char *path, struct utimbuf *t) 488 1.1 agc { 489 1.1 agc virt_dirent_t *ep; 490 1.1 agc char name[MAXPATHLEN]; 491 1.1 agc 492 1.1 agc if ((ep = virtdir_find_tgt(&tree, path, strlen(path))) == NULL) { 493 1.1 agc return -ENOENT; 494 1.1 agc } 495 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", virtdir_rootdir(&tree), ep->name); 496 1.1 agc if (utime(name, t) < 0) { 497 1.1 agc return -errno; 498 1.1 agc } 499 1.1 agc return 0; 500 1.1 agc } 501 1.1 agc 502 1.1 agc /* operations struct */ 503 1.1 agc static struct fuse_operations icfs_oper = { 504 1.1 agc .getattr = icfs_getattr, 505 1.1 agc .readlink = icfs_readlink, 506 1.1 agc .mknod = icfs_mknod, 507 1.1 agc .mkdir = icfs_mkdir, 508 1.1 agc .unlink = icfs_unlink, 509 1.1 agc .rmdir = icfs_rmdir, 510 1.1 agc .symlink = icfs_symlink, 511 1.1 agc .rename = icfs_rename, 512 1.1 agc .link = icfs_link, 513 1.1 agc .chmod = icfs_chmod, 514 1.1 agc .chown = icfs_chown, 515 1.1 agc .truncate = icfs_truncate, 516 1.1 agc .utime = icfs_utime, 517 1.1 agc .open = icfs_open, 518 1.1 agc .read = icfs_read, 519 1.1 agc .write = icfs_write, 520 1.1 agc .statfs = icfs_statfs, 521 1.1 agc .readdir = icfs_readdir, 522 1.1 agc .access = icfs_access, 523 1.1 agc .create = icfs_create 524 1.1 agc }; 525 1.1 agc 526 1.1 agc /* build up a virtdir from the information in the file system */ 527 1.1 agc static int 528 1.1 agc dodir(virtdir_t *tp, char *rootdir, const char *subdir) 529 1.1 agc { 530 1.1 agc struct dirent *dp; 531 1.1 agc struct stat st; 532 1.1 agc struct stat dir; 533 1.1 agc struct stat f; 534 1.1 agc struct stat l; 535 1.1 agc char icname[MAXPATHLEN]; 536 1.1 agc char name[MAXPATHLEN]; 537 1.1 agc char type; 538 1.1 agc DIR *dirp; 539 1.1 agc int len; 540 1.1 agc 541 1.1 agc if (tp->v == NULL) { 542 1.1 agc (void) stat(".", &dir); 543 1.1 agc (void) memcpy(&f, &dir, sizeof(f)); 544 1.1 agc f.st_mode = S_IFREG | 0644; 545 1.1 agc (void) memcpy(&l, &f, sizeof(l)); 546 1.1 agc l.st_mode = S_IFLNK | 0755; 547 1.1 agc virtdir_init(tp, rootdir, &dir, &f, &l); 548 1.1 agc virtdir_add(tp, "/", 1, 'd', "/", 1); 549 1.1 agc } 550 1.1 agc (void) snprintf(name, sizeof(name), "%s/%s", rootdir, subdir); 551 1.1 agc if ((dirp = opendir(name)) == NULL) { 552 1.1 agc warn("dodir: can't opendir `%s'", name); 553 1.1 agc return 0; 554 1.1 agc } 555 1.1 agc len = strlen(tp->rootdir); 556 1.1 agc while ((dp = readdir(dirp)) != NULL) { 557 1.1 agc if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) { 558 1.1 agc continue; 559 1.1 agc } 560 1.1 agc (void) snprintf(name, sizeof(name), "%s%s%s%s%s", rootdir, (subdir[0] == 0x0) ? "" : "/", subdir, "/", dp->d_name); 561 1.1 agc if (stat(name, &st) < 0) { 562 1.1 agc warnx("can't stat `%s'", name); 563 1.1 agc continue; 564 1.1 agc } 565 1.1 agc switch (st.st_mode & S_IFMT) { 566 1.1 agc case S_IFDIR: 567 1.1 agc type = 'd'; 568 1.1 agc break; 569 1.1 agc case S_IFREG: 570 1.1 agc type = 'f'; 571 1.1 agc break; 572 1.1 agc case S_IFLNK: 573 1.1 agc type = 'l'; 574 1.1 agc break; 575 1.1 agc case S_IFBLK: 576 1.1 agc type = 'b'; 577 1.1 agc break; 578 1.1 agc case S_IFCHR: 579 1.1 agc type = 'c'; 580 1.1 agc break; 581 1.1 agc default: 582 1.1 agc type = '?'; 583 1.1 agc break; 584 1.1 agc } 585 1.1 agc if (!virtdir_find(tp, &name[len], strlen(name) - len)) { 586 1.1 agc strtolower(&name[len], icname, sizeof(icname)); 587 1.1 agc virtdir_add(tp, &name[len], strlen(name) - len, type, icname, 588 1.1 agc strlen(icname)); 589 1.1 agc } 590 1.1 agc if (type == 'd') { 591 1.1 agc dodir(tp, rootdir, &name[len + 1]); 592 1.1 agc } 593 1.1 agc } 594 1.1 agc (void) closedir(dirp); 595 1.1 agc return 1; 596 1.1 agc } 597 1.1 agc 598 1.1 agc int 599 1.1 agc main(int argc, char **argv) 600 1.1 agc { 601 1.1 agc int i; 602 1.1 agc 603 1.1 agc while ((i = getopt(argc, argv, "f:v")) != -1) { 604 1.1 agc switch(i) { 605 1.1 agc case 'v': 606 1.1 agc verbose = 1; 607 1.1 agc break; 608 1.1 agc } 609 1.1 agc } 610 1.1 agc #if 0 611 1.1 agc (void) daemon(1, 1); 612 1.1 agc #endif 613 1.1 agc dodir(&tree, argv[optind], ""); 614 1.1 agc return fuse_main(argc, argv, &icfs_oper, NULL); 615 1.1 agc } 616