static int ifs_chmod(struct device *dev, const char *path, mode_t newmode) { struct ifs_entry entry; if (ifs_get_directory(dev, 0, path) != -1) { ino_t ino = ifs_get_directory(dev, 0, path); device_read(dev, &entry, sizeof(struct ifs_entry), ifs_get_address(dev, ino)); entry.mode = newmode; device_write(dev, &entry, ifs_get_address(dev, ino), sizeof(struct ifs_entry)); return 0; } return ENOENT; }
static int ifs_readlink(struct device *dev, const char *path, char *buf, int len) { struct ifs_entry entry; if (ifs_get_directory(dev, 0, path) != -1) { ino_t ino = ifs_get_directory(dev, 0, path); device_read(dev, &entry, sizeof(struct ifs_entry), ifs_get_address(dev, ino)); if(entry.file_type == IFS_LINK) { device_read(dev, buf, len % 1024, ifs_get_address(dev, entry.data_index)); return 0; } } return ENOENT; }
static int ifs_rmdir(struct device *dev, const char *path) { struct ifs_entry entry; if (ifs_get_directory(dev, 0, path) != -1) { ino_t ino = ifs_get_directory(dev, 0, path); device_read(dev, &entry, sizeof(struct ifs_entry), ifs_get_address(dev, ino)); if(entry.file_type != IFS_DIRECTORY) return ENOTDIR; ifs_remove_entry(dev, path, &entry); ifs_free_blockgroup(dev, &entry); ifs_free_block(dev, ino); return 0; } return ENOENT; }
/* * Creates a new IFS Directory */ void make_dir(char* name) { if(name[0] == '/') // Ignore leading / name++; int parent = 1; // Root by default if(contains(name, '/')) // Parent directory? { char* tmp = (char*)malloc(strlen(name)); strcpy(tmp, name); *strrchr(tmp, '/') = 0; parent = ifs_get_directory(1, tmp); free(tmp); } int* directory = ifs_get_directory_table(parent); IFSFileEntry* ent = ifs_create_file_entry(); if(contains(name, '/')) strcpy(ent->file_name, strrchr(name, '/') + 1); else strcpy(ent->file_name, name); ent->file_type = DIRECTORY; int pos = 0; while(directory[pos] != -1) pos++; directory[pos] = ent->block_index; int ptr = ifs_block_alloc_i(1024, &ent->data_index)->data; memset(initrd + ptr, 0xFF, 1024); }
/* * Returns the index to a directory table */ static int ifs_get_directory(struct device *dev, int parent, char *dir) { if(dir[0] == 0 && parent == 0) return 0; bool has_sep = contains(dir, '/'); int32_t directory[256]; struct ifs_entry dentry; device_read(dev, &dentry, sizeof(struct ifs_entry), ifs_get_address(dev, parent)); int dtable = dentry.data_index; device_read(dev, directory, 1024, ifs_get_address(dev, dtable)); for (int i = 0; i < 256 && directory[i] != -1; i++) { int e = directory[i]; struct ifs_entry entry; device_read(dev, &entry, sizeof(struct ifs_entry), ifs_get_address(dev, e)); if (has_sep && strncmp(dir, entry.file_name, strindx(dir, '/')) == 0) { return ifs_get_directory(dev, e, strrchr(dir, '/') + 1); } else if (!has_sep) { if (strncmp(entry.file_name, dir, strlen(entry.file_name)) == 0) { return e; } } } return -1; }
static int ifs_read_ino(struct device *dev, struct inode *inos, const char *path) { struct ifs_entry entry; if (ifs_get_directory(dev, 0, path) != -1) { ino_t ino = ifs_get_directory(dev, 0, path); device_read(dev, &entry, sizeof(struct ifs_entry), ifs_get_address(dev, ino)); inos->i_ino = ino; inos->i_size = entry.file_size; inos->i_dev = dev->dev_id; inos->i_mode = entry.mode; inos->i_uid = entry.uid; inos->i_gid = entry.gid; inos->i_islnk = entry.file_type == IFS_LINK; inos->i_isfifo = entry.file_type == IFS_PIPE; return 0; } else { return -1; } }
static inline int ifs_get_parent(struct device *dev, const char *path) { int parent = 0; if (contains(path, '/')) { char tmp[256]; strcpy(tmp, path); *strlchr(tmp, '/') = 0; parent = ifs_get_directory(dev, 0, tmp); } return parent; }
/* * Creates a new IFS file */ void add_file(char* name, char* contents, int len) { if(name[0] == '/') // Ignore leading / name++; int parent = 1; // Root by default if(contains(name, '/')) // Parent directory? { char* tmp = (char*)malloc(strlen(name)); strcpy(tmp, name); *strrchr(tmp, '/') = 0; parent = ifs_get_directory(1, tmp); free(tmp); } int* directory = ifs_get_directory_table(parent); IFSFileEntry* ent = ifs_create_file_entry(); if(contains(name, '/')) strcpy(ent->file_name, strrchr(name, '/') + 1); else strcpy(ent->file_name, name); ent->file_type = REG_FILE; int pos = 0; while(directory[pos] != -1) pos++; directory[pos] = ent->block_index; ent->file_size = len; int prevI = 0; for(int i = 0; i < len; i += vol_header->file_block_size) { int index = 0; void* ptr = (void*)(initrd + ifs_block_alloc_i(vol_header->file_block_size, &index)->data); if(i == 0) ent->data_index = (uint)index; else block_pool[prevI].next = index; memcpy(ptr, contents + i, (int)(len - i > vol_header->file_block_size ? vol_header->file_block_size : len - i)); prevI = index; } }
/* * Returns the index to a directory table */ static int ifs_get_directory(int parent, char* dir) { bool has_sep = contains(dir, '/'); int32_t* directory = (int32_t*)(initrd + ifs_get_address(parent)); for(int i = 0; i < 256 && directory[i] != -1; i++) { int e = directory[i]; IFSFileEntry* entry = (IFSFileEntry*)(initrd + ifs_get_address(e)); if(has_sep && strncmp(dir, entry->file_name, strindx(dir, '/')) == 0) { return ifs_get_directory(entry->data_index, strrchr(dir, '/') + 1); } else if (!has_sep) { if(strncmp(entry->file_name, dir, strlen(entry->file_name)) == 0) { return e; } } } return -1; }