int rd_creat(char* pathname){ char *dir_path; char *filename; split_dir_file(pathname, &dir_path, &filename); int dir_inode_num = get_dir_inode(dir_path, 1); //check if dir_path exists if(dir_inode_num == -1){ return -1; } int tmp = get_dir_entry(dir_inode_num, filename, 1); if(tmp != -1){ //directory already exists printf("error: dir already exists\n"); return -1; } //get ready to allocate inode int index = get_free_inode(); if(index == -1){ printf("no free inodes\n"); return -1; } s_block->free_inodes = s_block->free_inodes - 1; init_inode(index, 2); //type = 2, regular file inode_array[dir_inode_num].size = inode_array[dir_inode_num].size + sizeof(dir_entry); dir_entry* new_dir = get_free_dir_entry(dir_inode_num); new_dir->inode_number = index; strcpy(new_dir->filename, filename); printf("rd_creat created a file\n"); return 1; }
/*===========================================================================* * go_down * *===========================================================================*/ static int go_down( char path[PATH_MAX], /* path to add the name to */ struct inode *parent, /* inode of the current directory */ char *name, /* name of the directory entry */ struct inode **res_ino, /* place to store resulting inode */ struct sffs_attr *attr /* place to store inode attributes */ ) { /* Given a directory inode and a name, progress into a directory entry. */ struct inode *ino; int r, stale = 0; if ((r = push_path(path, name)) != OK) return r; dprintf(("%s: go_down: name '%s', path now '%s'\n", sffs_name, name, path)); ino = lookup_dentry(parent, name); dprintf(("%s: lookup_dentry('%s') returned %p\n", sffs_name, name, ino)); if (ino != NULL) r = verify_path(path, ino, attr, &stale); else r = sffs_table->t_getattr(path, attr); dprintf(("%s: path query returned %d\n", sffs_name, r)); if (r != OK) { if (ino != NULL) { put_inode(ino); ino = NULL; } if (!stale) return r; } dprintf(("%s: name '%s'\n", sffs_name, name)); if (ino == NULL) { if ((ino = get_free_inode()) == NULL) return ENFILE; dprintf(("%s: inode %p ref %d\n", sffs_name, ino, ino->i_ref)); ino->i_flags = MODE_TO_DIRFLAG(attr->a_mode); add_dentry(parent, name, ino); } *res_ino = ino; return OK; }
/** Create a directory */ int nphfuse_mkdir(const char *path, mode_t mode){ // char *filename, *dir; // extract_directory_file(&dir,&filename,path); struct timeval currTime; npheap_store *inode = NULL; char dir[236]; char filename[128]; uint64_t findex = -1; log_msg("Into mkdir functionality.\n"); inode = get_free_inode(&findex); //If empty directory not found if(inode == NULL){ log_msg("Empty Directory not found. \n"); return -ENOENT; } //Get directory and filename int extract = extract_directory_file(dir, filename, path); if(extract == 1){ log_msg("Extraction failed. \n"); return -EINVAL; } log_msg("Directory %s and Filename is %s \n", dir, filename); memset(inode, 0, sizeof(npheap_store)); strcpy(inode->dirname, dir); strcpy(inode->filename, filename); inode->mystat.st_ino = inode_off; inode_off++; inode->mystat.st_mode = S_IFDIR | mode; inode->mystat.st_gid = getgid(); inode->mystat.st_uid = getuid(); inode->mystat.st_size = BLOCK_SIZE/2; inode->mystat.st_nlink = 2; gettimeofday(&currTime, NULL); inode->mystat.st_atime = currTime.tv_sec; inode->mystat.st_mtime = currTime.tv_sec; inode->mystat.st_ctime = currTime.tv_sec; log_msg("mkdir executed successfully.! %d st_ino\n", inode->mystat.st_ino); return 0; }
int main(int argc, char const *argv[]){ if(argc != 4) { fprintf(stderr, "Usage: ext2_cp <formatted virtual disk> <local path> <absolute disk path>\n"); exit(1); } int fd = open(argv[1], O_RDWR); disk = mmap(NULL, 128 * EXT2_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(disk == MAP_FAILED) { perror("mmap"); exit(1); } FILE * fp; fp = fopen(argv[2], "r"); if (fp == NULL) { printf("File not found\n"); exit(ENOENT); } //get file size fseek(fp, 0L, SEEK_END); int file_sz = ftell(fp); fseek(fp, 0L, SEEK_SET); //number of blocks needed to copy file int num_blocks_needed = (int) (file_sz / EXT2_BLOCK_SIZE) + 1; //get the superblock struct ext2_super_block *superblock = (struct ext2_super_block *) (disk + EXT2_BLOCK_SIZE); int first_data_block = superblock->s_first_data_block; if (num_blocks_needed > superblock->s_free_blocks_count){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } // get the group descriptor table // we know that this table always start at third datablock (index 2) struct ext2_group_desc *group_des_table = (struct ext2_group_desc*) (disk + EXT2_BLOCK_SIZE * 2); int inode_bitmap = group_des_table->bg_inode_bitmap; int block_bitmap = group_des_table->bg_block_bitmap; int inode_table = group_des_table->bg_inode_table; void *tablestart = disk + EXT2_BLOCK_SIZE * inode_table; //check that the path does not already exist int found_inode; found_inode = search_inode(argv[3]); if (found_inode != -1){ // has to be not found fprintf(stderr, "File exists\n"); exit(EEXIST); } //get the parent directory into which to copy the file int parent_inode_num = parent_conversion(argv[3]); if (parent_inode_num == -1){ fprintf(stderr, "No such file or directory\n"); exit(ENOENT); } //get the inode of that parent directory struct ext2_inode *parent_inode = (struct ext2_inode*) (tablestart) + (parent_inode_num - 1); if (parent_inode->i_mode & EXT2_S_IFREG){ fprintf(stderr, "No such file or directory\n"); exit(ENOENT); } //get block bitmap int block_bitmap_block = block_bitmap * EXT2_BLOCK_SIZE; void * block_bits = (void *)(disk + block_bitmap_block); //get inode bitmap unsigned long inode_bitmap_block = inode_bitmap * EXT2_BLOCK_SIZE; void * inode_bits = (void *)(disk + inode_bitmap_block); //find free inode int inode_indx = get_free_inode(inode_bits); if (inode_indx == -1){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } //update superblock superblock->s_free_inodes_count = superblock->s_free_inodes_count - 1; //init new inode struct ext2_inode *new_inode = (struct ext2_inode*)(tablestart) + (inode_indx); new_inode->i_mode = 32768; //is file new_inode->i_size = file_sz; new_inode->i_blocks = 1; new_inode->i_links_count = 1; //global variables for indirect block if necessary void *indirect_block; unsigned int indr_block[15]; void *data_block; int i; for (i = 0; i < num_blocks_needed; i++){ if (i < 12){ int free_block_num = get_free_block(block_bits); if (free_block_num == -1){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1; new_inode->i_blocks += 1; new_inode->i_block[i] = first_data_block + free_block_num -1; data_block = (void *)(disk + (EXT2_BLOCK_SIZE * new_inode->i_block[i])); } else if (i == 12){ //i_blocks[12] entry is the 13th entry in the array //It holds the block number of the indirect block //- this block contains an array of block numbers //for the next data blocks of the file. //get free block for indirect block int indirect_block_num = get_free_block(block_bits); if (indirect_block_num == -1){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } new_inode->i_block[i] = first_data_block + indirect_block_num; //initialize indirect block indirect_block = (void *)(disk + (EXT2_BLOCK_SIZE * new_inode->i_block[i])); //get data block int free_block_num = get_free_block(block_bits); if (free_block_num == -1){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1; new_inode->i_blocks += 1; indr_block[i - 12] = first_data_block + free_block_num -1; memcpy(indirect_block, (void *) indr_block, 16); data_block = (void *)(disk + (EXT2_BLOCK_SIZE * indr_block[i - 12])); } else if (i > 12){ int free_block_num = get_free_block(block_bits); if (free_block_num == -1){ fprintf(stderr, "No space left on device\n"); exit(ENOSPC); } superblock->s_free_blocks_count = superblock->s_free_blocks_count - 1; new_inode->i_blocks += 1; indr_block[i - 12] = first_data_block + free_block_num -1; memcpy(indirect_block, (void *) indr_block, 16); data_block = (void *)(disk + (EXT2_BLOCK_SIZE * indr_block[i - 12])); } //read data from file to data block int num_read = fread(data_block, 1, EXT2_BLOCK_SIZE, fp); if (num_read == 0){ perror("Error reading file"); } } fclose(fp); //add this new file's directory entry to the parent directory int c; //loop through directory entries to get to the last entry for (c = 0; c < EXT2_BLOCK_SIZE;){ struct ext2_dir_entry_2 *node_dir = (struct ext2_dir_entry_2 *) (disk + (EXT2_BLOCK_SIZE * parent_inode->i_block[0]) + c); if (c + node_dir->rec_len == EXT2_BLOCK_SIZE){ //this is the last block in the directory int new_rec_len = node_dir->rec_len - node_dir->name_len - 8; node_dir->rec_len = node_dir->name_len + 8; //create directory entry struct ext2_dir_entry_2 *par_dir = (struct ext2_dir_entry_2 *) (disk + (EXT2_BLOCK_SIZE * parent_inode->i_block[0] + c + node_dir->rec_len)); par_dir->inode = inode_indx + 1; par_dir->file_type = 1; //get name of new file char dup_path[strlen(argv[3])]; strcpy(dup_path, argv[3]); char *ret; ret = strrchr(dup_path, '/'); if (ret[0] == '/'){ ret++; } par_dir->rec_len = new_rec_len; par_dir->name_len = strlen(ret); strcpy(par_dir->name, ret); break; } c += node_dir->rec_len; } return 0; }
/** Create a file node * * There is no create() operation, mknod() will be called for * creation of all non-directory, non-symlink nodes. */ int nphfuse_mknod(const char *path, mode_t mode, dev_t dev){ struct timeval currTime; npheap_store *inode = NULL; char dir[236]; char filename[128]; char *blk_data = NULL; uint64_t findex = -1; log_msg("Into mkdir functionality.\n"); inode = get_free_inode(&findex); //If empty directory not found if(inode == NULL){ log_msg("Empty Directory not found. \n"); return -ENOENT; } //Get directory and filename int extract = extract_directory_file(dir, filename, path); if(extract == 1){ log_msg("Extraction failed. \n"); return -EINVAL; } log_msg("Directory %s and Filename is %s \n", dir, filename); memset(inode, 0, sizeof(npheap_store)); strcpy(inode->dirname, dir); strcpy(inode->filename, filename); // Set mystat inode->mystat.st_ino = inode_off; inode_off++; inode->mystat.st_mode = mode; inode->mystat.st_gid = getgid(); inode->mystat.st_uid = getuid(); inode->mystat.st_dev = dev; inode->mystat.st_nlink = 1; gettimeofday(&currTime, NULL); inode->mystat.st_atime = currTime.tv_sec; inode->mystat.st_mtime = currTime.tv_sec; inode->mystat.st_ctime = currTime.tv_sec; //Set the offset for data object while(npheap_getsize(npheap_fd, data_off) != 0 && data_off < 10000){ log_msg("Offset already in use - %d\n", data_off); data_off++; } blk_data = (char *)npheap_alloc(npheap_fd, data_off, BLOCK_SIZE); //Check if allocated if(blk_data == NULL){ log_msg("Data block, couldn't be allocated\n"); memset(inode, 0, sizeof(npheap_store)); inode_off--; return -ENOMEM; } //Everything worked fine memset(blk_data, 0, BLOCK_SIZE); blk_array[data_off] = blk_data; inode->offset = data_off; log_msg("mknod ran successfully in NPHeap for %d data offset\n", data_off); data_off++; return 0; }
int mk_new_directory(jfs_t *jfs, char *pathname, int parent_inodenum, int grandparent_inodenum) { /* we need to create this directory */ /* round size up to nearest 4 byte boundary */ int size, prev_size, bytes_done=0; int new_inodenum, new_blocknum; char block[BLOCKSIZE]; struct inode* new_inode, *parent_inode; /* calculate the size of the new parent dirent */ size = (((strlen(pathname)/4) + 1) * 4) + 16; /* does it fit?*/ if (bytes_done + size > BLOCKSIZE) { fprintf(stderr, "No more space in the directory to add another entry\n"); exit(1); } /* allocate an inode for this directory */ if (strcmp(pathname, ".")==0) { new_inodenum = parent_inodenum; } else if (strcmp(pathname, "..")==0) { new_inodenum = grandparent_inodenum; } else { new_inodenum = get_free_inode(jfs); } /* update the parent directories inode size field */ jfs_read_block(jfs, block, inode_to_block(parent_inodenum)); parent_inode = (struct inode*)(block + (parent_inodenum % INODES_PER_BLOCK) * INODE_SIZE); prev_size = parent_inode->size; parent_inode->size += size; jfs_write_block(jfs, block, inode_to_block(parent_inodenum)); /* create an entry in the parent directory */ create_dirent(jfs, pathname, DT_DIRECTORY, parent_inode->blockptrs[0], prev_size, size, new_inodenum); if (strcmp(pathname, ".")!=0 && strcmp(pathname, "..")!=0) { /* it's a real directory */ /* get a block to hold the directory */ new_blocknum = get_free_block(jfs); /* read in the block that contains our new inode */ jfs_read_block(jfs, block, inode_to_block(new_inodenum)); new_inode = (struct inode*)(block + (new_inodenum % INODES_PER_BLOCK) * INODE_SIZE); new_inode->flags = FLAG_DIR; new_inode->blockptrs[0] = new_blocknum; new_inode->size = 0; /* write back the inode block */ jfs_write_block(jfs, block, inode_to_block(new_inodenum)); return new_inodenum; } return parent_inodenum; }
/*===========================================================================* * do_create * *===========================================================================*/ PUBLIC int do_create() { /* Create a new file. */ char path[PATH_MAX], name[NAME_MAX+1]; struct inode *parent, *ino; struct hgfs_attr attr; hgfs_file_t handle; int r; /* We cannot create files on a read-only file system. */ if (state.read_only) return EROFS; /* Get path, name, parent inode and possibly inode for the given path. */ if ((r = get_name(m_in.REQ_GRANT, m_in.REQ_PATH_LEN, name)) != OK) return r; if (!strcmp(name, ".") || !strcmp(name, "..")) return EEXIST; if ((parent = find_inode(m_in.REQ_INODE_NR)) == NULL) return EINVAL; if ((r = verify_dentry(parent, name, path, &ino)) != OK) return r; /* Are we going to need a new inode upon success? * Then make sure there is one available before trying anything. */ if (ino == NULL || ino->i_ref > 1 || HAS_CHILDREN(ino)) { if (!have_free_inode()) { if (ino != NULL) put_inode(ino); return ENFILE; } } /* Perform the actual create call. */ r = hgfs_open(path, O_CREAT | O_EXCL | O_RDWR, m_in.REQ_MODE, &handle); if (r != OK) { /* Let's not try to be too clever with error codes here. If something * is wrong with the directory, we'll find out later anyway. */ if (ino != NULL) put_inode(ino); return r; } /* Get the created file's attributes. */ attr.a_mask = HGFS_ATTR_MODE | HGFS_ATTR_SIZE; r = hgfs_getattr(path, &attr); /* If this fails, or returns a directory, we have a problem. This * scenario is in fact possible with race conditions. * Simulate a close and return a somewhat appropriate error. */ if (r != OK || S_ISDIR(attr.a_mode)) { printf("HGFS: lost file after creation!\n"); hgfs_close(handle); if (ino != NULL) { del_dentry(ino); put_inode(ino); } return (r == OK) ? EEXIST : r; } /* We do assume that the HGFS open(O_CREAT|O_EXCL) did its job. * If we previousy found an inode, get rid of it now. It's old. */ if (ino != NULL) { del_dentry(ino); put_inode(ino); } /* Associate the open file handle with an inode, and reply with its details. */ ino = get_free_inode(); assert(ino != NULL); /* we checked before whether we had a free one */ ino->i_file = handle; ino->i_flags = I_HANDLE; add_dentry(parent, name, ino); m_out.RES_INODE_NR = INODE_NR(ino); m_out.RES_MODE = get_mode(ino, attr.a_mode); m_out.RES_FILE_SIZE_HI = ex64hi(attr.a_size); m_out.RES_FILE_SIZE_LO = ex64lo(attr.a_size); m_out.RES_UID = opt.uid; m_out.RES_GID = opt.gid; m_out.RES_DEV = NO_DEV; return OK; }
/*===========================================================================* * do_getdents * *===========================================================================*/ int do_getdents() { /* Retrieve directory entries. */ char name[NAME_MAX+1]; struct inode *ino, *child; struct dirent *dent; struct sffs_attr attr; size_t len, off, user_off, user_left; off_t pos; int r; /* must be at least sizeof(struct dirent) + NAME_MAX */ static char buf[BLOCK_SIZE]; attr.a_mask = SFFS_ATTR_MODE; if ((ino = find_inode(m_in.REQ_INODE_NR)) == NULL) return EINVAL; if (m_in.REQ_SEEK_POS_HI != 0) return EINVAL; if (!IS_DIR(ino)) return ENOTDIR; /* We are going to need at least one free inode to store children in. */ if (!have_free_inode()) return ENFILE; /* If we don't have a directory handle yet, get one now. */ if ((r = get_handle(ino)) != OK) return r; off = 0; user_off = 0; user_left = m_in.REQ_MEM_SIZE; /* We use the seek position as file index number. The first position is for * the "." entry, the second position is for the ".." entry, and the next * position numbers each represent a file in the directory. */ for (pos = m_in.REQ_SEEK_POS_LO; ; pos++) { /* Determine which inode and name to use for this entry. * We have no idea whether the host will give us "." and/or "..", * so generate our own and skip those from the host. */ if (pos == 0) { /* Entry for ".". */ child = ino; strcpy(name, "."); get_inode(child); } else if (pos == 1) { /* Entry for "..", but only when there is a parent. */ if (ino->i_parent == NULL) continue; child = ino->i_parent; strcpy(name, ".."); get_inode(child); } else { /* Any other entry, not being "." or "..". */ r = sffs_table->t_readdir(ino->i_dir, pos - 2, name, sizeof(name), &attr); if (r != OK) { /* No more entries? Then close the handle and stop. */ if (r == ENOENT) { put_handle(ino); break; } /* FIXME: what if the error is ENAMETOOLONG? */ return r; } if (!strcmp(name, ".") || !strcmp(name, "..")) continue; if ((child = lookup_dentry(ino, name)) == NULL) { child = get_free_inode(); /* We were promised a free inode! */ assert(child != NULL); child->i_flags = MODE_TO_DIRFLAG(attr.a_mode); add_dentry(ino, name, child); } } len = DWORD_ALIGN(sizeof(struct dirent) + strlen(name)); /* Is the user buffer too small to store another record? * Note that we will be rerequesting the same dentry upon a subsequent * getdents call this way, but we really need the name length for this. */ if (user_off + off + len > user_left) { put_inode(child); /* Is the user buffer too small for even a single record? */ if (user_off == 0 && off == 0) return EINVAL; break; } /* If our own buffer cannot contain the new record, copy out first. */ if (off + len > sizeof(buf)) { r = sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, user_off, (vir_bytes) buf, off, D); if (r != OK) { put_inode(child); return r; } user_off += off; user_left -= off; off = 0; } /* Fill in the actual directory entry. */ dent = (struct dirent *) &buf[off]; dent->d_ino = INODE_NR(child); dent->d_off = pos; dent->d_reclen = len; strcpy(dent->d_name, name); off += len; put_inode(child); } /* If there is anything left in our own buffer, copy that out now. */ if (off > 0) { r = sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, user_off, (vir_bytes) buf, off, D); if (r != OK) return r; user_off += off; } m_out.RES_SEEK_POS_HI = 0; m_out.RES_SEEK_POS_LO = pos; m_out.RES_NBYTES = user_off; return OK; }
int create_file(char *path, int is_dir) { char *lpath = malloc(sizeof(char)*strlen(path)+1); char *last; char *ptr; int wd, free_inode_num, found, s; struct inode_block *cur_inode_block = NULL; struct inode *cur_inode = NULL; strcpy(lpath, path); if(strlen(lpath) == 1) { if(lpath[0] == '/') { return ERR_FILE_EXISTS; } else { return ERR_INVALID_PATH; } } ptr = strrchr(lpath, '/'); if(ptr == lpath+strlen(lpath)-1) { *ptr = '\0'; ptr = strrchr(lpath, '/'); } *ptr = '\0'; ptr++; last = malloc(sizeof(char)*strlen(ptr)+1); strcpy(last, ptr); wd = path_to_inode(lpath); DEBUG1 && printf("wd = %d \n", wd); if(wd < 0) { return ERR_INVALID_PATH; } //printf("wd inode = %d \n", wd); get_inode(&cur_inode_block, &cur_inode, wd); if(cur_inode_block == NULL || cur_inode == NULL) { DEBUG2 && printf("get inode failed\n"); return ERR_INTERNAL; } found = has_file(cur_inode, last); //printf("found = %d \n", found); DEBUG1 && printf("found = %d \n", found); if(found != -1) { //printf("file or dir already exists!\n"); //printf("wd = %d, last = %s \n ", wd, last); return ERR_FILE_EXISTS; } free_inode_num = get_free_inode(); //printf("free inode num = %d\n", free_inode_num); if(free_inode_num < 0) { return ERR_MAX_FILES; } get_inode( &cur_inode_block, &cur_inode , free_inode_num); if(cur_inode_block == NULL || cur_inode == NULL) { return ERR_INTERNAL; } cur_inode->is_dir = is_dir; put_inode_block(cur_inode_block, free_inode_num); //free_data_block_num = get_free_datablock(); //printf("free_data_block_num = %d\n", free_data_block_num); s = add_dir_to_inode(wd, last, free_inode_num); return s; }
/*===========================================================================* * do_getdents * *===========================================================================*/ ssize_t do_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, off_t *posp) { /* Retrieve directory entries. */ struct fsdriver_dentry fsdentry; char name[NAME_MAX+1]; struct inode *ino, *child; struct sffs_attr attr; off_t pos; int r; /* must be at least sizeof(struct dirent) + NAME_MAX */ static char buf[BLOCK_SIZE]; if ((ino = find_inode(ino_nr)) == NULL) return EINVAL; if (!IS_DIR(ino)) return ENOTDIR; if (*posp < 0 || *posp >= ULONG_MAX) return EINVAL; /* We are going to need at least one free inode to store children in. */ if (!have_free_inode()) return ENFILE; /* If we don't have a directory handle yet, get one now. */ if ((r = get_handle(ino)) != OK) return r; fsdriver_dentry_init(&fsdentry, data, bytes, buf, sizeof(buf)); /* We use the seek position as file index number. The first position is for * the "." entry, the second position is for the ".." entry, and the next * position numbers each represent a file in the directory. */ do { /* Determine which inode and name to use for this entry. * We have no idea whether the host will give us "." and/or "..", * so generate our own and skip those from the host. */ pos = (*posp)++; if (pos == 0) { /* Entry for ".". */ child = ino; strcpy(name, "."); get_inode(child); } else if (pos == 1) { /* Entry for "..", but only when there is a parent. */ if (ino->i_parent == NULL) continue; child = ino->i_parent; strcpy(name, ".."); get_inode(child); } else { /* Any other entry, not being "." or "..". */ attr.a_mask = SFFS_ATTR_MODE; r = sffs_table->t_readdir(ino->i_dir, pos - 2, name, sizeof(name), &attr); if (r != OK) { /* No more entries? Then close the handle and stop. */ if (r == ENOENT) { put_handle(ino); break; } /* FIXME: what if the error is ENAMETOOLONG? */ return r; } if (!strcmp(name, ".") || !strcmp(name, "..")) continue; if ((child = lookup_dentry(ino, name)) == NULL) { child = get_free_inode(); /* We were promised a free inode! */ assert(child != NULL); child->i_flags = MODE_TO_DIRFLAG(attr.a_mode); add_dentry(ino, name, child); } } r = fsdriver_dentry_add(&fsdentry, INODE_NR(child), name, strlen(name), IS_DIR(child) ? DT_DIR : DT_REG); put_inode(child); if (r < 0) return r; } while (r > 0); return fsdriver_dentry_finish(&fsdentry); }
/** Creates and fills in a gd_fs_entry_t from an <entry>...</entry> in xml. * * @xml the xml containing the entry * @node the node representing this <entry>...</entry> block * * @returns pointer to gd_fs_entry_t with fields filled in as needed */ struct gd_fs_entry_t* gd_fs_entry_from_xml(xmlDocPtr xml, xmlNodePtr node) { struct gd_fs_entry_t* entry; unsigned long inode = 0; entry = (struct gd_fs_entry_t*) malloc(sizeof(struct gd_fs_entry_t)); if(entry == NULL) {} // TODO: ERROR memset(entry, 0, sizeof(struct gd_fs_entry_t)); size_t length; xmlNodePtr c1, c2; xmlChar *value = NULL; inode = get_free_inode(); for(c1 = node->children; c1 != NULL; c1 = c1->next) { char const *name = c1->name; switch(*name) { case 'a': // 'author' for(c2 = c1->children; c2 != NULL; c2 = c2->next) { name = c2->name; value = xmlNodeListGetString(xml, c2->children, 1); switch(*name) { case 'n': str_init_create(&entry->author, value, 0); break; case 'e': str_init_create(&entry->author_email, value, 0); break; default: break; } xmlFree(value); } break; case 'c': if(strcmp(name, "content") == 0) { value = xmlGetProp(c1, "src"); str_init_create(&entry->src, value, 0); xmlFree(value); } // file's type else if (strcmp(name, "category") == 0) { value = xmlGetProp(c1, "label"); if (strcmp(value, "folder")==0) { inodetable[inode].inode->mode = S_IFDIR | 0700; entry->mode = S_IFDIR | 0700; entry->shared = 0; } else if (strcmp(value, "shared")==0) { inodetable[inode].inode->mode = S_IFREG | 0600; entry->mode = S_IFREG | 0600; entry->shared = 1; } else { inodetable[inode].inode->mode = S_IFREG | 0600; entry->mode = S_IFREG | 0600; entry->shared = 0; } } break; case 'f': if(strcmp(name, "feedlink") == 0) { value = xmlGetProp(c1, "rel"); if(strcmp(value, "http://schemas.google.com/acl/2007#accessControlList") == 0) { // Link for r/w access to ACLS for this entry // Do we care? // Can we expose this? } else if(strcmp(value, "http://schemas.google.com/docs/2007/revisions") == 0) { // Link for r/w access to revisions // It would be cool if we can expose these somehow } } break; case 'l': if(strcmp(name, "lastModifiedBy") == 0) { for(c2 = c1->children; c2 != NULL; c2 = c2->next) { name = c2->name; value = xmlNodeListGetString(xml, c2->children, 1); switch(*name) { case 'n': str_init_create(&entry->lastModifiedBy, value, 0); break; case 'e': str_init_create(&entry->lastModifiedBy_email, value, 0); break; default: break; } xmlFree(value); } } else if(strcmp(name, "link") == 0) { value = xmlGetProp(c1, "rel"); if(strcmp(value, "http://schemas.google.com/docs/2007#parent") == 0) { xmlChar *value; value = xmlGetProp(c1, "title"); str_init_create(&entry->parent, value, 0); xmlFree(value); value = xmlGetProp(c1, "href"); str_init_create(&entry->parent_href, value, 0); xmlFree(value); // This entry is inside one (or more?) collections // These entries are the folders for this entry } else if(strcmp(value, "alternate") == 0) { // Link you can open this document in a web browser with // Do we care? } else if(strcmp(value, "self") == 0) { // Link to XML feed for just this entry // Might be useful for checking for updates instead of changesets xmlChar *href = xmlGetProp(c1, "href"); str_init_create(&entry->feed, href, 0); xmlFree(href); } else if(strcmp(value, "edit") == 0) { // For writes? } /* else if(strcmp(value, "edit-media") == 0) { // deprecated, use 'resumeable-edit-media' } */ else if(strcmp(value, "http://schemas.google.com/g/2005#resumable-edit-media") == 0) { // For resumeable writes? // This may be the one we *really* want to use, rather than 'edit' } else if(strcmp(value, "http://schemas.google.com/docs/2007/thumbnail") == 0) { // Might be a useful way to expose this for GUI file managers? } xmlFree(value); } break; case 'm': if(strcmp(name, "md5Checksum") == 0) { value = xmlNodeListGetString(xml, c1->children, 1); entry->md5set = 1; str_init_create(&entry->md5, value, 0); xmlFree(value); } break; case 't': // 'title' if(strcmp(name, "title") == 0) { value = xmlNodeListGetString(xml, c1->children, 1); str_init_create(&entry->filename, value, 0); entry->filename.str = filenameencode(value, &entry->filename.len); entry->filename.reserved = entry->filename.len; xmlFree(value); } break; case 's': if(strcmp(name, "size") == 0) { value = xmlNodeListGetString(xml, c1->children, 1); length = xmlStrlen(value); // TODO: errors? entry->size = strtol((char*)value, NULL, 10); xmlFree(value); } break; default: break; } } entry->inode = inode; inodetable[inode].num = inode; inodetable[inode].inode->node = entry; return entry; }
int main(int argc, char **argv) { if (argc != 4) { fprintf(stderr, "Usage: readimg <image file name> filepath \n"); exit(1); } // open source file int fd_src = open(argv[2], O_RDONLY); if (fd_src < 0){ fprintf(stderr, "No such file exists in the native file system \n"); exit(ENOENT); } int filesize_src = lseek(fd_src, 0, SEEK_END); // mmap cannot map size 0 file. if (filesize_src <= 0){ fprintf(stderr, "The source file is empty \n"); exit(ENOENT); } int req_block_num = (filesize_src - 1) / EXT2_BLOCK_SIZE + 1; // open the image int fd = open(argv[1], O_RDWR); if (fd < 0){ fprintf(stderr, "No such virtual disk exists \n"); exit(ENOENT); } // map the virtual disk and source file on memory ptr_disk = mmap(NULL, BLOCK_NUM * BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); unsigned char* ptr_disk_src = mmap(NULL, filesize_src, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd_src, 0); if (ptr_disk == MAP_FAILED || ptr_disk_src == MAP_FAILED) { perror("mmap"); exit(1); } struct ext2_group_desc *ptr_group_desc = (struct ext2_group_desc *)(ptr_disk + EXT2_SB_OFFSET + EXT2_BLOCK_SIZE); // get the inode table struct ext2_inode *ptr_inode = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table); unsigned char *bm_inode = (ptr_disk + (ptr_group_desc -> bg_inode_bitmap) * BLOCK_SIZE); unsigned char *bm_block = (ptr_disk + (ptr_group_desc -> bg_block_bitmap) * BLOCK_SIZE); struct ext2_super_block *ptr_super_block = (struct ext2_super_block *)(ptr_disk + EXT2_SB_OFFSET); char *ptr_path_src = strdup(argv[2]); char *ptr_path_dest = strdup(argv[3]); char *table_path_src[10]; char *table_path_dest[10]; int count_path_src = get_path_table(table_path_src, ptr_path_src); int count_path_dest = get_path_table(table_path_dest, ptr_path_dest); // Find the destination directory in the virtual disk struct ext2_dir_entry_2 *ptr_dir_dest = recurse_inode(ptr_inode + 1, table_path_dest, count_path_dest, 0, ptr_group_desc->bg_inode_table); if(ptr_dir_dest == 0) { printf("No such directory exists on virtual disk\n"); return -1; } int table_new_block[req_block_num]; int copy_flag = 0; int i = 0; while(i < req_block_num) { int free_block = get_free_block(bm_block, ptr_super_block); SETBIT(bm_block, free_block); table_new_block[i] = free_block; if(filesize_src - copy_flag <= BLOCK_SIZE) { memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, filesize_src - copy_flag - 1); } else { memcpy(ptr_disk + EXT2_BLOCK_SIZE * (free_block + 1), ptr_disk_src + BLOCK_SIZE * i, EXT2_BLOCK_SIZE); copy_flag += BLOCK_SIZE; } i++; } int block_id_inderect; if(req_block_num > 11) { block_id_inderect = get_free_block(bm_block, ptr_super_block); int *indirect_block = (int *)(ptr_disk + EXT2_BLOCK_SIZE * (block_id_inderect + 1)); SETBIT(bm_block, block_id_inderect); for(i = 12; i < req_block_num; i++) { *indirect_block = table_new_block[i]; indirect_block++; } } int fr_inode = get_free_inode(bm_inode, ptr_super_block); struct ext2_inode *node_new = ptr_inode + (fr_inode); SETBIT(bm_inode, fr_inode); node_new->i_links_count = 1; node_new->i_mode = EXT2_S_IFREG; node_new->i_size = filesize_src; node_new->i_blocks = req_block_num * 2; i = 0; while (i < 11 && req_block_num != i) { node_new->i_block[i] = table_new_block[i]; i++; } if(req_block_num > 11) { node_new -> i_block[12] = block_id_inderect; } struct ext2_inode *in_src = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table); struct ext2_inode *in_cur = (struct ext2_inode *)(ptr_disk + EXT2_BLOCK_SIZE * ptr_group_desc->bg_inode_table); in_src = in_src + ptr_dir_dest -> inode - 1; in_cur = in_cur + ptr_dir_dest -> inode - 1; in_cur->i_links_count++; int len_req = strlen(table_path_src[count_path_src - 1]) + 8; struct ext2_dir_entry_2 *ptr_dir = get_free_space(in_cur, len_req); if(ptr_dir == 0) { int free_block_new = get_free_block(bm_block, ptr_super_block); ptr_dir = (void*)ptr_disk + EXT2_BLOCK_SIZE * (free_block_new + 1); ptr_dir -> inode = fr_inode + 1; ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]); ptr_dir -> file_type = EXT2_FT_DIR; strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]); ptr_dir -> rec_len = BLOCK_SIZE; in_src -> i_blocks += 2; in_src ->i_block[in_src -> i_size / BLOCK_SIZE] = free_block_new + 1; in_src -> i_size += BLOCK_SIZE; } else { int new_rec_len = ptr_dir -> rec_len - (4 * (ptr_dir -> name_len) + 8); ptr_dir -> rec_len = 4 * (ptr_dir -> name_len) + 8; ptr_dir = (void*)ptr_dir + ptr_dir -> rec_len; ptr_dir -> rec_len = new_rec_len; ptr_dir -> inode = fr_inode + 1; ptr_dir -> name_len = strlen(table_path_dest[count_path_dest - 1]); ptr_dir -> file_type = EXT2_FT_REG_FILE; strcpy(ptr_dir -> name, table_path_dest[count_path_dest - 1]); } ptr_group_desc->bg_used_dirs_count++; return 0; }