/* * file.c * * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke * */ #include #ifdef MODULE #include #include #endif #include #include #include #include #include #include #include #include #include #include "ncplib.h" #include static int ncp_fsync(struct inode *inode, struct file *file) { return 0; } int ncp_make_open(struct inode *i, int right) { struct ncp_dirent *dirent; if (i == NULL) { printk("ncp_make_open: got NULL inode\n"); return -EINVAL; } dirent = &(NCP_INOP(i)->finfo); DPRINTK("ncp_make_open: dirent->opened = %d\n", dirent->opened); if ((dirent->opened) == 0) { struct ncp_file_info finfo; /* tries max. rights */ if (ncp_open_file(NCP_SERVER(i), 0, dirent->path, 0, AR_READ | AR_WRITE, &finfo) == 0) { dirent->access = O_RDWR; } else if (ncp_open_file(NCP_SERVER(i), 0, dirent->path, 0, AR_READ, &finfo) == 0) { dirent->access = O_RDONLY; } else { return -EACCES; } dirent->opened = 1; memcpy(&(dirent->file_id), finfo.file_id, NCP_FILE_ID_LEN); } if ( ((right == O_RDONLY) && ( (dirent->access == O_RDONLY) || (dirent->access == O_RDWR))) || ((right == O_WRONLY) && ( (dirent->access == O_WRONLY) || (dirent->access == O_RDWR))) || ((right == O_RDWR) && (dirent->access == O_RDWR))) return 0; return -EACCES; } static int ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) { int bufsize, to_read, already_read; off_t pos; int errno; DPRINTK("ncp_file_read: enter %s\n", NCP_FINFO(inode)->path); if (!inode) { DPRINTK("ncp_file_read: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { DPRINTK("ncp_file_read: read from non-file, mode %07o\n", inode->i_mode); return -EINVAL; } pos = file->f_pos; if (pos + count > inode->i_size) count = inode->i_size - pos; if (count <= 0) return 0; if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) return errno; bufsize = NCP_SERVER(inode)->buffer_size; already_read = 0; /* First read in as much as possible for each bufsize. */ while (already_read < count) { int read_this_time; if ((pos % bufsize) != 0) { to_read = bufsize - (pos % bufsize); } else { to_read = bufsize; } to_read = min(to_read, count - already_read); if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_id, pos, to_read, buf, &read_this_time) != 0) { return -EIO; /* This is not exact, i know.. */ } pos += read_this_time; buf += read_this_time; already_read += read_this_time; if (read_this_time < to_read) { break; } } file->f_pos = pos; if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; DPRINTK("ncp_file_read: exit %s\n", NCP_FINFO(inode)->path); return already_read; } static int ncp_file_write(struct inode *inode, struct file *file, const char *buf, int count) { int bufsize, to_write, already_written; off_t pos; int errno; if (!inode) { DPRINTK("ncp_file_write: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { DPRINTK("ncp_file_write: write to non-file, mode %07o\n", inode->i_mode); return -EINVAL; } DPRINTK("ncp_file_write: enter %s\n", NCP_FINFO(inode)->path); if (count <= 0) return 0; if ((errno = ncp_make_open(inode, O_RDWR)) != 0) return errno; pos = file->f_pos; if (file->f_flags & O_APPEND) pos = inode->i_size; bufsize = NCP_SERVER(inode)->buffer_size; already_written = 0; while (already_written < count) { int written_this_time; if ((pos % bufsize) != 0) { to_write = bufsize - (pos % bufsize); } else { to_write = bufsize; } to_write = min(to_write, count - already_written); if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_id, pos, to_write, buf, &written_this_time) != 0) { return -EIO; } pos += written_this_time; buf += written_this_time; already_written += written_this_time; if (written_this_time < to_write) { break; } } inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_dirt = 1; file->f_pos = pos; if (pos > inode->i_size) { inode->i_size = pos; } DPRINTK("ncp_file_write: exit %s\n", NCP_FINFO(inode)->path); return already_written; } static struct file_operations ncp_file_operations = { NULL, /* lseek - default */ ncp_file_read, /* read */ ncp_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ ncp_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* open */ NULL, /* release */ ncp_fsync, /* fsync */ }; struct inode_operations ncp_file_inode_operations = { &ncp_file_operations, /* default file operations */ NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* bmap */ NULL /* truncate */ };