/* * file.c * * Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */ #include #include #include #include #include #include #include #include #include #include static inline int min(int a, int b) { return a < b ? a : b; } static int smb_fsync(struct inode *inode, struct file *file) { return 0; } int smb_make_open(struct inode *i, int right) { struct smb_dirent *dirent; if (i == NULL) { printk("smb_make_open: got NULL inode\n"); return -EINVAL; } dirent = &(SMB_INOP(i)->finfo); DDPRINTK("smb_make_open: dirent->opened = %d\n", dirent->opened); if ((dirent->opened) == 0) { /* tries max. rights */ int open_result = smb_proc_open(SMB_SERVER(i), SMB_INOP(i)->dir, dirent->name, dirent->len, dirent); if (open_result) { return open_result; } } 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 long smb_file_read(struct inode *inode, struct file *file, char *buf, unsigned long count) { int result, bufsize, to_read, already_read; off_t pos; int errno; DPRINTK("smb_file_read: enter %s\n", SMB_FINFO(inode)->name); if (!inode) { DPRINTK("smb_file_read: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { DPRINTK("smb_file_read: read from non-file, mode %07o\n", inode->i_mode); return -EINVAL; } if ((errno = smb_make_open(inode, O_RDONLY)) != 0) return errno; pos = file->f_pos; if (pos + count > inode->i_size) { count = inode->i_size - pos; } if (count <= 0) { return 0; } bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; already_read = 0; /* First read in as much as possible for each bufsize. */ while (already_read < count) { to_read = min(bufsize, count - already_read); result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode), pos, to_read, buf, 1); if (result < 0) { return result; } pos += result; buf += result; already_read += result; if (result < to_read) { break; } } file->f_pos = pos; if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME; inode->i_dirt = 1; DPRINTK("smb_file_read: exit %s\n", SMB_FINFO(inode)->name); return already_read; } static long smb_file_write(struct inode *inode, struct file *file, const char *buf, unsigned long count) { int result, bufsize, to_write, already_written; off_t pos; int errno; if (!inode) { DPRINTK("smb_file_write: inode = NULL\n"); return -EINVAL; } if (!S_ISREG(inode->i_mode)) { DPRINTK("smb_file_write: write to non-file, mode %07o\n", inode->i_mode); return -EINVAL; } DPRINTK("smb_file_write: enter %s\n", SMB_FINFO(inode)->name); if (count <= 0) { return 0; } if ((errno = smb_make_open(inode, O_RDWR)) != 0) { return errno; } pos = file->f_pos; if (file->f_flags & O_APPEND) pos = inode->i_size; bufsize = SMB_SERVER(inode)->max_xmit - SMB_HEADER_LEN - 5 * 2 - 5; already_written = 0; DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n", SMB_SERVER(inode)->blkmode, SMB_SERVER(inode)->blkmode & 2); while (already_written < count) { to_write = min(bufsize, count - already_written); result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode), pos, to_write, buf); if (result < 0) { return result; } pos += result; buf += result; already_written += result; if (result < 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("smb_file_write: exit %s\n", SMB_FINFO(inode)->name); return already_written; } static struct file_operations smb_file_operations = { NULL, /* lseek - default */ smb_file_read, /* read */ smb_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* poll - default */ smb_ioctl, /* ioctl */ smb_mmap, /* mmap */ NULL, /* open */ NULL, /* release */ smb_fsync, /* fsync */ }; struct inode_operations smb_file_inode_operations = { &smb_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, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ NULL /* truncate */ };