/* * file.c * * Copyright (C) 1995, 1996 by Volker Lendecke * */ #include #include #include #include #include #include #include #include #include #include #include "ncplib_kernel.h" #include static inline int min(int a, int b) { return a < b ? a : b; } static int ncp_fsync(struct inode *inode, struct file *file) { return 0; } int ncp_make_open(struct inode *i, int right) { struct nw_file_info *finfo; if (i == NULL) { printk("ncp_make_open: got NULL inode\n"); return -EINVAL; } finfo = NCP_FINFO(i); DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened); lock_super(i->i_sb); if (finfo->opened == 0) { finfo->access = -1; /* tries max. rights */ if (ncp_open_create_file_or_subdir(NCP_SERVER(i), NULL, NULL, OC_MODE_OPEN, 0, AR_READ | AR_WRITE, finfo) == 0) { finfo->access = O_RDWR; } else if (ncp_open_create_file_or_subdir(NCP_SERVER(i), NULL, NULL, OC_MODE_OPEN, 0, AR_READ, finfo) == 0) { finfo->access = O_RDONLY; } } unlock_super(i->i_sb); if (((right == O_RDONLY) && ((finfo->access == O_RDONLY) || (finfo->access == O_RDWR))) || ((right == O_WRONLY) && ((finfo->access == O_WRONLY) || (finfo->access == O_RDWR))) || ((right == O_RDWR) && (finfo->access == O_RDWR))) return 0; return -EACCES; } static long ncp_file_read(struct inode *inode, struct file *file, char *buf, unsigned long count) { int bufsize, already_read; off_t pos; int errno; DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName); if (inode == NULL) { DPRINTK("ncp_file_read: inode = NULL\n"); return -EINVAL; } if (!ncp_conn_valid(NCP_SERVER(inode))) { return -EIO; } 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; int to_read = min(bufsize - (pos % bufsize), count - already_read); if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 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_ISTRUCT(inode)->entryName); return already_read; } static long ncp_file_write(struct inode *inode, struct file *file, const char *buf, unsigned long count) { int bufsize, already_written; off_t pos; int errno; if (inode == NULL) { DPRINTK("ncp_file_write: inode = NULL\n"); return -EINVAL; } if (!ncp_conn_valid(NCP_SERVER(inode))) { return -EIO; } 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_ISTRUCT(inode)->entryName); 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; int to_write = min(bufsize - (pos % bufsize), count - already_written); if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle, 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; ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode); } DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName); 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, /* poll - default */ ncp_ioctl, /* ioctl */ ncp_mmap, /* 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 */ };