The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ncpfs/file.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  file.c
    3  *
    4  *  Copyright (C) 1995, 1996 by Volker Lendecke
    5  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
    6  *
    7  */
    8 
    9 #include <asm/uaccess.h>
   10 #include <asm/system.h>
   11 
   12 #include <linux/sched.h>
   13 #include <linux/kernel.h>
   14 #include <linux/errno.h>
   15 #include <linux/fcntl.h>
   16 #include <linux/stat.h>
   17 #include <linux/mm.h>
   18 #include <linux/locks.h>
   19 #include <linux/slab.h>
   20 #include <linux/vmalloc.h>
   21 
   22 #include <linux/ncp_fs.h>
   23 #include "ncplib_kernel.h"
   24 
   25 static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
   26 {
   27         return 0;
   28 }
   29 
   30 /*
   31  * Open a file with the specified read/write mode.
   32  */
   33 int ncp_make_open(struct inode *inode, int right)
   34 {
   35         int error;
   36         int access;
   37 
   38         error = -EINVAL;
   39         if (!inode) {
   40                 printk(KERN_ERR "ncp_make_open: got NULL inode\n");
   41                 goto out;
   42         }
   43 
   44         DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
   45                 atomic_read(&NCP_FINFO(inode)->opened), 
   46                 NCP_FINFO(inode)->volNumber, 
   47                 NCP_FINFO(inode)->dirEntNum);
   48         error = -EACCES;
   49         down(&NCP_FINFO(inode)->open_sem);
   50         if (!atomic_read(&NCP_FINFO(inode)->opened)) {
   51                 struct ncp_entry_info finfo;
   52                 int result;
   53 
   54                 finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
   55                 finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
   56                 /* tries max. rights */
   57                 finfo.access = O_RDWR;
   58                 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
   59                                         NULL, NULL, OC_MODE_OPEN,
   60                                         0, AR_READ | AR_WRITE, &finfo);
   61                 if (!result)
   62                         goto update;
   63                 /* RDWR did not succeeded, try readonly or writeonly as requested */
   64                 switch (right) {
   65                         case O_RDONLY:
   66                                 finfo.access = O_RDONLY;
   67                                 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
   68                                         NULL, NULL, OC_MODE_OPEN,
   69                                         0, AR_READ, &finfo);
   70                                 break;
   71                         case O_WRONLY:
   72                                 finfo.access = O_WRONLY;
   73                                 result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
   74                                         NULL, NULL, OC_MODE_OPEN,
   75                                         0, AR_WRITE, &finfo);
   76                                 break;
   77                 }
   78                 if (result) {
   79                         PPRINTK("ncp_make_open: failed, result=%d\n", result);
   80                         goto out_unlock;
   81                 }
   82                 /*
   83                  * Update the inode information.
   84                  */
   85         update:
   86                 ncp_update_inode(inode, &finfo);
   87                 atomic_set(&NCP_FINFO(inode)->opened, 1);
   88         }
   89 
   90         access = NCP_FINFO(inode)->access;
   91         PPRINTK("ncp_make_open: file open, access=%x\n", access);
   92         if (access == right || access == O_RDWR) {
   93                 atomic_inc(&NCP_FINFO(inode)->opened);
   94                 error = 0;
   95         }
   96 
   97 out_unlock:
   98         up(&NCP_FINFO(inode)->open_sem);
   99 out:
  100         return error;
  101 }
  102 
  103 static ssize_t
  104 ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
  105 {
  106         struct dentry *dentry = file->f_dentry;
  107         struct inode *inode = dentry->d_inode;
  108         size_t already_read = 0;
  109         off_t pos;
  110         size_t bufsize;
  111         int error;
  112         void* freepage;
  113         size_t freelen;
  114 
  115         DPRINTK("ncp_file_read: enter %s/%s\n",
  116                 dentry->d_parent->d_name.name, dentry->d_name.name);
  117 
  118         error = -EIO;
  119         if (!ncp_conn_valid(NCP_SERVER(inode)))
  120                 goto out;
  121         error = -EINVAL;
  122         if (!S_ISREG(inode->i_mode)) {
  123                 DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
  124                         inode->i_mode);
  125                 goto out;
  126         }
  127 
  128         pos = *ppos;
  129 /* leave it out on server ...
  130         if (pos + count > inode->i_size) {
  131                 count = inode->i_size - pos;
  132         }
  133 */
  134         error = 0;
  135         if (!count)     /* size_t is never < 0 */
  136                 goto out;
  137 
  138         error = ncp_make_open(inode, O_RDONLY);
  139         if (error) {
  140                 DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
  141                 goto out;
  142         }
  143 
  144         bufsize = NCP_SERVER(inode)->buffer_size;
  145 
  146         error = -EIO;
  147         freelen = ncp_read_bounce_size(bufsize);
  148         freepage = vmalloc(freelen);
  149         if (!freepage)
  150                 goto outrel;
  151         error = 0;
  152         /* First read in as much as possible for each bufsize. */
  153         while (already_read < count) {
  154                 int read_this_time;
  155                 size_t to_read = min_t(unsigned int,
  156                                      bufsize - (pos % bufsize),
  157                                      count - already_read);
  158 
  159                 error = ncp_read_bounce(NCP_SERVER(inode),
  160                                 NCP_FINFO(inode)->file_handle,
  161                                 pos, to_read, buf, &read_this_time, 
  162                                 freepage, freelen);
  163                 if (error) {
  164                         error = -EIO;   /* NW errno -> Linux errno */
  165                         break;
  166                 }
  167                 pos += read_this_time;
  168                 buf += read_this_time;
  169                 already_read += read_this_time;
  170 
  171                 if (read_this_time != to_read) {
  172                         break;
  173                 }
  174         }
  175         vfree(freepage);
  176 
  177         *ppos = pos;
  178 
  179         if (!IS_RDONLY(inode)) {
  180                 inode->i_atime = CURRENT_TIME;
  181         }
  182         
  183         DPRINTK("ncp_file_read: exit %s/%s\n",
  184                 dentry->d_parent->d_name.name, dentry->d_name.name);
  185 outrel:
  186         ncp_inode_close(inode);         
  187 out:
  188         return already_read ? already_read : error;
  189 }
  190 
  191 static ssize_t
  192 ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
  193 {
  194         struct dentry *dentry = file->f_dentry;
  195         struct inode *inode = dentry->d_inode;
  196         size_t already_written = 0;
  197         off_t pos;
  198         size_t bufsize;
  199         int errno;
  200         void* bouncebuffer;
  201 
  202         DPRINTK("ncp_file_write: enter %s/%s\n",
  203                 dentry->d_parent->d_name.name, dentry->d_name.name);
  204         errno = -EIO;
  205         if (!ncp_conn_valid(NCP_SERVER(inode)))
  206                 goto out;
  207         if (!S_ISREG(inode->i_mode)) {
  208                 DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
  209                         inode->i_mode);
  210                 return -EINVAL;
  211         }
  212 
  213         errno = 0;
  214         if (!count)
  215                 goto out;
  216         errno = ncp_make_open(inode, O_WRONLY);
  217         if (errno) {
  218                 DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
  219                 return errno;
  220         }
  221         pos = *ppos;
  222 
  223         if (file->f_flags & O_APPEND) {
  224                 pos = inode->i_size;
  225         }
  226         bufsize = NCP_SERVER(inode)->buffer_size;
  227 
  228         already_written = 0;
  229 
  230         bouncebuffer = vmalloc(bufsize);
  231         if (!bouncebuffer) {
  232                 errno = -EIO;   /* -ENOMEM */
  233                 goto outrel;
  234         }
  235         while (already_written < count) {
  236                 int written_this_time;
  237                 size_t to_write = min_t(unsigned int,
  238                                       bufsize - (pos % bufsize),
  239                                       count - already_written);
  240 
  241                 if (copy_from_user(bouncebuffer, buf, to_write)) {
  242                         errno = -EFAULT;
  243                         break;
  244                 }
  245                 if (ncp_write_kernel(NCP_SERVER(inode), 
  246                     NCP_FINFO(inode)->file_handle,
  247                     pos, to_write, bouncebuffer, &written_this_time) != 0) {
  248                         errno = -EIO;
  249                         break;
  250                 }
  251                 pos += written_this_time;
  252                 buf += written_this_time;
  253                 already_written += written_this_time;
  254 
  255                 if (written_this_time != to_write) {
  256                         break;
  257                 }
  258         }
  259         vfree(bouncebuffer);
  260         inode->i_mtime = inode->i_atime = CURRENT_TIME;
  261         
  262         *ppos = pos;
  263 
  264         if (pos > inode->i_size) {
  265                 inode->i_size = pos;
  266         }
  267         DPRINTK("ncp_file_write: exit %s/%s\n",
  268                 dentry->d_parent->d_name.name, dentry->d_name.name);
  269 outrel:
  270         ncp_inode_close(inode);         
  271 out:
  272         return already_written ? already_written : errno;
  273 }
  274 
  275 static int ncp_release(struct inode *inode, struct file *file) {
  276         if (ncp_make_closed(inode)) {
  277                 DPRINTK("ncp_release: failed to close\n");
  278         }
  279         return 0;
  280 }
  281 
  282 struct file_operations ncp_file_operations =
  283 {
  284         llseek:         generic_file_llseek,
  285         read:           ncp_file_read,
  286         write:          ncp_file_write,
  287         ioctl:          ncp_ioctl,
  288         mmap:           ncp_mmap,
  289         release:        ncp_release,
  290         fsync:          ncp_fsync,
  291 };
  292 
  293 struct inode_operations ncp_file_inode_operations =
  294 {
  295         setattr:        ncp_notify_change,
  296 };

Cache object: 3407f745f6f438e39fcc8720be3e4ab3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.