duc_dir *duc_dir_openat(duc_dir *dir, const char *name) { if(strcmp(name, "..") == 0) { /* Special case: go up one directory */ if(dir->devino_parent.dev && dir->devino_parent.ino) { duc_dir *pdir = duc_dir_new(dir->duc, &dir->devino_parent); if(pdir == NULL) return NULL; pdir->path = duc_strdup(dir->path); dirname(pdir->path); return pdir; } } else { /* Find given name in dir */ size_t i; struct duc_dirent *e = dir->ent_list; for(i=0; i<dir->ent_count; i++) { if(strcmp(e->name, name) == 0) { return duc_dir_openent(dir, e); } e++; } } return NULL; }
struct ducrc *ducrc_new(const char *section) { struct ducrc *ducrc; ducrc = duc_malloc(sizeof *ducrc); ducrc->noptions = 0; ducrc->section = duc_strdup(section); return ducrc; }
int duc_dir_add_ent(struct duc_dir *dir, const char *name, off_t size_apparent, off_t size_actual, uint8_t type, dev_t dev, ino_t ino) { if((dir->ent_count+1) * sizeof(struct duc_dirent) > dir->ent_pool) { dir->ent_pool *= 2; dir->ent_list = duc_realloc(dir->ent_list, dir->ent_pool); } struct duc_dirent *ent = &dir->ent_list[dir->ent_count]; dir->ent_count ++; ent->name = duc_strdup(name); ent->size_apparent = size_apparent; ent->size_actual = size_actual; ent->type = type; ent->dev = dev; ent->ino = ino; return 0; }
duc_dir *duc_dir_open(struct duc *duc, const char *path) { /* Canonicalized path */ char *path_canon = duc_canonicalize_path(path); if(!path_canon) { duc->err = DUC_E_PATH_NOT_FOUND; return NULL; } /* Find top path in database */ char *path_try = duc_strdup(path_canon); int l = strlen(path_try); struct duc_devino devino = { 0, 0 }; while(l > 0) { path_try[l] = '\0'; struct duc_index_report *report; report = db_read_report(duc, path_try); if(report) { devino = report->devino; free(report); break; } l--; } free(path_try); if(l == 0) { duc_log(duc, DUC_LOG_FTL, "Path %s not found in database", path_canon); duc->err = DUC_E_PATH_NOT_FOUND; free(path_canon); return NULL; } struct duc_dir *dir; dir = duc_dir_new(duc, &devino); if(dir == NULL) { duc->err = DUC_E_PATH_NOT_FOUND; free(path_canon); return NULL; } char rest[DUC_PATH_MAX]; strncpy(rest, path_canon+l, sizeof rest); char *name = strtok(rest, "/"); while(dir && name) { struct duc_dirent *ent = duc_dir_find_child(dir, name); struct duc_dir *dir_next = NULL; if(ent) { dir_next = duc_dir_openent(dir, ent); } duc_dir_close(dir); dir = dir_next; name = strtok(NULL, "/"); } if(dir) { dir->path = strdup(path_canon); } free(path_canon); return dir; }