def create_inode_table(): first_data_block = fs.bytes_to_int( superblock.get_field(superblock.s_first_data_block)) inodetable_block = inodetable.load_inode(0) table_number = inodetable.get_table_number(0) inodetable_block.set_field( table_number, inodetable_block.i_mode, inodetable.S_IFDIR | inodetable.S_IXUSR | inodetable.S_IRUSR | inodetable.S_IWUSR | inodetable.S_IXOTH | inodetable.S_IROTH | inodetable.S_IWOTH | inodetable.S_IWGRP | inodetable.S_IRGRP | inodetable.S_IXGRP) inodetable_block.set_field(table_number, inodetable_block.i_uid, 0) inodetable_block.set_field(table_number, inodetable_block.i_size, 0) inodetable_block.set_field(table_number, inodetable_block.i_atime, 0) inodetable_block.set_field(table_number, inodetable_block.i_mtime, 0) inodetable_block.set_field(table_number, inodetable_block.i_ctime, int(time.time())) inodetable_block.set_field(table_number, inodetable_block.i_dtime, 0) inodetable_block.set_field(table_number, inodetable_block.i_gid, 0) inodetable_block.set_field(table_number, inodetable_block.i_blocks, 1) inodetable_block.set_field(table_number, inodetable_block.i_flags, 0) block = bytearray(inodetable_block.i_block[sysblock.SIZE_INDEX]) block[:superblock.s_first_data_block[sysblock.SIZE_INDEX]] = \ first_data_block.to_bytes(superblock.s_first_data_block[sysblock.SIZE_INDEX], 'little') inodetable_block.set_field(table_number, inodetable_block.i_block, bytes(block)) inodetable_block.set_field( table_number, inodetable_block.i_pad, bytes(inodetable_block.i_pad[sysblock.SIZE_INDEX])) inodetable.unload_inode(0)
def auth(user, passwd): nonlocal uid, gid if uid != -1: raise AuthError uid, gid = 0, 0 fd = openfile.open_file('/etc/passwd', openfile.O_RDONLY) inode = fdtable.get_inode(fd) inode_tn = inodetable.get_table_number(inode) file_inodetable_block = inodetable.load_inode(inode) file_size = fs.bytes_to_int( file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_size)) lines = readfile.read_by_offset( fd, file_size).decode(encoding='ASCII').splitlines() closefile.close_file(fd) uid, gid = -1, -1 digest = hashlib.sha224(passwd.encode()).hexdigest() for l in lines: if l.lstrip()[0] != '#': u = tuple(l.split(':')) if u[0] == user: if u[1] == digest and u[4] != 'nologin': uid = int(u[2]) gid = int(u[3]) if uid == -1: raise AuthError return uid
def remove_file_record(offset): inode = get_record_inode_number(offset) inode_table_block = inodetable.load_inode(inode) inode_tn = inodetable.get_table_number(inode) i_block = inode_table_block.get_field(inode_tn, inode_table_block.i_block) inodetable.free_file_blocks(inode_table_block, inode, i_block) data_block_buffer.set_bytes(offset, fs.int_to_bytes(0, IN_FIELD_SIZE))
def write_by_offset(fd, buf, nbytes): inode = fdtable.get_inode(fd) offset = fdtable.get_offset(fd) inode_tn = inodetable.get_table_number(inode) file_inodetable_block = inodetable.load_inode(inode) i_block = file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_block) file_size = fs.bytes_to_int( file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_size)) blocks_count = fs.bytes_to_int( file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_blocks)) block_size = fs.bytes_to_int( superblock.get_field(superblock.s_log_block_size)) * 1024 lbn = offset // block_size b_offset = offset % block_size if offset + nbytes > file_size: if b_offset + nbytes > block_size or lbn == blocks_count: inodetable.extend_file_blocks(file_inodetable_block, inode, i_block) file_inodetable_block.set_field(inode_tn, file_inodetable_block.i_size, offset + nbytes) bn = inodetable.lbn_to_bn(lbn, i_block) data_block_buffer.load(bn) if b_offset + nbytes > block_size: first_bytes_count = block_size - b_offset if first_bytes_count != 0: data_block_buffer.set_bytes(b_offset, buf[:first_bytes_count]) data_block_buffer.unload(bn) bn = inodetable.lbn_to_bn(lbn + 1, i_block) data_block_buffer.load(bn) data_block_buffer.set_bytes(0, buf[first_bytes_count:nbytes]) else: data_block_buffer.set_bytes(b_offset, buf) data_block_buffer.unload(bn) fdtable.set_offset(fd, offset + nbytes) file_inodetable_block.set_field(inode_tn, file_inodetable_block.i_mtime, int(time.time())) inodetable.unload_inode(inode)
def chmod(path, mode): fd = openfile.create_file_descriptor(path, openfile.O_RDONLY, 0) ino = fdtable.get_inode(fd) inode_tn = inodetable.get_table_number(ino) inode_block = inodetable.load_inode(ino) i_mode = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_mode)) i_uid = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_uid)) try: if user.get_uid() != i_uid and user.get_uid() != 0: raise permissions.PermissionsError(i_mode) if i_mode & inodetable.S_IFREG == inodetable.S_IFREG: inode_block.set_field(inode_tn, inode_block.i_mode, inodetable.S_IFREG | int(mode)) else: inode_block.set_field(inode_tn, inode_block.i_mode, inodetable.S_IFDIR | int(mode)) finally: inodetable.unload_inode(ino) closefile.close_file(fd) return 0
def write_to_end(fd, buf, nbytes): inode = fdtable.get_inode(fd) inode_tn = inodetable.get_table_number(inode) file_inodetable_block = inodetable.load_inode(inode) i_block = file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_block) file_size = fs.bytes_to_int( file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_size)) block_size = fs.bytes_to_int( superblock.get_field(superblock.s_log_block_size)) * 1024 last_block_size = file_size % block_size if last_block_size == 0: last_bn = inodetable.extend_file_blocks(file_inodetable_block, inode, i_block) else: last_bn = inodetable.get_last_file_bn(i_block) data_block_buffer.load(last_bn) if last_block_size + nbytes > block_size: last_bn = inodetable.extend_file_blocks(file_inodetable_block, inode, i_block) remaining_bytes_count = block_size - last_block_size data_block_buffer.set_bytes(last_block_size, buf[:remaining_bytes_count]) data_block_buffer.unload(data_block_buffer.block_number) data_block_buffer.load(last_bn) data_block_buffer.set_bytes(0, buf[remaining_bytes_count:nbytes]) else: data_block_buffer.set_bytes(last_block_size, buf[:nbytes]) file_inodetable_block.set_field(inode_tn, file_inodetable_block.i_size, file_size + nbytes) data_block_buffer.unload(last_bn) file_inodetable_block.set_field(inode_tn, file_inodetable_block.i_mtime, int(time.time())) inodetable.unload_inode(inode)
def read_by_offset(fd, nbytes): inode = fdtable.get_inode(fd) offset = fdtable.get_offset(fd) inode_tn = inodetable.get_table_number(inode) file_inodetable_block = inodetable.load_inode(inode) i_block = file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_block) file_size = fs.bytes_to_int( file_inodetable_block.get_field(inode_tn, file_inodetable_block.i_size)) block_size = fs.bytes_to_int( superblock.get_field(superblock.s_log_block_size)) * 1024 if offset >= file_size: raise OffsetError(offset) lbn = offset // block_size b_offset = offset % block_size buf = bytearray() if b_offset + nbytes > block_size: first_bytes_count = block_size - b_offset data_block_buffer.load(inodetable.lbn_to_bn(lbn, i_block)) buf[:first_bytes_count] = data_block_buffer.get_bytes( b_offset, first_bytes_count) data_block_buffer.load(inodetable.lbn_to_bn(lbn + 1, i_block)) buf[first_bytes_count:nbytes] = data_block_buffer.get_bytes( 0, nbytes - first_bytes_count) else: data_block_buffer.load(inodetable.lbn_to_bn(lbn, i_block)) buf[:] = data_block_buffer.get_bytes(b_offset, nbytes) fdtable.set_offset(fd, offset + nbytes) file_inodetable_block.set_field(inode_tn, file_inodetable_block.i_atime, int(time.time())) inodetable.unload_inode(inode) return bytes(buf)
def stat(path): fd = openfile.create_file_descriptor(path, openfile.O_STAT, 0) ino = fdtable.get_inode(fd) inode_tn = inodetable.get_table_number(ino) inode_block = inodetable.load_inode(ino) mode = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_mode)) uid = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_uid)) gid = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_gid)) size = fs.bytes_to_int(inode_block.get_field(inode_tn, inode_block.i_size)) atime = fs.bytes_to_int( inode_block.get_field(inode_tn, inode_block.i_atime)) mtime = fs.bytes_to_int( inode_block.get_field(inode_tn, inode_block.i_mtime)) ctime = fs.bytes_to_int( inode_block.get_field(inode_tn, inode_block.i_ctime)) blocks = fs.bytes_to_int( inode_block.get_field(inode_tn, inode_block.i_blocks)) inodetable.unload_inode(ino) closefile.close_file(fd) return ino, mode, uid, gid, size, atime, mtime, ctime, blocks
def create_file_descriptor(path, oflag, mode): names = [n for n in path.split('/') if n != ''] dir_table_in = 0 dir_inodetable_block = inodetable.load_inode(dir_table_in) dir_in = 0 perm = inodetable.S_IRUSR | inodetable.S_IRGRP | inodetable.S_IROTH if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if path != '/': if len(names) > 1: for n in names[:-1]: offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, n) inodetable.unload_inode(dir_in) if offset is None: raise createfile.DirNotFoundError(n) dir_in = filerecord.get_record_inode_number(offset) dir_table_in = inodetable.get_table_number(dir_in) dir_inodetable_block = inodetable.load_inode(dir_in) if not permissions.check_file_permissions( dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if fs.bytes_to_int( dir_inodetable_block.get_field( dir_table_in, dir_inodetable_block.i_mode) ) & inodetable.S_IFDIR != inodetable.S_IFDIR: raise createfile.DirNotFoundError(n) offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, names[-1]) if oflag == O_WRONLY: perm = inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH if oflag == O_RDWR: perm |= inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH if offset is None: raise deletefile.FileNotExistsError(names[-1]) inode_n = filerecord.get_record_inode_number(offset) inode_table_n = inodetable.get_table_number(inode_n) file_inodetable_block = inodetable.load_inode(inode_n) else: if oflag == O_WRONLY: perm = inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH if oflag == O_RDWR: perm |= inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH inode_n = dir_in inode_table_n = dir_table_in file_inodetable_block = dir_inodetable_block if fs.bytes_to_int( file_inodetable_block.get_field( inode_table_n, file_inodetable_block.i_mode)) & mode != mode: raise deletefile.WrongFileTypeError(names[-1]) if oflag != O_STAT: if not permissions.check_file_permissions(file_inodetable_block, inode_n, perm): raise permissions.PermissionsError(perm) inodetable.unload_inode(dir_in) inodetable.unload_inode(0) return fdtable.reserve_fd(inode_n)
def create_file_record(path, mode): if path == '/': raise FileAlreadyExistsError('/') names = [n for n in path.split('/') if n != ''] bg_block = gdtable.get_gdtableblock(0) inodebitmap.inode_bitmap.load( fs.bytes_to_int(bg_block.get_field(0, bg_block.bg_inode_bitmap))) inode_ign = inodebitmap.find_first_free_inode() inode_n = fs.ign_to_in( 0, fs.bytes_to_int(superblock.get_field(superblock.s_inodes_per_group)), inode_ign) dir_table_in = 0 dir_inodetable_block = inodetable.load_inode(dir_table_in) dir_in = 0 perm = inodetable.S_IRUSR | inodetable.S_IRGRP | inodetable.S_IROTH if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if len(names) > 1: for n in names[:-1]: offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, n) inodetable.unload_inode(dir_in) if offset is None: raise DirNotFoundError(n) dir_in = filerecord.get_record_inode_number(offset) dir_table_in = inodetable.get_table_number(dir_in) dir_inodetable_block = inodetable.load_inode(dir_in) if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if fs.bytes_to_int( dir_inodetable_block.get_field(dir_table_in, dir_inodetable_block.i_mode) ) & inodetable.S_IFDIR != inodetable.S_IFDIR: raise DirNotFoundError(n) perm = inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, names[-1]) if offset is None: filerecord.create_file_record(dir_inodetable_block, dir_table_in, inode_n, names[-1]) dir_inodetable_block.set_field(dir_table_in, dir_inodetable_block.i_mtime, int(time.time())) else: raise FileAlreadyExistsError(names[-1]) inodetable_block = inodetable.load_inode(inode_n) inodetable_block.set_field(inode_ign, inodetable_block.i_mode, mode) inodetable_block.set_field(inode_ign, inodetable_block.i_uid, user.get_uid()) inodetable_block.set_field(inode_ign, inodetable_block.i_size, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_atime, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_mtime, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_ctime, int(time.time())) inodetable_block.set_field(inode_ign, inodetable_block.i_dtime, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_gid, user.get_gid()) inodetable_block.set_field(inode_ign, inodetable_block.i_blocks, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_flags, 0) inodetable_block.set_field(inode_ign, inodetable_block.i_block, bytes(60)) inodetable_block.set_field( inode_ign, inodetable_block.i_pad, bytes(inodetable_block.i_pad[sysblock.SIZE_INDEX])) inodebitmap.set_used_inode(inode_ign) inodebitmap.inode_bitmap.unload( fs.bytes_to_int(bg_block.get_field(0, bg_block.bg_inode_bitmap))) inodetable.unload_inode(inode_n) inodetable.unload_inode(0) return fdtable.reserve_fd(inode_n)
def delete_file_record(path, mode): if path == '/': raise WrongFileTypeError(path) names = [n for n in path.split('/') if n != ''] bg_block = gdtable.get_gdtableblock(0) inodebitmap.inode_bitmap.load( fs.bytes_to_int(bg_block.get_field(0, bg_block.bg_inode_bitmap))) dir_table_in = 0 dir_inodetable_block = inodetable.load_inode(dir_table_in) dir_in = 0 perm = inodetable.S_IRUSR | inodetable.S_IRGRP | inodetable.S_IROTH if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if len(names) > 1: for n in names[:-1]: offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, n) if dir_in != 0: inodetable.unload_inode(dir_in) if offset is None: raise createfile.DirNotFoundError(n) dir_in = filerecord.get_record_inode_number(offset) dir_table_in = inodetable.get_table_number(dir_in) dir_inodetable_block = inodetable.load_inode(dir_in) if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) if fs.bytes_to_int( dir_inodetable_block.get_field(dir_table_in, dir_inodetable_block.i_mode) ) & inodetable.S_IFDIR != inodetable.S_IFDIR: raise createfile.DirNotFoundError(n) perm = inodetable.S_IWUSR | inodetable.S_IWGRP | inodetable.S_IWOTH if not permissions.check_file_permissions(dir_inodetable_block, dir_in, perm): raise permissions.PermissionsError(perm) offset = filerecord.find_file_record(dir_inodetable_block, dir_table_in, names[-1]) bn = data_block_buffer.block_number if offset is None: raise FileNotExistsError(names[-1]) inode_n = filerecord.get_record_inode_number(offset) inode_table_n = inodetable.get_table_number(inode_n) file_inodetable_block = inodetable.load_inode(inode_n) if fs.bytes_to_int( file_inodetable_block.get_field( inode_table_n, file_inodetable_block.i_mode)) & mode != mode: raise WrongFileTypeError(names[-1]) if mode & inodetable.S_IFDIR == inodetable.S_IFDIR: fd = opendir.opendir(path) try: readdir.readdir(fd) raise DirIsNotEmpty(path) except readfile.OffsetError: pass finally: closedir.closedir(fd) data_block_buffer.load(bn) filerecord.remove_file_record(offset) dir_inodetable_block.set_field(dir_table_in, dir_inodetable_block.i_mtime, int(time.time())) inodebitmap.set_free_inode(inode_table_n) inodebitmap.inode_bitmap.unload( fs.bytes_to_int(bg_block.get_field(0, bg_block.bg_inode_bitmap))) inodetable.unload_inode(inode_n) inodetable.unload_inode(dir_in) inodetable.unload_inode(0) data_block_buffer.unload(data_block_buffer.block_number)