/* Use parent_entry to make filtered list not empty, or create such entry (if * parent_entry is NULL) and put it to original list. */ static void ensure_filtered_list_not_empty(view_t *view, dir_entry_t *parent_entry) { if(view->list_rows != 0U) { return; } if(parent_entry == NULL) { add_parent_dir(view); if(view->list_rows > 0) { (void)add_dir_entry(&view->local_filter.unfiltered, &view->local_filter.unfiltered_count, &view->dir_entry[view->list_rows - 1]); } } else { size_t list_size = 0U; (void)add_dir_entry(&view->dir_entry, &list_size, parent_entry); view->list_rows = list_size; } }
static struct dir_info *dir_new(struct dir_info *parent, const char *name) { struct dir_info *dir; size_t sz; char *path; path = dir_path(parent, name); if (mkdir(path, 0777) == -1) { CHECK(errno == ENOSPC); full = 1; free(path); return NULL; } free(path); sz = sizeof(struct dir_info); dir = (struct dir_info *) malloc(sz); CHECK(dir != NULL); memset(dir, 0, sz); dir->name = copy_string(name); dir->parent = parent; if (parent) add_dir_entry(parent, 'd', name, dir); return dir; }
static struct file_info *file_new(struct dir_info *parent, const char *name) { struct file_info *file = NULL; char *path; mode_t mode; int fd; size_t sz; CHECK(parent != NULL); path = dir_path(parent, name); mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; fd = open(path, O_CREAT | O_EXCL | O_RDWR, mode); if (fd == -1) { CHECK(errno == ENOSPC); free(path); full = 1; return NULL; } free(path); sz = sizeof(struct file_info); file = (struct file_info *) malloc(sz); CHECK(file != NULL); memset(file, 0, sz); file->name = copy_string(name); add_dir_entry(parent, 'f', name, file); add_fd(file, fd); return file; }
static void link_new(struct dir_info *parent, const char *name, struct file_info *file) { struct dir_entry_info *entry; char *path, *target; int ret; if (!file) return; entry = file->links; if (!entry) return; path = dir_path(parent, name); target = dir_path(entry->parent, entry->name); ret = link(target, path); if (ret == -1) { CHECK(errno == ENOSPC); free(target); free(path); full = 1; return; } free(target); free(path); add_dir_entry(parent, 'f', name, file); }
// compress current chunk and write it to file, // also update directory map void write_current_chunk(void) { // uncompressed chunk size unsigned long cs = thePandalog->chunk.buf_p - thePandalog->chunk.buf; unsigned long ccs = thePandalog->chunk.zsize; int ret; // loop allows compress2 to fail and resize output buffer as needed // not sure why compress2 needs output buf to be bigger than input // even though ultimately it is smaller. scratch space? // 10 is just a random guess. shouldn't need more than 1 re-try uint32_t i; for (i=0; i<10; i++) { ret = compress2(thePandalog->chunk.zbuf, &ccs, thePandalog->chunk.buf, cs, Z_BEST_COMPRESSION); if (ret == Z_OK) break; // bigger output buffer needed to perform compression? thePandalog->chunk.zsize *= 2; thePandalog->chunk.zbuf = (unsigned char *) realloc(thePandalog->chunk.zbuf, thePandalog->chunk.zsize); assert (thePandalog->chunk.zbuf != NULL); } // ccs is final compressed chunk size assert (ret == Z_OK); assert(ccs > 0); assert(cs >= ccs); printf ("writing chunk %d of pandalog %d / %d = %.2f compression\n", (int) thePandalog->chunk_num, (int) cs, (int) ccs, ((float) cs) / ((float) ccs)); fwrite(thePandalog->chunk.zbuf, 1, ccs, thePandalog->file); add_dir_entry(thePandalog->chunk_num); // reset start instr / pos thePandalog->chunk.start_instr = rr_get_guest_instr_count(); thePandalog->chunk.start_pos = ftell(thePandalog->file); // rewind chunk buf and inc chunk # thePandalog->chunk.buf_p = thePandalog->chunk.buf; thePandalog->chunk_num ++; thePandalog->chunk.ind_entry = 0; }
/* First information such as permissions is gathered for each directory entry. * Finally the sorted entries are added to the @data->fragment one by one. */ static inline void add_dir_entries(struct directory_entry *entries, unsigned char *dirpath, struct string *page) { unsigned char dircolor[8]; int dirpathlen = strlen((const char *)dirpath); int i; /* Setup @dircolor so it's easy to check if we should color dirs. */ if (get_opt_bool((const unsigned char *)"document.browse.links.color_dirs", NULL)) { color_to_string(get_opt_color((const unsigned char *)"document.colors.dirs", NULL), (unsigned char *) &dircolor); } else { dircolor[0] = 0; } for (i = 0; entries[i].name; i++) { add_dir_entry(&entries[i], page, dirpathlen, dircolor); mem_free(entries[i].attrib); mem_free(entries[i].name); } /* We may have allocated space for entries but added none. */ mem_free_if(entries); }
int ext2_rename(inode_t *old_dir, dentry_t *old_dentry, inode_t *new_dir, dentry_t *new_dentry) { // Remove inode from parent dir. remove_dir_entry((ext2_fs_instance_t*)old_dir->i_instance, old_dir->i_ino, old_dentry->d_name); add_dir_entry((ext2_fs_instance_t*)new_dir->i_instance, new_dir->i_ino, new_dentry->d_name, EXT2_FT_REG_FILE, old_dentry->d_inode->i_ino); //XXX return 0; }
int pandalog_close_write(void) { // finish current chunk then write directory info and header write_current_chunk(); // Not a mistake! // this will add one more dir entry for last instr and file pos add_dir_entry(thePandalog->chunk_num); write_dir(); return 0; }
void list_path(char *path, list_t *list) { int fd; int n = 0; iox_dirent_t buf; if(!strncmp(path,"cdfs:",5)) { CDVD_FlushCache(); } // Add fake .. directory entry add_reg_entry(list->entries, "..", n++); // Try to open the path if((fd=fileXioDopen(path)) < 0) { list->num = n; return; } else { // Add directories first while(fileXioDread(fd, &buf) > 0) { if(buf.stat.mode & FIO_S_IFDIR && (!strcmp(buf.name,".") || !strcmp(buf.name,".."))) continue; if(buf.stat.mode & FIO_S_IFDIR) { add_dir_entry(list->entries, buf.name, n++); } if (buf.stat.mode & FIO_S_IFREG) { add_reg_entry(list->entries, buf.name, n++); } // Prevent overflowing the list if (n >= list->size) { break; } } list->num = n; fileXioDclose(fd); } }
static void hash_index_entry(struct index_state *istate, struct cache_entry *ce) { if (ce->ce_flags & CE_HASHED) return; ce->ce_flags |= CE_HASHED; hashmap_entry_init(ce, memihash(ce->name, ce_namelen(ce))); hashmap_add(&istate->name_hash, ce); if (ignore_case) add_dir_entry(istate, ce); }
static struct inode *open_always(struct filsys *fs, char *name, int len, int mode) { struct inode *dir; struct inode *inode; vfs_ino_t ino; dir = parse_name(fs, &name, &len); if (!dir) return NULL; ino = find_dir_entry(dir, name, len); if (ino == -1) { inode = alloc_inode(dir, VFS_S_IFREG | mode); if (!inode) { release_inode(dir); return NULL; } inode->desc->linkcount++; mark_inode_dirty(inode); if (add_dir_entry(dir, name, len, inode->ino) < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return NULL; } } else { inode = get_inode(fs, ino); if (!inode) { release_inode(dir); return NULL; } if (VFS_S_ISDIR(inode->desc->mode)) { release_inode(dir); release_inode(inode); return NULL; } } release_inode(dir); return inode; }
struct file_synch_status *status_for_inode (struct inode *inode) { if (inode_get_inumber (inode) == FREE_MAP_SECTOR) return &free_map_synch; lock_acquire (&(fm->file_map_lock)); struct fpm_info *start = fm->fp_map[hash_inode(inode)]; while (start) { if (start->inode == inode) break; start = start->next; } struct file_synch_status *retval = (start == NULL) ? add_dir_entry (inode) : &start->status; lock_release (&(fm->file_map_lock)); return retval; }
static int create_new(struct filsys *fs, char *name, ino_t ino, int mode, struct inode **retval) { struct inode *dir; struct inode *inode; int rc; int len = strlen(name); rc = diri(fs, &name, &len, &dir); if (rc < 0) return rc; rc = find_dir_entry(dir, name, len, NULL); if (rc != -ENOENT) { release_inode(dir); return rc >= 0 ? -EEXIST : rc; } if (ino == NOINODE) { inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO)); if (!inode) rc = -ENOSPC; } else { rc = get_inode(fs, ino, &inode); if (rc < 0) inode = NULL; if (inode) { inode->desc->ctime = inode->desc->mtime = time(NULL); inode->desc->uid = inode->desc->gid = 0; inode->desc->mode = S_IFREG | 0700; inode->desc->linkcount++; mark_inode_dirty(inode); } } if (!inode) { release_inode(dir); return rc; } rc = add_dir_entry(dir, name, len, inode->ino); if (rc < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return rc; } release_inode(dir); *retval = inode; return 0; }
static void symlink_new(struct dir_info *dir, const char *name) { struct symlink_info *s; char *path; size_t sz; sz = sizeof(struct symlink_info); s = malloc(sz); CHECK(s != NULL); memset(s, 0, sz); add_dir_entry(dir, 's', name, s); path = dir_path(dir, name); s->target_pathname = pick_symlink_target(path); CHECK(symlink(s->target_pathname, path) != -1); free(path); }
static struct inode *create_new(struct filsys *fs, char *name, int len, int mode) { struct inode *dir; struct inode *inode; struct inode *oldinode; vfs_ino_t oldino; dir = parse_name(fs, &name, &len); if (!dir) return NULL; inode = alloc_inode(dir, VFS_S_IFREG | mode); if (!inode) { release_inode(dir); return NULL; } inode->desc->linkcount++; mark_inode_dirty(inode); oldino = modify_dir_entry(dir, name, len, inode->ino); if (oldino != -1) { oldinode = get_inode(fs, oldino); if (oldinode) { unlink_inode(oldinode); release_inode(oldinode); } } else { if (add_dir_entry(dir, name, len, inode->ino) < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return NULL; } } release_inode(dir); return inode; }
static struct inode *create_always(struct filsys *fs, char *name, int len, vfs_ino_t ino, int mode) { struct inode *dir; struct inode *inode; dir = parse_name(fs, &name, &len); if (!dir) return NULL; if (find_dir_entry(dir, name, len) != -1) { release_inode(dir); return NULL; } if (ino == -1) inode = alloc_inode(dir, VFS_S_IFREG | mode); else { inode = get_inode(fs, ino); if (inode->desc->ctime == 0) inode->desc->ctime = time(NULL); inode->desc->mode = VFS_S_IFREG | mode; } if (!inode) { release_inode(dir); return NULL; } inode->desc->linkcount++; mark_inode_dirty(inode); if (add_dir_entry(dir, name, len, inode->ino) < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return NULL; } release_inode(dir); return inode; }
static int open_always(struct filsys *fs, char *name, int mode, struct inode **retval) { struct inode *dir; struct inode *inode; ino_t ino; int rc; int len = strlen(name); rc = diri(fs, &name, &len, &dir); if (rc < 0) return rc; rc = find_dir_entry(dir, name, len, &ino); if (rc < 0 && rc != -ENOENT) { release_inode(dir); return rc; } if (rc == -ENOENT) { inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO)); if (!inode) { release_inode(dir); return -ENOSPC; } rc = add_dir_entry(dir, name, len, inode->ino); if (rc < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return rc; } } else { rc = get_inode(fs, ino, &inode); if (rc < 0) { release_inode(dir); return rc; } } release_inode(dir); *retval = inode; return 0; }
void filters_drop_temporaries(view_t *view, dir_entry_t entries[]) { /* This is basically a simplified version of update_filtering_lists(). Not * sure if it's worth merging them. */ int i; size_t list_size = 0U; for(i = 0; i < view->list_rows; ++i) { dir_entry_t *new_entry; dir_entry_t *const entry = &view->dir_entry[i]; /* The tag field links to position of nodes passed through filter in the * list of visible files. Removed nodes have -1. */ entry->tag = -1; if(entry->temporary) { fentry_free(view, entry); continue; } new_entry = add_dir_entry(&entries, &list_size, entry); if(new_entry != NULL) { entry->tag = list_size - 1U; /* We basically grow the tree node by node while performing * reparenting. */ reparent_tree_node(entry, new_entry); } } dynarray_free(view->dir_entry); view->dir_entry = entries; view->list_rows = list_size; }
/* Copies/moves elements of the unfiltered list into dir_entry list. add * parameter controls whether entries matching filter are copied into dir_entry * list. clear parameter controls whether entries not matching filter are * cleared in unfiltered list. Returns zero unless addition is performed in * which case can return non-zero when all files got filtered out. */ static int update_filtering_lists(view_t *view, int add, int clear) { /* filters_drop_temporaries() is a similar function. */ size_t i; size_t list_size = 0U; dir_entry_t *parent_entry = NULL; int parent_added = 0; for(i = 0; i < view->local_filter.unfiltered_count; ++i) { /* FIXME: some very long file names won't be matched against some * regexps. */ char name_with_slash[NAME_MAX + 1 + 1]; dir_entry_t *const entry = &view->local_filter.unfiltered[i]; const char *name = entry->name; if(is_parent_dir(name)) { if(entry->child_pos == 0) { parent_entry = entry; if(add && cfg_parent_dir_is_visible(is_root_dir(view->curr_dir))) { (void)add_dir_entry(&view->dir_entry, &list_size, entry); parent_added = 1; } continue; } else if(!filter_is_empty(&view->local_filter.filter)) { if(clear) { fentry_free(view, entry); } continue; } } if(fentry_is_dir(entry)) { append_slash(name, name_with_slash, sizeof(name_with_slash)); name = name_with_slash; } /* tag links to position of nodes passed through filter in list of visible * files. Nodes that didn't pass have -1. */ entry->tag = -1; if(filter_matches(&view->local_filter.filter, name) != 0) { if(add) { dir_entry_t *e = add_dir_entry(&view->dir_entry, &list_size, entry); if(e != NULL) { entry->tag = list_size - 1U; /* We basically grow the tree node by node while performing * reparenting. */ reparent_tree_node(entry, e); } } } else { if(clear) { fentry_free(view, entry); } } } if(clear) { /* XXX: the check of name pointer is horrible, but is needed to prevent * freeing of entry in use. */ if(!parent_added && parent_entry != NULL && list_size != 0U && view->dir_entry[0].name != parent_entry->name) { fentry_free(view, parent_entry); } } if(add) { view->list_rows = list_size; view->filtered = view->local_filter.prefiltered_count + view->local_filter.unfiltered_count - list_size; ensure_filtered_list_not_empty(view, parent_entry); return list_size == 0U || (list_size == 1U && parent_added && (filter_matches(&view->local_filter.filter, "../") == 0)); } return 0; }
int syscall_rename(const char *a_oldpath, const char *a_newpath) { int ohandle, nhandle; int drive1, drive2; char dir_path1[512], dir_path2[512]; char name_comp1[13], name_comp2[13], conv_name1[11], conv_name2[11]; char oldpath[512], newpath[512]; struct dir_entry dent1, dent2; int exist1, exist2; struct DIR_FILE *dirf; int len1, len2; int i,t; len1 = strlen(a_oldpath); len2 = strlen(a_newpath); if (len1 > 512 || len2 > 512) return ELONGPATH; strcpy(oldpath,a_oldpath); strcpy(newpath,a_newpath); if (oldpath[len1-1] == '/' || oldpath[len1-1] == '\\') oldpath[len1-1] = '\0'; if (newpath[len2-1] == '/' || newpath[len2-1] == '\\') newpath[len2-1] = '\0'; parse_path(oldpath, &drive1, dir_path1, name_comp1); parse_path(newpath, &drive2, dir_path2, name_comp2); if (drive1 != drive2) return EDEVICE_DIFFERENT; nhandle = open_path(drive2, dir_path2); if (nhandle < 0) return nhandle; if (name_comp2[0] !='\0') { if (convert_name(name_comp2, conv_name2) < 0) { close_dir(nhandle); return EINVALIDNAME; // Error } exist2 = find_entry(nhandle, conv_name2, &dent2); } ohandle = open_path(drive1, dir_path1); if (ohandle < 0) { close_dir(nhandle); return ohandle; } if (name_comp1[0] != '\0') { if (convert_name(name_comp1, conv_name1) < 0) { close_dir(nhandle); close_dir(ohandle); return EINVALIDNAME; // Error } exist1 = find_entry(ohandle, conv_name1, &dent1); } // Check whether new path exists and is removable if ((exist2 == 1) && ((dent2.attrib & FTYPE_READONLY) || ((dent2.attrib & FTYPE_DIR) && (empty_dir(nhandle, &dent2) != 1)))) { close_dir(nhandle); close_dir(ohandle); return ETARGET_EXISTS; } // Check if source exists and is movable if (exist1 != 1) { close_dir(nhandle); close_dir(ohandle); return EPATH_NOT_EXISTS; } if ((dent1.attrib & FTYPE_READONLY) != 0) { close_dir(nhandle); close_dir(ohandle); return EREADONLY; } // Check whether oldpath is not a subpath of newpath if ((dent1.attrib & FTYPE_DIR) && (ohandle != nhandle)) { t = nhandle; dirf = &dir_file_list[t]; while (dirf->parent_index >= 0 && dirf->parent_index != ohandle) { t = dirf->parent_index; dirf = &dir_file_list[t]; } if (dirf->parent_index == ohandle) { close_dir(nhandle); close_dir(ohandle); return EOLDPATH_PARENT_OF_NEWPATH; } } // Check if newpath already exists whether it is compatible or not if ((exist2 == 1) && (((dent1.attrib & FTYPE_DIR) != 0 && (dent2.attrib & FTYPE_DIR) == 0) || ((dent1.attrib & FTYPE_DIR) == 0 && (dent2.attrib & FTYPE_DIR) != 0))) { close_dir(nhandle); close_dir(ohandle); return ESRC_DEST_NOT_SAME_TYPE; } // Remove destination entry if exists if (exist2 == 1) { if (dent2.attrib & FTYPE_DIR) syscall_rmdir(newpath); else syscall_unlink(newpath); } // Add the source dir entry after changing the name // to destination directory bcopy( (char *)&dent1, (char *)&dent2, sizeof(struct dir_entry)); for (i=0; i<11; i++) // Both name and extension dent2.name[i] = conv_name2[i]; t = add_dir_entry(nhandle, &dent2); if (t == 1) { delete_dir_entry(ohandle, dent1.name); } // Close the handles of parent directories close_dir(ohandle); close_dir(nhandle); if (t == 1) return 0; else return t; }
// Used to move a file unsigned int fs_mv(char * name, char * newname, int from_inode) { int i1 = fs_open_file(name, from_inode, O_WR | O_RD, EXT2_S_IFREG); if(i1 < 0) { return i1; // If there's an error with the first name then there's nothing to do actually. } int i2 = fs_indir(newname, from_inode); if(i2 == 0) { folder_rem_direntry(i1, n._dir_inode); inode_read(from_inode, &n); int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, newname, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(from_inode, &n); return 1; } else { inode_read(i2, &n); if(!fs_has_perms(&n, ACTION_READ)) { return ERR_PERMS; } if(!(n.mode & EXT2_S_IFDIR)) { return ERR_INVALID_TYPE; } if (fs_indir(name, i2)) { return ERR_REPEATED; } int log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i1, name, &log_block); log_block_write(&n, &log_block); n.blocks = log_block * 2; inode_write(i2, &n); inode_read(i1, &n); folder_rem_direntry(i1, n._dir_inode); inode_read(i1, &n); folder_rem_direntry(n._dir_inode, i1); log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, i2, "..", &log_block); log_block_write(&n, &log_block); n._dir_inode = i2; inode_write(i1, &n); } return i1; }
// Makes a new directory unsigned int fs_mkdir(char * name, unsigned int parent_inode) { unsigned int inode_id = 0; if ((inode_id = fs_indir(name, parent_inode))) { return 0; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!parent_inode) { parent_inode = inode_id; } int log_block; if (parent_inode != inode_id) { inode_read(parent_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(parent_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = EXT2_S_IFDIR; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; add_dir_entry(&n, EXT2_FT_DIR, inode_id, ".", &log_block); add_dir_entry(&n, EXT2_FT_DIR, parent_inode, "..", &log_block); log_block_write(&n, &log_block); n.blocks = (log_block) * 2; n.i_file_acl = 511; n._dir_inode = parent_inode; n._last_write_offset = dir_op_offset; inode_write(inode_id, &n); fs_bitmaps_write_all(); return inode_id; }
// Opens a file unsigned int fs_open_file(char * name, unsigned int folder_inode, int mode, int type) { unsigned int inode_id = 0; if(strcmp(name, "/") == 0 && strlen(name) == strlen("/")) { return 1; // root } if(name[0] == 0) { inode_id = current_ttyc()->pwd; } else { inode_id = fs_indir(name, folder_inode); } if (inode_id) { if (mode & O_CREAT) { int _rm_res = fs_rm(inode_id, 0); if(_rm_res < 0) { return _rm_res; } } else if(mode & O_NEW) { inode_read(inode_id, &n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { inode_read(inode_id, &n); int can = 1; if((mode & O_RD) && !fs_has_perms(&n, ACTION_READ)) { can = 0; } if((mode & O_WR) && !fs_has_perms(&n, ACTION_WRITE)) { can = 0; } if(can || !fs_done) { if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; } else { return ERR_PERMS; } } } else if (!(mode & (O_NEW | O_CREAT))) { return ERR_NO_EXIST; } inode_id = bitmap_first_valued(bm_inodes, FS_INODE_BITMAP_SIZE, 0) + 1; if (!folder_inode) { folder_inode = inode_id; } int log_block; if (folder_inode != inode_id) { inode_read(folder_inode, &n); if(!fs_has_perms(&n, ACTION_WRITE)) { return ERR_PERMS; } log_block = n.blocks / 2; block_clear(&b); dir_op_offset = 0; log_block_read(&n, &log_block); add_dir_entry(&n, EXT2_FT_DIR, inode_id, name, &log_block); log_block_write(&n, &log_block); inode_write(folder_inode, &n); } bitmap_write(bm_inodes, inode_id - 1, 1); inode_clear(&n); if(!fs_done) { n.uid = 0; } else { n.uid = current_ttyc()->uid; } n.mode = type; n.size = 0; n.blocks = 0; // Beware! This represents the SECTORS! n._last_write_offset = 0; n.i_file_acl = 511; n._dir_inode = folder_inode; inode_write(inode_id, &n); inode_clear(&n); if(n.mode == EXT2_S_IFLNK) { return n.data_blocks[0]; } return inode_id; }
static callback_ret_t readdir_callback(CFStringRef inkey, CFStringRef value, void *udata) { char *str; CFIndex inkeylen, value_len; struct dir_cbdata *temp = (struct dir_cbdata *)udata; struct dir_entry **list = temp->list; struct dir_entry *last = temp->last; char key[MAXFILENAMELEN+1]; char linebuf[LINESZ], lineqbuf[LINESZ]; int error; if (trace > 1) { str = od_CFStringtoCString(inkey); if (str != NULL) { trace_prt(1, " readdir_callback called: key %s\n", str); free(str); } } inkeylen = od_cfstrlen(inkey); if (inkeylen > (CFIndex)MAXFILENAMELEN) return (OD_CB_KEEPGOING); if (inkeylen == 0) return (OD_CB_KEEPGOING); /* ignore empty lines */ if (!od_cfstrlcpy(key, inkey, inkeylen)) return (OD_CB_KEEPGOING); if (isspace((unsigned char)key[0]) || key[0] == '#') return (OD_CB_KEEPGOING); /* ignore blank lines and comments */ /* * Wildcard entry should be ignored - following entries should continue * to be read to corroborate with the way we search for entries in * LDAP, i.e., first for an exact key match and then a wildcard * if there's no exact key match. */ if (key[0] == '*' && key[1] == '\0') return (OD_CB_KEEPGOING); value_len = od_cfstrlen(value); if (value_len >= LINESZ) return (OD_CB_KEEPGOING); if (value_len < 2) return (OD_CB_KEEPGOING); if (!od_cfstrlcpy(linebuf, value, value_len)) return (OD_CB_KEEPGOING); unquote(linebuf, lineqbuf); error = add_dir_entry(key, linebuf, lineqbuf, list, &last); if (error != -1) { if (error != 0) { temp->error = error; return (OD_CB_ERROR); } temp->last = last; } if (trace > 1) trace_prt(1, "readdir_callback returning OD_CB_KEEPGOING...\n"); return (OD_CB_KEEPGOING); }
static void rename_entry(struct dir_entry_info *entry) { struct dir_entry_info *rename_entry = NULL; struct dir_info *parent; char *path, *to, *name; int ret, isdir, retry; if (!entry->parent) return; for (retry = 0; retry < 3; retry++) { path = dir_path(entry->parent, entry->name); isdir = entry->type == 'd' ? 1 : 0; name = pick_rename_name(&parent, &rename_entry, isdir); to = dir_path(parent, name); /* * Check we are not trying to move a directory to a subdirectory * of itself. */ if (isdir) { struct dir_info *p; for (p = parent; p; p = p->parent) if (p == entry->entry.dir) break; if (p == entry->entry.dir) { free(path); free(name); free(to); path = NULL; continue; } } break; } if (!path) return; ret = rename(path, to); if (ret == -1) { if (errno == ENOSPC) full = 1; CHECK(errno == ENOSPC || errno == EBUSY); free(path); free(name); free(to); return; } free(path); free(to); if (rename_entry && rename_entry->type == entry->type && rename_entry->entry.target == entry->entry.target) { free(name); return; } add_dir_entry(parent, entry->type, name, entry->entry.target); if (rename_entry) remove_dir_entry(rename_entry); remove_dir_entry(entry); free(name); }
void list_mountable_devices(char *device, list_t *list) { int i,n = 0; iox_stat_t stat; char mc_path[6] = "mc0:"; char mass_device[8] = "mass0:"; add_reg_entry(list->entries,"..",n++); if (!strcmp(device,"mc")) { for (i = 0; i < 2; i++) { mc_path[2] = '0' + i; if(!fileXioGetStat(mc_path,&stat)) { add_dir_entry(list->entries,mc_path,n++); } } list->num = n; } if (!strcmp(device,"mass")) { for(i=0; i < 10; i++) { mass_device[4] = '0'+i; if(!(fileXioGetStat(mass_device, &stat) < 0)) { add_dir_entry(list->entries,mass_device,n++); } } // Older versions of the module only support "mass:" if (!n) { if (!(fileXioGetStat("mass:",&stat) < 0)) { add_dir_entry(list->entries,"mass:",n++); } } list->num = n; } if (!strcmp(device,"hdd")) { // Checking for "hdd0:" doesn't work, maybe since it's a block device //if (!(fileXioGetStat("hdd0:",&stat) < 0)) { list_partitions(list); } } if (!strcmp(device,"cdfs")) { //if(!(fileXioGetStat("cdfs:",&stat) < 0)) { add_dir_entry(list->entries,"cdfs:", n++); } CDVD_FlushCache(); refresh_cdfs(); list->num = n; } else { CDVD_Stop(); } }
static int create_always(struct filsys *fs, char *name, int mode, struct inode **retval) { struct inode *dir; struct inode *inode; struct inode *oldinode; ino_t oldino; int rc; int len = strlen(name); rc = diri(fs, &name, &len, &dir); if (rc < 0) return rc; rc = find_dir_entry(dir, name, len, &oldino); if (rc == 0) { rc = get_inode(fs, oldino, &oldinode); if (rc < 0) { release_inode(dir); return rc; } if (S_ISDIR(oldinode->desc->mode) && oldinode->desc->linkcount == 1) { release_inode(dir); return -EISDIR; } inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO)); if (!inode) { release_inode(dir); return -ENOSPC; } rc = modify_dir_entry(dir, name, len, inode->ino, NULL); if (rc < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return rc; } unlink_inode(oldinode); release_inode(oldinode); } else if (rc == -ENOENT) { inode = alloc_inode(dir, S_IFREG | (mode & S_IRWXUGO)); if (!inode) { release_inode(dir); return -ENOSPC; } rc = add_dir_entry(dir, name, len, inode->ino); if (rc < 0) { unlink_inode(inode); release_inode(inode); release_inode(dir); return rc; } } else { release_inode(dir); return rc; } release_inode(dir); *retval = inode; return 0; }
/* Implement the netfs_get_directs callback as described in <hurd/netfs.h>. */ error_t netfs_get_dirents (struct iouser *cred, struct node *dir, int first_entry, int num_entries, char **data, mach_msg_type_number_t *data_len, vm_size_t max_data_len, int *data_entries) { error_t err; int count; size_t size = 0; /* Total size of our return block. */ struct hostmux_name *first_name, *nm; /* Add the length of a directory entry for NAME to SIZE and return true, unless it would overflow MAX_DATA_LEN or NUM_ENTRIES, in which case return false. */ int bump_size (const char *name) { if (num_entries == -1 || count < num_entries) { size_t new_size = size + DIRENT_LEN (strlen (name)); if (max_data_len > 0 && new_size > max_data_len) return 0; size = new_size; count++; return 1; } else return 0; } if (dir->nn->name) return ENOTDIR; pthread_rwlock_rdlock (&dir->nn->mux->names_lock); /* Find the first entry. */ for (first_name = dir->nn->mux->names, count = 2; first_name && first_entry > count; first_name = first_name->next) if (first_name->node) count++; count = 0; /* Make space for the `.' and `..' entries. */ if (first_entry == 0) bump_size ("."); if (first_entry <= 1) bump_size (".."); /* See how much space we need for the result. */ for (nm = first_name; nm; nm = nm->next) if (nm->node && !bump_size (nm->name)) break; /* Allocate it. */ *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); err = ((void *) *data == (void *) -1) ? errno : 0; if (! err) /* Copy out the result. */ { char *p = *data; int add_dir_entry (const char *name, ino_t fileno, int type) { if (num_entries == -1 || count < num_entries) { struct dirent hdr; size_t name_len = strlen (name); size_t sz = DIRENT_LEN (name_len); if (sz > size) return 0; else size -= sz; hdr.d_fileno = fileno; hdr.d_reclen = sz; hdr.d_type = type; hdr.d_namlen = name_len; memcpy (p, &hdr, DIRENT_NAME_OFFS); strcpy (p + DIRENT_NAME_OFFS, name); p += sz; count++; return 1; } else return 0; } *data_len = size; *data_entries = count; count = 0; /* Add `.' and `..' entries. */ if (first_entry == 0) add_dir_entry (".", 2, DT_DIR); if (first_entry <= 1) add_dir_entry ("..", 2, DT_DIR); /* Fill in the real directory entries. */ for (nm = first_name; nm; nm = nm->next) if (nm->node && !add_dir_entry (nm->name, nm->fileno, strcmp (nm->canon, nm->name) == 0 ? DT_REG : DT_LNK)) break; }
int main(int argc, char **argv) { int dev, i; char *zeros; unsigned long size; superblock_t *sb, *sb_dup; inode_t *rootdir; openlog("GNORDOFS", LOG_PID, LOG_LOCAL0); // Size = 10Mib size = 1024*1024*10; dev = open("gnordofs.img", O_RDWR | O_CREAT, 0666); if (dev < 0) { perror(NULL); exit(1); } /* Inicializar superbloque y zona de inodos. */ sb = superblock_init(size); inode_list_init(dev, sb); //superblock_print_dump(sb); /* Poner cero toda la zona de bloques, por si acaso. */ if (lseek(dev, sb->block_zone_base, SEEK_SET) < 0) { printf("Dude, WTF???\n"); exit(1); } zeros = malloc(BLOCK_SIZE); memset(zeros, 0, BLOCK_SIZE); for (i=sb->block_zone_base; i < size - BLOCK_SIZE; i += BLOCK_SIZE) { write(dev, zeros, BLOCK_SIZE); } if (size > i) write(dev, zeros, size - i); /* Inicializar lista de bloques libres. */ free_block_list_init(dev, sb); /* ¡Que no se me olvide salvar el maldito superbloque! */ superblock_write(dev, sb); /* A partir de aquí se maneja casi como si estuviese inicializado. */ /* Reservar el primer inodo libre, marcarlo como directorio, añadir las entradas . y .., salvarlo en disco y hacer que first_directory del superbloque apunte a dicho inodo. */ rootdir = ialloc(dev, sb); // Modificar rootdir con entradas . y .. rootdir->type = I_DIR; rootdir->perms = S_IFDIR | 0755; add_dir_entry(dev, sb, rootdir, rootdir, "."); add_dir_entry(dev, sb, rootdir, rootdir, ".."); rootdir->atime = rootdir->ctime = rootdir->mtime = time(NULL); iput(dev, sb, rootdir); sb->first_inode = rootdir->n; superblock_write(dev, sb); printf("rootdir->type = %d\n", rootdir->type); printf("rootdir->size = %d\n", rootdir->size); printf("rootdir->link_counter = %d\n", rootdir->link_counter); printf("rootdir->owner = %d\n", rootdir->owner); printf("rootdir->group = %d\n", rootdir->group); printf("rootdir->perms = %o\n", rootdir->perms); printf("rootdir->n = %d\n", rootdir->n); printf("rootdir->offset_ptr = %d\n", rootdir->offset_ptr); /* Comprobar que se puede leer el superbloque. */ sb_dup = superblock_read(dev); if (!sb_dup || memcmp(sb, sb_dup, sizeof(struct persistent_superblock) != 0)) { printf("WTF?\n"); exit(1); } superblock_print_dump(sb_dup); print_free_block_list(dev, sb); free(sb); free(sb_dup); close(dev); return 0; }