std::shared_ptr<file_ownership_handle> file_handle_pool::register_file(const std::string& file_name) { std::lock_guard<std::mutex> guard(this->m_mutex); std::shared_ptr<file_ownership_handle> ret = get_file_handle(file_name); if (!ret) { logstream(LOG_DEBUG) << "register_file_handle for file " << sanitize_url(file_name) << std::endl; ret = std::make_shared<file_ownership_handle>(file_name, boost::algorithm::starts_with(file_name, "cache://")); m_file_handles[file_name] = ret; } /** This seems to be the safest way to do this. Ideally, we would * like file_ownership_handle to take care of this. However, it * is not certain that the pool will be around when that object is * destroyed, so that brings up a number of possible rare corner * cases to check for. Doing this is simplest for now. */ if( (++this->num_file_registers) % (16*1024) == 0) { for(auto it = m_file_handles.begin(); it != m_file_handles.end();) { if(it->second.expired()) { // Advances to the next element, or m_file_handles.end(); it = m_file_handles.erase(it); } else { ++it; } } } return ret; }
struct file *get_file_pointer(task_t *t, int n) { struct file_ptr *fp = get_file_handle(t, n); if(fp && !fp->fi) panic(PANIC_NOSYNC, "found empty file handle in task %d pointer list", t->pid); return fp ? fp->fi : 0; }
int8_t sd::append_string(uint8_t* filename,uint8_t* buffer){ FIL write_file; get_file_handle(filename,&write_file,FA_OPEN_ALWAYS | FA_WRITE | FA_READ); // open and create if not existing f_lseek(&write_file,write_file.fsize); // append -> jump to end int8_t status=writeString(&write_file,buffer); // write the string f_close(&write_file); // close the file return status; }
void remove_file_pointer(task_t *t, int n) { if(n > FILP_HASH_LEN) return; if(!t || !t->filp) return; struct file_ptr *f = get_file_handle(t, n); if(!f) return; t->filp[n] = 0; task_critical(); f->fi->count--; task_uncritical(); if(!f->fi->count) kfree(f->fi); kfree(f); }
bool file_handle_pool::mark_file_for_delete(std::string file_name) { Dlog_func_entry(); // file is not registered with global pool, let caller // do the actual deletion std::lock_guard<std::mutex> guard(this->m_mutex); std::shared_ptr<file_ownership_handle> handle_ptr = get_file_handle(file_name); if (!handle_ptr) { return false; } else { // Mark the file for deletion and the file will be deleted when going out-of-scope logstream(LOG_DEBUG) << "mark file " << file_name << " for deletion " << std::endl; handle_ptr->delete_on_destruction(); return true; } }
int16_t sd::get_line_n(int16_t line_nr,uint8_t* filename,uint8_t* buffer,uint16_t max_length, uint16_t* lines_in_file){ FIL read_file; if(get_file_handle(filename,&read_file,FA_READ)<0){ sd_failed=true; return -1; } bool found=false; bool eof=false; int16_t cur_line=0; int16_t buf_pointer=0; uint8_t char_buf[1]={0x00}; ////////// suche den anfang der richtigen zeile while(!found && !eof){ // solange suchen bis wir entweder den Datensatz oder das ende haben UINT n; f_read(&read_file,char_buf, 1,&n); // jeweils nur 1 uint8_t lesen if(n==1){ // true, if not end of file if(char_buf[0]==0x0A){ // find end of line if(buf_pointer<max_length) buffer[buf_pointer]=0x00; // if end reach, terminate string buf_pointer=0; // reset buf write pointer if(cur_line==line_nr){ // if we have "our" line found=true; // we found the right line }; cur_line++; // increase number of read lines } else { // its not \n buffer[buf_pointer]=char_buf[0]; // so store it in the buffer if(buf_pointer<max_length) buf_pointer++; // and increase the pointer until max }; } else { // if we were unable to read one further uint8_t eof=true; // we have reached the eof before reading the target line }; } f_close(&read_file); *lines_in_file=cur_line-1; if(eof){ return -2; } return 0; }
int reg_export(int argc, WCHAR *argv[]) { HKEY root, hkey; WCHAR *path, *long_key; BOOL overwrite_file = FALSE; HANDLE hFile; int ret; if (argc == 3 || argc > 5) goto error; if (!parse_registry_key(argv[2], &root, &path, &long_key)) return 1; if (argc == 5 && !(overwrite_file = is_overwrite_switch(argv[4]))) goto error; if (RegOpenKeyExW(root, path, 0, KEY_READ, &hkey)) { output_message(STRING_INVALID_KEY); return 1; } hFile = get_file_handle(argv[3], overwrite_file); export_file_header(hFile); ret = export_registry_data(hFile, hkey, long_key); export_newline(hFile); CloseHandle(hFile); RegCloseKey(hkey); return ret; error: output_message(STRING_INVALID_SYNTAX); output_message(STRING_FUNC_HELP, struprW(argv[1])); return 1; }
int sd::get_file_handle(unsigned char *pathToFile,FIL *file_handle,uint8_t flags){ unsigned char last_filename_buffer[strlen((char*)pathToFile)]; return get_file_handle(pathToFile,last_filename_buffer,file_handle,flags); }
/** * main_enc_dec * @f: pointer to struct which contains information about input,temporary and output files * @user_args: pointer to struct user_args_t which contains arguments given by user in user-space * * Initiates basic validation checks to be performed before starting encryption/decryption. Gets the required file handles. Post encryption * or decryption, renames and unlinks the file as required. * * Returns 0 on success;non-zero otherwise */ int main_enc_dec(struct file_struct *f, struct user_args_t *user_args) { int err, tmp_err; char *key_hash; struct dentry *lower_old_dentry; struct dentry *lower_new_dentry; struct dentry *lower_old_dir_dentry; struct dentry *lower_new_dir_dentry; struct dentry *trap = NULL; err = validate_in_out_file(f); f->filp_in = f->filp_out = f->filp_temp = NULL; if (err) { printk(KERN_ALERT"error in validate in out"); goto ERR; } key_hash = get_key_hash(user_args->enc_key); if (IS_ERR(key_hash)) { err = PTR_ERR(key_hash); goto ERR; } err = get_file_handle(&(f->filp_in), f->in_file->name, O_RDONLY, 0); if (err) goto ERR_KEY; if (!(f->filp_in->f_op->read)) { printk(KERN_ALERT"read operation not supported\n"); err = -EPERM; goto ERR_IN; } printk(KERN_ALERT"read file permission\n"); if (f->create_out_file == 'y') { printk(KERN_ALERT"file with default permission\n"); err = get_file_handle(&(f->filp_temp), "/tmp/my_temp_file", O_WRONLY|O_CREAT|O_TRUNC, 0666-current_umask()); } else { printk(KERN_ALERT"creating file with outfile mode\n"); err = get_file_handle(&(f->filp_temp), "/tmp/my_temp_file", O_WRONLY|O_CREAT|O_TRUNC, f->out_file_mode); } if (err) goto ERR_IN; printk(KERN_ALERT"file permission for temp file=\n"); printk(KERN_ALERT"\n"); if (user_args->flags == 1) err = encrypt(f, &key_hash[0], user_args); else err = decrypt(f, &key_hash[0], user_args); if (err) { tmp_err = err; err = vfs_unlink(d_inode(f->filp_temp->f_path.dentry->d_parent), f->filp_temp->f_path.dentry, NULL); if (err) printk(KERN_ALERT"Error in unlink\n"); err = tmp_err; goto ERR_IN; } printk(KERN_ALERT"enc/dec done so now doing a rename\n"); if (f->create_out_file == 'y') err = get_file_handle(&(f->filp_out), f->out_file->name, O_WRONLY|O_CREAT|O_TRUNC, 0666-current_umask()); else err = get_file_handle(&(f->filp_out), f->out_file->name, O_WRONLY, 0); if (err) goto ERR_OUT; if (!(f->filp_out->f_op->write)) { printk(KERN_ALERT"write operation not supported\n"); err = -EPERM; goto ERR; } lower_old_dentry = f->filp_temp->f_path.dentry; lower_old_dir_dentry = dget_parent(lower_old_dentry); lower_new_dentry = f->filp_out->f_path.dentry; lower_new_dir_dentry = dget_parent(lower_new_dentry); trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); err = vfs_rename(d_inode(lower_old_dir_dentry), lower_old_dentry, d_inode(lower_new_dir_dentry), lower_new_dentry, NULL, 0); if (err) { printk(KERN_ALERT"error in rename\n"); tmp_err = err; err = vfs_unlink(d_inode(f->filp_temp->f_path.dentry->d_parent), f->filp_temp->f_path.dentry, NULL); if (err) printk(KERN_ALERT"Error in unlink\n"); if (f->create_out_file == 'y') { err = vfs_unlink(d_inode(f->filp_temp->f_path.dentry->d_parent), f->filp_temp->f_path.dentry, NULL); if (err) printk(KERN_ALERT"Error in unlink\n"); } err = tmp_err; } printk(KERN_ALERT"rename done!\n"); unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); if (f->filp_temp) filp_close(f->filp_temp, NULL); ERR_OUT: if (f->filp_out) filp_close(f->filp_out, NULL); ERR_IN: if (f->filp_in) filp_close(f->filp_in, NULL); ERR_KEY: kfree(key_hash); ERR: return err; }
int sys_read(int fd, userptr_t buf, int len, int* retval) { // argument checks. if(fd <0 || fd>= OPEN_MAX) return EBADF; int result; char kern_buffer[len + 1]; // are we using this properly?.. check jinghao's blog for example // no actual use for the kern buffer, just doing this to check if memory location is valid. if(buf!= NULL) { result = copyin(buf, kern_buffer, len); // using this because users are stupid/malicious and can pass invalid memory addresses to the kernel. if(result) { kprintf("read copy in bad \n"); return result; } } struct file_handle* fh = get_file_handle(curproc->t_file_table, fd); if(fh == NULL) return EBADF; if(!can_read(fh->openflags)) // could have other flags Or'd with O_RDONLY, need to change this. return EBADF; // !!!! Should we do copyin's to kernel space, or will the VOP_WRITE take care of the invalid address issue for us. lock_acquire(fh->fh_lock); // IS this really necessary??.. turns out it is , offset should be synchronized. imagine if parent and child call this at the same time. struct iovec iov; struct uio u; iov.iov_ubase = (userptr_t)buf; iov.iov_len = len; // length of the memory space u.uio_iov = &iov; u.uio_iovcnt = 1; u.uio_resid = len; // amount to read from the file u.uio_offset = fh->offset; u.uio_segflg = UIO_USERSPACE; u.uio_rw = UIO_READ; u.uio_space = proc_getas(); // lifted from loadelf.c, is this the right way to do it? result = VOP_READ(fh->file, &u); if (result) { lock_release(fh->fh_lock); return result; } if (u.uio_resid != 0) { // kprintf("ELF: short read on segment - file truncated?\n"); } // should update offset in the file handle.use lock. uio_offset will be updated. can use it directly. fh->offset = u.uio_offset; lock_release(fh->fh_lock); *retval = len - u.uio_resid; // number of bytes gets returned to the user return 0; }