// Changes the permissions of the file unsigned int fs_chmod(char * filename, int perms) { int current_uid = current_ttyc()->uid; int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if (namenode) { inode_read(namenode, &n); if (n.uid == current_uid || current_uid == 0) { n.i_file_acl = perms; inode_write(namenode, &n); } else { return ERR_PERMS; } return 1; } else { return ERR_NO_EXIST; } }
// Returns the inode's permissions unsigned int fs_getmod(char * filename) { int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if (namenode) { inode_read(namenode, &n); return n.i_file_acl & 0777; } else { return ERR_NO_EXIST; } }
// Changes the inode's owner unsigned int fs_chown(char * filename, char * username) { int new_uid = user_exists(username); int current_uid = current_ttyc()->uid; int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if (namenode && new_uid != -1) { inode_read(namenode, &n); if (n.uid == current_uid || current_uid == 0) { n.uid = new_uid; inode_write(namenode, &n); } else { return ERR_PERMS; } return 1; } else { return ERR_NO_EXIST; } }
/* Opens a file descriptor and sets it's type, data and permissions*/ int fd_open_with_index (int fd, int type, void * data, int perms) { if(files_allocd == 0) { files_alloc(); } if(!files[fd].used) { files[fd].type = type; files[fd].data = data; files[fd].perms = perms; switch(files[fd].type) { case _FD_TTY: // break; case _FD_FIFO: files[fd].fifo_inode = (int) fs_open_fifo(data, current_ttyc()->pwd, perms); // Fifos are stored with their own id... if(files[fd].fifo_inode > 0) { files[fd].data = (void *) fifo_make(files[fd].fifo_inode); } break; case _FD_FILE: files[fd].data = (void *)fs_open_reg_file(data, current_ttyc()->pwd, perms); // Inodes are stoded with their inode number. if(files[fd].data > 0 && fs_is_fifo((int)files[fd].data)) { files[fd].fifo_inode = (int) files[fd].data; files[fd].data = (void *) fifo_make(files[fd].fifo_inode); files[fd].type = _FD_FIFO; } break; default: return -1; } } // Errors... if((int)files[fd].fifo_inode < 0 && type == _FD_FIFO) { return (int)files[fd].fifo_inode; } if((int)files[fd].data < 0 && type == _FD_FILE) { return (int)files[fd].data; } files[fd].used++; return fd; }
// Changes the directory int fs_cd(char * name) { int start_inode = current_ttyc()->pwd; int namenode = fs_indir(name, start_inode); if (namenode) { inode_read(namenode, &n); if(n.mode & EXT2_S_IFLNK) { if (bitmap_read(bm_inodes, n.data_blocks[0] - 1)) current_ttyc()->pwd = n.data_blocks[0]; else { return ERR_NO_EXIST; } } else { current_ttyc()->pwd = namenode; } return 1; } else { return ERR_NO_EXIST; } }
// Gets info from the file void fs_finfo(char * filename, int * data) { int start_inode = current_ttyc()->pwd; int namenode = fs_indir(filename, start_inode); if(namenode) { inode_read(namenode, &n); data[0] = namenode; // Inode data[1] = n.blocks / 2; // Blocks data[2] = n.blocks / 2 * 1024; // Bytes data[3] = n.i_file_acl; // Permissions data[4] = n.uid; // UID data[5] = n._dir_inode; // Directory inode } }
// Opens a link filetype unsigned int fs_open_link(char * name, char * target_name) { unsigned int folder_inode = current_ttyc()->pwd; int target_inode = fs_indir(target_name, folder_inode); if(target_inode > 0) { int result = fs_open_file(name, folder_inode, O_NEW, EXT2_S_IFLNK); if(result > 0) { inode_read(result, &n); n.data_blocks[0] = target_inode; inode_write(result, &n); return 1; } else { return result; } } else { return ERR_NO_EXIST; } }
// Tells the current location char * fs_pwd() { int j = 1023; int i = 0; for(; i < 1024; ++i) { pwd_string[i] = 0; } int start_inode = current_ttyc()->pwd; inode_read(start_inode, &n); while(n._dir_inode != start_inode) { int _old_dirnode = n._dir_inode; char * name = fs_iname(start_inode, n._dir_inode); int k = strlen(name) - 2; for(; k >= 0; k--, j--) { pwd_string[j] = name[k]; } pwd_string[j] = '/'; j--; start_inode = _old_dirnode; inode_read(start_inode, &n); } if(j == 1023) { pwd_string[j] = '/'; } else { j++; } for(i = 0; j < 1024; i++,j++) { pwd_string[i] = pwd_string[j]; pwd_string[j] = 0; } return pwd_string; }
// Tells if the current user has permissions to make an action in the given inode unsigned int fs_has_perms(inode * n, int for_what) { if (!fs_done) { // If the kernel's not ready then we can do anything. // We're like, Chuck Norris, a superroot or Chuck Testa. return 1; } int current_uid = current_ttyc()->uid; int current_gid = user_gid(current_uid); int file_gid = user_gid(n->uid); int can = 0; if(for_what == ACTION_READ) { if (n->uid == current_uid && (n->i_file_acl & 0400)) { can = 1; } if (file_gid == current_gid && (n->i_file_acl & 0040)) { can = 1; } if (n->i_file_acl & 0004) { can = 1; } } else if(for_what == ACTION_WRITE) { if (n->uid == current_uid && (n->i_file_acl & 0200)) { can = 1; } if (file_gid == current_gid && (n->i_file_acl & 0020)) { can = 1; } if (n->i_file_acl & 0002) { can = 1; } } return can; }
// 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; }
// INT 80h Handler, kernel entry. void int_80() { if(krn) { return; } krn++; int systemCall = kernel_buffer[0]; int fd = kernel_buffer[1]; int buffer = kernel_buffer[2]; int count = kernel_buffer[3]; int i, j; Process * current; Process * p; int inode; int _fd; // Yeah, wanna know why we don't access an array directly? ... Because of big bugs we might have. switch(systemCall) { case READY: kernel_buffer[KERNEL_RETURN] = kernel_ready(); break; case WRITE: current = getp(); kernel_buffer[KERNEL_RETURN] = fd_write(current->file_descriptors[fd],(char *)buffer,count); break; case READ: current = getp(); kernel_buffer[KERNEL_RETURN] = fd_read(current->file_descriptors[fd],(char *)buffer,count); break; case MKFIFO: _fd = process_getfreefd(); fd = fd_open(_FD_FIFO, (void *)kernel_buffer[1],kernel_buffer[2]); if(_fd != -1 && fd != -1) { getp()->file_descriptors[_fd] = fd; kernel_buffer[KERNEL_RETURN] = _fd; } else { kernel_buffer[KERNEL_RETURN] = -1; } break; case OPEN: _fd = process_getfreefd(); fd = fd_open(_FD_FILE, (void *) kernel_buffer[1], kernel_buffer[2]); if(_fd != -1 && fd >= 0) { getp()->file_descriptors[_fd] = fd; kernel_buffer[KERNEL_RETURN] = _fd; } else { kernel_buffer[KERNEL_RETURN] = fd; } break; case CLOSE: kernel_buffer[KERNEL_RETURN] = fd_close(getp()->file_descriptors[fd]); break; case PCREATE: kernel_buffer[KERNEL_RETURN] = sched_pcreate(kernel_buffer[1],kernel_buffer[2],kernel_buffer[3]); break; case PRUN: kernel_buffer[KERNEL_RETURN] = sched_prun(kernel_buffer[1]); break; case PDUP2: kernel_buffer[KERNEL_RETURN] = sched_pdup2(kernel_buffer[1],kernel_buffer[2],kernel_buffer[3]); break; case GETPID: kernel_buffer[KERNEL_RETURN] = sched_getpid(); break; case WAITPID: kernel_buffer[KERNEL_RETURN] = sched_waitpid(kernel_buffer[1]); break; case PTICKS: kernel_buffer[KERNEL_RETURN] = (int) storage_index(); break; case PNAME: p = process_getbypid(kernel_buffer[1]); if(p == NULL) { kernel_buffer[KERNEL_RETURN] = (int) NULL; } else { kernel_buffer[KERNEL_RETURN] = (int) p->name; } break; case PSTATUS: p = process_getbypid(kernel_buffer[1]); if(p == NULL) { kernel_buffer[KERNEL_RETURN] = (int) -1; } else { kernel_buffer[KERNEL_RETURN] = (int) p->state; } break; case PPRIORITY: p = process_getbypid(kernel_buffer[1]); if(p == NULL) { kernel_buffer[KERNEL_RETURN] = (int) -1; } else { kernel_buffer[KERNEL_RETURN] = (int) p->priority; } break; case PGID: p = process_getbypid(kernel_buffer[1]); if(p == NULL) { kernel_buffer[KERNEL_RETURN] = (int) -1; } else { kernel_buffer[KERNEL_RETURN] = (int) p->gid; } break; case PGETPID_AT: p = process_getbypindex(kernel_buffer[1]); if (p->state != -1) { kernel_buffer[KERNEL_RETURN] = (int) p->pid; } else { kernel_buffer[KERNEL_RETURN] = -1; } break; case KILL: kernel_buffer[KERNEL_RETURN - 1] = kernel_buffer[1]; kernel_buffer[KERNEL_RETURN - 2] = kernel_buffer[2]; break; case PSETP: p = process_getbypid(kernel_buffer[1]); if(p == NULL) { kernel_buffer[KERNEL_RETURN] = (int) -1; } else { if(kernel_buffer[2] <= 4 && kernel_buffer[2] >= 0) { p->priority = kernel_buffer[2]; } kernel_buffer[KERNEL_RETURN] = (int) p->gid; } break; case SETSCHED: sched_set_mode(kernel_buffer[1]); break; case PWD: kernel_buffer[KERNEL_RETURN] = (int) fs_pwd(); break; case CD: kernel_buffer[KERNEL_RETURN] = (int) fs_cd(kernel_buffer[1]); break; case FINFO: fs_finfo(kernel_buffer[1], kernel_buffer[2]); break; case MOUNT: fs_init(); break; case MKDIR: kernel_buffer[KERNEL_RETURN] = (int) fs_mkdir(kernel_buffer[1],current_ttyc()->pwd); break; case RM: inode = fs_indir(kernel_buffer[1],current_ttyc()->pwd); if (inode) { kernel_buffer[KERNEL_RETURN] = (int) fs_rm(inode,0); } else { kernel_buffer[KERNEL_RETURN] = ERR_NO_EXIST; } break; case GETUID: if(kernel_buffer[1] == 0) { kernel_buffer[KERNEL_RETURN] = (int) current_ttyc()->uid; } else { kernel_buffer[KERNEL_RETURN] = (int) user_exists(kernel_buffer[1]); } break; case GETGID: if(kernel_buffer[1] == 0) { kernel_buffer[KERNEL_RETURN] = (int) user_gid(current_ttyc()->uid); } else { kernel_buffer[KERNEL_RETURN] = (int) user_gid(kernel_buffer[1]); } break; case MAKEUSER: kernel_buffer[KERNEL_RETURN] = user_create(kernel_buffer[1], kernel_buffer[2], user_gid(current_ttyc()->uid)); break; case SETGID: kernel_buffer[KERNEL_RETURN] = user_setgid(kernel_buffer[1], kernel_buffer[2]); break; case UDELETE: kernel_buffer[KERNEL_RETURN] = user_delete(kernel_buffer[1]); break; case UEXISTS: kernel_buffer[KERNEL_RETURN] = user_exists(kernel_buffer[1]); break; case ULOGIN: kernel_buffer[KERNEL_RETURN] = user_login(kernel_buffer[1], kernel_buffer[2]); break; case ULOGOUT: kernel_buffer[KERNEL_RETURN] = user_logout(); break; case CHOWN: kernel_buffer[KERNEL_RETURN] = fs_chown(kernel_buffer[1], kernel_buffer[2]); break; case CHMOD: kernel_buffer[KERNEL_RETURN] = fs_chmod(kernel_buffer[1], kernel_buffer[2]); break; case GETOWN: kernel_buffer[KERNEL_RETURN] = fs_getown(kernel_buffer[1]); break; case GETMOD: kernel_buffer[KERNEL_RETURN] = fs_getmod(kernel_buffer[1]); break; case CP: kernel_buffer[KERNEL_RETURN] = fs_cp(kernel_buffer[1], kernel_buffer[2], current_ttyc()->pwd, current_ttyc()->pwd); break; case MV: kernel_buffer[KERNEL_RETURN] = fs_mv(kernel_buffer[1], kernel_buffer[2], current_ttyc()->pwd); break; case LINK: kernel_buffer[KERNEL_RETURN] = fs_open_link(kernel_buffer[1], kernel_buffer[2], current_ttyc()->pwd); break; case FSSTAT: kernel_buffer[KERNEL_RETURN] = fs_stat(kernel_buffer[1]); break; case SLEEP: kernel_buffer[KERNEL_RETURN] = scheduler_sleep(kernel_buffer[1]); break; default: break; } krn--; }