OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [ncpfs/] [inode.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 *  inode.c
 *  inode.c
 *
 *
 *  Copyright (C) 1995, 1996 by Volker Lendecke
 *  Copyright (C) 1995, 1996 by Volker Lendecke
 *
 *
 */
 */
 
 
#include <linux/module.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/config.h>
 
 
#include <asm/system.h>
#include <asm/system.h>
#include <asm/segment.h>
#include <asm/segment.h>
 
 
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/ncp_fs.h>
#include <linux/ncp_fs.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/locks.h>
#include <linux/locks.h>
#include <linux/fcntl.h>
#include <linux/fcntl.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
#ifdef CONFIG_KERNELD
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#include <linux/kerneld.h>
#endif
#endif
#include "ncplib_kernel.h"
#include "ncplib_kernel.h"
 
 
extern int close_fp(struct file *filp);
extern int close_fp(struct file *filp);
 
 
static void ncp_put_inode(struct inode *);
static void ncp_put_inode(struct inode *);
static void ncp_read_inode(struct inode *);
static void ncp_read_inode(struct inode *);
static void ncp_put_super(struct super_block *);
static void ncp_put_super(struct super_block *);
static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
 
 
static struct super_operations ncp_sops = {
static struct super_operations ncp_sops = {
        ncp_read_inode,         /* read inode */
        ncp_read_inode,         /* read inode */
        ncp_notify_change,      /* notify change */
        ncp_notify_change,      /* notify change */
        NULL,                   /* write inode */
        NULL,                   /* write inode */
        ncp_put_inode,          /* put inode */
        ncp_put_inode,          /* put inode */
        ncp_put_super,          /* put superblock */
        ncp_put_super,          /* put superblock */
        NULL,                   /* write superblock */
        NULL,                   /* write superblock */
        ncp_statfs,             /* stat filesystem */
        ncp_statfs,             /* stat filesystem */
        NULL
        NULL
};
};
 
 
/* ncp_read_inode: Called from iget, it only traverses the allocated
/* ncp_read_inode: Called from iget, it only traverses the allocated
   ncp_inode_info's and initializes the inode from the data found
   ncp_inode_info's and initializes the inode from the data found
   there.  It does not allocate or deallocate anything. */
   there.  It does not allocate or deallocate anything. */
 
 
static void
static void
ncp_read_inode(struct inode *inode)
ncp_read_inode(struct inode *inode)
{
{
        /* Our task should be extremely simple here. We only have to
        /* Our task should be extremely simple here. We only have to
           look up the information somebody else (ncp_iget) put into
           look up the information somebody else (ncp_iget) put into
           the inode tree. The address of this information is the
           the inode tree. The address of this information is the
           inode->i_ino. Just to make sure everything went well, we
           inode->i_ino. Just to make sure everything went well, we
           check it's there. */
           check it's there. */
 
 
        struct ncp_inode_info *inode_info = ncp_find_inode(inode);
        struct ncp_inode_info *inode_info = ncp_find_inode(inode);
 
 
        if (inode_info == NULL)
        if (inode_info == NULL)
        {
        {
                /* Ok, now we're in trouble. The inode info is not there. What
                /* Ok, now we're in trouble. The inode info is not there. What
                   should we do now??? */
                   should we do now??? */
                printk("ncp_read_inode: inode info not found\n");
                printk("ncp_read_inode: inode info not found\n");
                return;
                return;
        }
        }
 
 
        inode_info->state = NCP_INODE_VALID;
        inode_info->state = NCP_INODE_VALID;
 
 
        NCP_INOP(inode) = inode_info;
        NCP_INOP(inode) = inode_info;
        inode_info->inode = inode;
        inode_info->inode = inode;
 
 
        if (NCP_ISTRUCT(inode)->attributes & aDIR)
        if (NCP_ISTRUCT(inode)->attributes & aDIR)
        {
        {
                inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
                inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
                /* for directories dataStreamSize seems to be some
                /* for directories dataStreamSize seems to be some
                   Object ID ??? */
                   Object ID ??? */
                inode->i_size = 512;
                inode->i_size = 512;
        }
        }
        else
        else
        {
        {
                inode->i_mode = NCP_SERVER(inode)->m.file_mode;
                inode->i_mode = NCP_SERVER(inode)->m.file_mode;
#if 1
#if 1
                if (NCP_ISTRUCT(inode)->attributes & /* 0x60001 incl. DiRi */ 1) inode->i_mode &= ~0222;
                if (NCP_ISTRUCT(inode)->attributes & /* 0x60001 incl. DiRi */ 1) inode->i_mode &= ~0222;
#endif
#endif
                inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
                inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
        }
        }
 
 
        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 
 
        inode->i_nlink   = 1;
        inode->i_nlink   = 1;
        inode->i_uid     = NCP_SERVER(inode)->m.uid;
        inode->i_uid     = NCP_SERVER(inode)->m.uid;
        inode->i_gid     = NCP_SERVER(inode)->m.gid;
        inode->i_gid     = NCP_SERVER(inode)->m.gid;
        inode->i_blksize = 512;
        inode->i_blksize = 512;
        inode->i_rdev    = 0;
        inode->i_rdev    = 0;
 
 
        if ((inode->i_blksize != 0) && (inode->i_size != 0))
        if ((inode->i_blksize != 0) && (inode->i_size != 0))
        {
        {
                inode->i_blocks =
                inode->i_blocks =
                        (inode->i_size - 1) / inode->i_blksize + 1;
                        (inode->i_size - 1) / inode->i_blksize + 1;
        }
        }
        else
        else
        {
        {
                inode->i_blocks = 0;
                inode->i_blocks = 0;
        }
        }
 
 
        inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
        inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
                                           NCP_ISTRUCT(inode)->modifyDate);
                                           NCP_ISTRUCT(inode)->modifyDate);
        inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
        inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
                                           NCP_ISTRUCT(inode)->creationDate);
                                           NCP_ISTRUCT(inode)->creationDate);
        inode->i_atime = ncp_date_dos2unix(0,
        inode->i_atime = ncp_date_dos2unix(0,
                                           NCP_ISTRUCT(inode)->lastAccessDate);
                                           NCP_ISTRUCT(inode)->lastAccessDate);
 
 
        if (S_ISREG(inode->i_mode))
        if (S_ISREG(inode->i_mode))
        {
        {
                inode->i_op = &ncp_file_inode_operations;
                inode->i_op = &ncp_file_inode_operations;
        }
        }
        else if (S_ISDIR(inode->i_mode))
        else if (S_ISDIR(inode->i_mode))
        {
        {
                inode->i_op = &ncp_dir_inode_operations;
                inode->i_op = &ncp_dir_inode_operations;
        }
        }
        else
        else
        {
        {
                inode->i_op = NULL;
                inode->i_op = NULL;
        }
        }
}
}
 
 
/*
/*
 * Defer release of inode_info and file_info structures until the inode
 * Defer release of inode_info and file_info structures until the inode
 * has been cleared.  This avoids a race condition allowing the inode to
 * has been cleared.  This avoids a race condition allowing the inode to
 * be put back in use before being cleared. Also, temporarily increment
 * be put back in use before being cleared. Also, temporarily increment
 * i_count after clear_inode() so that the inode can't be reused.
 * i_count after clear_inode() so that the inode can't be reused.
 */
 */
static void
static void
ncp_put_inode(struct inode *inode)
ncp_put_inode(struct inode *inode)
{
{
        struct super_block      *sb     = inode->i_sb;
        struct super_block      *sb     = inode->i_sb;
        struct ncp_server       *server = NCP_SERVER(inode);
        struct ncp_server       *server = NCP_SERVER(inode);
        struct ncp_inode_info   *iinfo  = NCP_INOP(inode);
        struct ncp_inode_info   *iinfo  = NCP_INOP(inode);
        struct nw_file_info     *finfo  = NCP_FINFO(inode);
        struct nw_file_info     *finfo  = NCP_FINFO(inode);
 
 
        /*
        /*
         * This operation may block, so we lock before checking the count.
         * This operation may block, so we lock before checking the count.
         */
         */
        lock_super(sb);
        lock_super(sb);
 
 
        if (inode->i_count > 1)
        if (inode->i_count > 1)
        {
        {
                printk("ncp_put_inode: inode in use device %s, inode %ld, count=%ld\n",
                printk("ncp_put_inode: inode in use device %s, inode %ld, count=%ld\n",
                       kdevname(inode->i_dev), inode->i_ino, inode->i_count);
                       kdevname(inode->i_dev), inode->i_ino, inode->i_count);
                goto unlock;
                goto unlock;
        }
        }
 
 
        DDPRINTK("ncp_put_inode: put %s\n",
        DDPRINTK("ncp_put_inode: put %s\n",
                 finfo->i.entryName);
                 finfo->i.entryName);
        /*
        /*
         * This operation should never block.
         * This operation should never block.
         */
         */
        if (S_ISDIR(inode->i_mode))
        if (S_ISDIR(inode->i_mode))
        {
        {
                DDPRINTK("ncp_put_inode: put directory %ld\n",
                DDPRINTK("ncp_put_inode: put directory %ld\n",
                         inode->i_ino);
                         inode->i_ino);
                ncp_invalid_dir_cache(inode);
                ncp_invalid_dir_cache(inode);
        }
        }
 
 
        clear_inode(inode);
        clear_inode(inode);
 
 
        /*
        /*
         * After clearing the inode i_count will be 0 in 2.0.xx kernels.
         * After clearing the inode i_count will be 0 in 2.0.xx kernels.
         * To keep the inode from being reused as free if we block while
         * To keep the inode from being reused as free if we block while
         * closing the file, increment i_count temporarily.
         * closing the file, increment i_count temporarily.
         */
         */
        inode->i_count++;
        inode->i_count++;
 
 
        if (finfo->opened != 0)
        if (finfo->opened != 0)
        {
        {
                if (ncp_close_file(server, finfo->file_handle) != 0)
                if (ncp_close_file(server, finfo->file_handle) != 0)
                {
                {
                        /* We can't do anything but complain. */
                        /* We can't do anything but complain. */
                        printk("ncp_put_inode: could not close %s\n",
                        printk("ncp_put_inode: could not close %s\n",
                                finfo->i.entryName);
                                finfo->i.entryName);
                }
                }
        }
        }
 
 
        ncp_free_inode_info(iinfo);
        ncp_free_inode_info(iinfo);
        inode->i_count--;
        inode->i_count--;
 
 
unlock:
unlock:
        unlock_super(sb);
        unlock_super(sb);
}
}
 
 
struct super_block *
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
{
        struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
        struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
        struct ncp_server *server;
        struct ncp_server *server;
        struct file *ncp_filp;
        struct file *ncp_filp;
        struct file *wdog_filp;
        struct file *wdog_filp;
        struct file *msg_filp;
        struct file *msg_filp;
        kdev_t dev = sb->s_dev;
        kdev_t dev = sb->s_dev;
        int error;
        int error;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
#ifdef CONFIG_NCPFS_PACKET_SIGNING
        int options;
        int options;
#endif
#endif
 
 
        if (data == NULL)
        if (data == NULL)
        {
        {
                printk("ncp_read_super: missing data argument\n");
                printk("ncp_read_super: missing data argument\n");
                sb->s_dev = 0;
                sb->s_dev = 0;
                return NULL;
                return NULL;
        }
        }
 
 
        if (data->version != NCP_MOUNT_VERSION)
        if (data->version != NCP_MOUNT_VERSION)
        {
        {
                printk("ncp warning: mount version %s than kernel\n",
                printk("ncp warning: mount version %s than kernel\n",
                       (data->version < NCP_MOUNT_VERSION) ?
                       (data->version < NCP_MOUNT_VERSION) ?
                       "older" : "newer");
                       "older" : "newer");
                sb->s_dev = 0;
                sb->s_dev = 0;
                return NULL;
                return NULL;
        }
        }
 
 
        if (   (data->ncp_fd >= NR_OPEN)
        if (   (data->ncp_fd >= NR_OPEN)
            || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
            || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
            || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
            || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
        {
        {
                printk("ncp_read_super: invalid ncp socket\n");
                printk("ncp_read_super: invalid ncp socket\n");
                sb->s_dev = 0;
                sb->s_dev = 0;
                return NULL;
                return NULL;
        }
        }
 
 
        if (   (data->wdog_fd >= NR_OPEN)
        if (   (data->wdog_fd >= NR_OPEN)
            || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
            || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
            || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
            || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
        {
        {
                printk("ncp_read_super: invalid wdog socket\n");
                printk("ncp_read_super: invalid wdog socket\n");
                sb->s_dev = 0;
                sb->s_dev = 0;
                return NULL;
                return NULL;
        }
        }
 
 
        if (   (data->message_fd >= NR_OPEN)
        if (   (data->message_fd >= NR_OPEN)
            || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
            || ((msg_filp = current->files->fd[data->message_fd]) == NULL)
            || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
            || (!S_ISSOCK(msg_filp->f_inode->i_mode)))
        {
        {
                printk("ncp_read_super: invalid wdog socket\n");
                printk("ncp_read_super: invalid wdog socket\n");
                sb->s_dev = 0;
                sb->s_dev = 0;
                return NULL;
                return NULL;
        }
        }
 
 
        /* We must malloc our own super-block info */
        /* We must malloc our own super-block info */
        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
        server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
                                                   GFP_KERNEL);
                                                   GFP_KERNEL);
 
 
        if (server == NULL)
        if (server == NULL)
        {
        {
                printk("ncp_read_super: could not alloc ncp_server\n");
                printk("ncp_read_super: could not alloc ncp_server\n");
                return NULL;
                return NULL;
        }
        }
 
 
        ncp_filp->f_count += 1;
        ncp_filp->f_count += 1;
        wdog_filp->f_count += 1;
        wdog_filp->f_count += 1;
        msg_filp->f_count += 1;
        msg_filp->f_count += 1;
 
 
        lock_super(sb);
        lock_super(sb);
 
 
        NCP_SBP(sb) = server;
        NCP_SBP(sb) = server;
 
 
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
        sb->s_blocksize_bits = 10;
        sb->s_blocksize_bits = 10;
        sb->s_magic = NCP_SUPER_MAGIC;
        sb->s_magic = NCP_SUPER_MAGIC;
        sb->s_dev = dev;
        sb->s_dev = dev;
        sb->s_op = &ncp_sops;
        sb->s_op = &ncp_sops;
 
 
        server->ncp_filp    = ncp_filp;
        server->ncp_filp    = ncp_filp;
        server->wdog_filp   = wdog_filp;
        server->wdog_filp   = wdog_filp;
        server->msg_filp    = msg_filp;
        server->msg_filp    = msg_filp;
        server->lock        = 0;
        server->lock        = 0;
        server->wait        = NULL;
        server->wait        = NULL;
        server->packet      = NULL;
        server->packet      = NULL;
        server->buffer_size = 0;
        server->buffer_size = 0;
        server->conn_status = 0;
        server->conn_status = 0;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
#ifdef CONFIG_NCPFS_PACKET_SIGNING
        server->sign_wanted = 0;
        server->sign_wanted = 0;
        server->sign_active = 0;
        server->sign_active = 0;
#endif
#endif
        server->m = *data;
        server->m = *data;
        server->m.file_mode = (server->m.file_mode &
        server->m.file_mode = (server->m.file_mode &
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
        server->m.dir_mode  = (server->m.dir_mode &
        server->m.dir_mode  = (server->m.dir_mode &
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
                               (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
 
 
        /* protect against invalid mount points */
        /* protect against invalid mount points */
        server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';
        server->m.mount_point[sizeof(server->m.mount_point)-1] = '\0';
 
 
        server->packet_size = NCP_PACKET_SIZE;
        server->packet_size = NCP_PACKET_SIZE;
        server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
        server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
 
 
        if (server->packet == NULL)
        if (server->packet == NULL)
        {
        {
                printk("ncpfs: could not alloc packet\n");
                printk("ncpfs: could not alloc packet\n");
                error = -ENOMEM;
                error = -ENOMEM;
                unlock_super(sb);
                unlock_super(sb);
                goto fail;
                goto fail;
        }
        }
 
 
        /*
        /*
         * Make the connection to the server
         * Make the connection to the server
         */
         */
 
 
        if (ncp_catch_watchdog(server) != 0)
        if (ncp_catch_watchdog(server) != 0)
        {
        {
                printk("ncp_read_super: Could not catch watchdog\n");
                printk("ncp_read_super: Could not catch watchdog\n");
                error = -EINVAL;
                error = -EINVAL;
                unlock_super(sb);
                unlock_super(sb);
                goto fail;
                goto fail;
        }
        }
 
 
        if (ncp_catch_message(server) != 0)
        if (ncp_catch_message(server) != 0)
        {
        {
                printk("ncp_read_super: Could not catch messages\n");
                printk("ncp_read_super: Could not catch messages\n");
                ncp_dont_catch_watchdog(server);
                ncp_dont_catch_watchdog(server);
                error = -EINVAL;
                error = -EINVAL;
                unlock_super(sb);
                unlock_super(sb);
                goto fail;
                goto fail;
        }
        }
 
 
        ncp_lock_server(server);
        ncp_lock_server(server);
        error = ncp_connect(server);
        error = ncp_connect(server);
        ncp_unlock_server(server);
        ncp_unlock_server(server);
        unlock_super(sb);
        unlock_super(sb);
 
 
        if (error < 0)
        if (error < 0)
        {
        {
                sb->s_dev = 0;
                sb->s_dev = 0;
                printk("ncp_read_super: Failed connection, bailing out "
                printk("ncp_read_super: Failed connection, bailing out "
                       "(error = %d).\n", -error);
                       "(error = %d).\n", -error);
                ncp_kfree_s(server->packet, server->packet_size);
                ncp_kfree_s(server->packet, server->packet_size);
                ncp_dont_catch_watchdog(server);
                ncp_dont_catch_watchdog(server);
                goto fail;
                goto fail;
        }
        }
 
 
        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
 
 
        ncp_init_root(server);
        ncp_init_root(server);
 
 
        if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
        if (!(sb->s_mounted = iget(sb, ncp_info_ino(server, &(server->root)))))
        {
        {
                sb->s_dev = 0;
                sb->s_dev = 0;
                printk("ncp_read_super: get root inode failed\n");
                printk("ncp_read_super: get root inode failed\n");
                goto disconnect;
                goto disconnect;
        }
        }
 
 
#ifdef CONFIG_NCPFS_PACKET_SIGNING
#ifdef CONFIG_NCPFS_PACKET_SIGNING
        if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
        if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
        {
        {
                if (options != NCP_DEFAULT_OPTIONS)
                if (options != NCP_DEFAULT_OPTIONS)
                {
                {
                        if (ncp_negotiate_size_and_options(server,
                        if (ncp_negotiate_size_and_options(server,
                                NCP_DEFAULT_BUFSIZE,
                                NCP_DEFAULT_BUFSIZE,
                                options & 2,
                                options & 2,
                                &(server->buffer_size), &options) != 0)
                                &(server->buffer_size), &options) != 0)
 
 
                        {
                        {
                                sb->s_dev = 0;
                                sb->s_dev = 0;
                                printk("ncp_read_super: "
                                printk("ncp_read_super: "
                                        "could not set options\n");
                                        "could not set options\n");
                                goto disconnect;
                                goto disconnect;
                        }
                        }
                }
                }
                if (options & 2)
                if (options & 2)
                        server->sign_wanted = 1;
                        server->sign_wanted = 1;
        }
        }
        else
        else
#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
        if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
        if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
                                     &(server->buffer_size)) != 0)
                                     &(server->buffer_size)) != 0)
        {
        {
                sb->s_dev = 0;
                sb->s_dev = 0;
                printk("ncp_read_super: could not get bufsize\n");
                printk("ncp_read_super: could not get bufsize\n");
                goto disconnect;
                goto disconnect;
        }
        }
 
 
        DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
        DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
 
 
        MOD_INC_USE_COUNT;
        MOD_INC_USE_COUNT;
        return sb;
        return sb;
 
 
 disconnect:
 disconnect:
        ncp_lock_server(server);
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
        ncp_unlock_server(server);
        ncp_kfree_s(server->packet, server->packet_size);
        ncp_kfree_s(server->packet, server->packet_size);
        ncp_dont_catch_watchdog(server);
        ncp_dont_catch_watchdog(server);
 fail:
 fail:
        ncp_filp->f_count -= 1;
        ncp_filp->f_count -= 1;
        wdog_filp->f_count -= 1;
        wdog_filp->f_count -= 1;
        msg_filp->f_count -= 1;
        msg_filp->f_count -= 1;
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        return NULL;
        return NULL;
}
}
 
 
static void
static void
ncp_put_super(struct super_block *sb)
ncp_put_super(struct super_block *sb)
{
{
        struct ncp_server *server = NCP_SBP(sb);
        struct ncp_server *server = NCP_SBP(sb);
 
 
        lock_super(sb);
        lock_super(sb);
 
 
        ncp_lock_server(server);
        ncp_lock_server(server);
        ncp_disconnect(server);
        ncp_disconnect(server);
        ncp_unlock_server(server);
        ncp_unlock_server(server);
 
 
        close_fp(server->ncp_filp);
        close_fp(server->ncp_filp);
 
 
        ncp_dont_catch_watchdog(server);
        ncp_dont_catch_watchdog(server);
        close_fp(server->wdog_filp);
        close_fp(server->wdog_filp);
        close_fp(server->msg_filp);
        close_fp(server->msg_filp);
 
 
        ncp_free_all_inodes(server);
        ncp_free_all_inodes(server);
 
 
        ncp_kfree_s(server->packet, server->packet_size);
        ncp_kfree_s(server->packet, server->packet_size);
 
 
        sb->s_dev = 0;
        sb->s_dev = 0;
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
        NCP_SBP(sb) = NULL;
        NCP_SBP(sb) = NULL;
 
 
        unlock_super(sb);
        unlock_super(sb);
 
 
        MOD_DEC_USE_COUNT;
        MOD_DEC_USE_COUNT;
}
}
 
 
/* This routine is called from an interrupt in ncp_msg_data_ready. So
/* This routine is called from an interrupt in ncp_msg_data_ready. So
 * we have to be careful NOT to sleep here! */
 * we have to be careful NOT to sleep here! */
void
void
ncp_trigger_message(struct ncp_server *server)
ncp_trigger_message(struct ncp_server *server)
{
{
#ifdef CONFIG_KERNELD
#ifdef CONFIG_KERNELD
        char command[ sizeof(server->m.mount_point)
        char command[ sizeof(server->m.mount_point)
                     + sizeof(NCP_MSG_COMMAND) + 2];
                     + sizeof(NCP_MSG_COMMAND) + 2];
#endif
#endif
 
 
        if (server == NULL)
        if (server == NULL)
        {
        {
                printk("ncp_trigger_message: invalid server!\n");
                printk("ncp_trigger_message: invalid server!\n");
                return;
                return;
        }
        }
 
 
        DPRINTK("ncp_trigger_message: on %s\n",
        DPRINTK("ncp_trigger_message: on %s\n",
                server->m.mount_point);
                server->m.mount_point);
 
 
#ifdef CONFIG_KERNELD
#ifdef CONFIG_KERNELD
        strcpy(command, NCP_MSG_COMMAND);
        strcpy(command, NCP_MSG_COMMAND);
        strcat(command, " ");
        strcat(command, " ");
        strcat(command, server->m.mount_point);
        strcat(command, server->m.mount_point);
        DPRINTK("ksystem: %s\n", command);
        DPRINTK("ksystem: %s\n", command);
        ksystem(command, KERNELD_NOWAIT);
        ksystem(command, KERNELD_NOWAIT);
#endif
#endif
}
}
 
 
static void
static void
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
{
        struct statfs tmp;
        struct statfs tmp;
 
 
        /* We cannot say how much disk space is left on a mounted
        /* We cannot say how much disk space is left on a mounted
           NetWare Server, because free space is distributed over
           NetWare Server, because free space is distributed over
           volumes, and the current user might have disk quotas. So
           volumes, and the current user might have disk quotas. So
           free space is not that simple to determine. Our decision
           free space is not that simple to determine. Our decision
           here is to err conservatively. */
           here is to err conservatively. */
 
 
        tmp.f_type = NCP_SUPER_MAGIC;
        tmp.f_type = NCP_SUPER_MAGIC;
        tmp.f_bsize = 512;
        tmp.f_bsize = 512;
        tmp.f_blocks = 0;
        tmp.f_blocks = 0;
        tmp.f_bfree = 0;
        tmp.f_bfree = 0;
        tmp.f_bavail = 0;
        tmp.f_bavail = 0;
        tmp.f_files = -1;
        tmp.f_files = -1;
        tmp.f_ffree = -1;
        tmp.f_ffree = -1;
        tmp.f_namelen = 12;
        tmp.f_namelen = 12;
        memcpy_tofs(buf, &tmp, bufsiz);
        memcpy_tofs(buf, &tmp, bufsiz);
}
}
 
 
int
int
ncp_notify_change(struct inode *inode, struct iattr *attr)
ncp_notify_change(struct inode *inode, struct iattr *attr)
{
{
        int result = 0;
        int result = 0;
        int info_mask;
        int info_mask;
        struct nw_modify_dos_info info;
        struct nw_modify_dos_info info;
 
 
        if (!ncp_conn_valid(NCP_SERVER(inode)))
        if (!ncp_conn_valid(NCP_SERVER(inode)))
        {
        {
                return -EIO;
                return -EIO;
        }
        }
 
 
        if ((result = inode_change_ok(inode, attr)) < 0)
        if ((result = inode_change_ok(inode, attr)) < 0)
                return result;
                return result;
 
 
        if (((attr->ia_valid & ATTR_UID) &&
        if (((attr->ia_valid & ATTR_UID) &&
             (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
             (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
                return -EPERM;
                return -EPERM;
 
 
        if (((attr->ia_valid & ATTR_GID) &&
        if (((attr->ia_valid & ATTR_GID) &&
             (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
             (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
                return -EPERM;
                return -EPERM;
 
 
        if (((attr->ia_valid & ATTR_MODE) &&
        if (((attr->ia_valid & ATTR_MODE) &&
             (attr->ia_mode &
             (attr->ia_mode &
              ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
              ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
                return -EPERM;
                return -EPERM;
 
 
        info_mask = 0;
        info_mask = 0;
        memset(&info, 0, sizeof(info));
        memset(&info, 0, sizeof(info));
 
 
#if 1 
#if 1 
        if ((attr->ia_valid & ATTR_MODE) != 0)
        if ((attr->ia_valid & ATTR_MODE) != 0)
        {
        {
                if (NCP_ISTRUCT(inode)->attributes & aDIR)
                if (NCP_ISTRUCT(inode)->attributes & aDIR)
                {
                {
                        return -EPERM;
                        return -EPERM;
                }
                }
                else
                else
                {
                {
                        umode_t newmode;
                        umode_t newmode;
 
 
                        info_mask |= DM_ATTRIBUTES;
                        info_mask |= DM_ATTRIBUTES;
                        newmode=attr->ia_mode;
                        newmode=attr->ia_mode;
                        newmode &= NCP_SERVER(inode)->m.file_mode;
                        newmode &= NCP_SERVER(inode)->m.file_mode;
 
 
                        if (newmode & 0222) /* any write bit set */
                        if (newmode & 0222) /* any write bit set */
                        {
                        {
                                info.attributes &= ~0x60001;
                                info.attributes &= ~0x60001;
                        }
                        }
                        else
                        else
                        {
                        {
                                info.attributes |= 0x60001;
                                info.attributes |= 0x60001;
                        }
                        }
                }
                }
        }
        }
#endif
#endif
 
 
        if ((attr->ia_valid & ATTR_CTIME) != 0)
        if ((attr->ia_valid & ATTR_CTIME) != 0)
        {
        {
                info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
                info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
                ncp_date_unix2dos(attr->ia_ctime,
                ncp_date_unix2dos(attr->ia_ctime,
                                  &(info.creationTime), &(info.creationDate));
                                  &(info.creationTime), &(info.creationDate));
        }
        }
 
 
        if ((attr->ia_valid & ATTR_MTIME) != 0)
        if ((attr->ia_valid & ATTR_MTIME) != 0)
        {
        {
                info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
                info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
                ncp_date_unix2dos(attr->ia_mtime,
                ncp_date_unix2dos(attr->ia_mtime,
                                  &(info.modifyTime), &(info.modifyDate));
                                  &(info.modifyTime), &(info.modifyDate));
        }
        }
 
 
        if ((attr->ia_valid & ATTR_ATIME) != 0)
        if ((attr->ia_valid & ATTR_ATIME) != 0)
        {
        {
                __u16 dummy;
                __u16 dummy;
                info_mask |= (DM_LAST_ACCESS_DATE);
                info_mask |= (DM_LAST_ACCESS_DATE);
                ncp_date_unix2dos(attr->ia_ctime,
                ncp_date_unix2dos(attr->ia_ctime,
                                  &(dummy), &(info.lastAccessDate));
                                  &(dummy), &(info.lastAccessDate));
        }
        }
 
 
        if (info_mask != 0)
        if (info_mask != 0)
        {
        {
                if ((result =
                if ((result =
                     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
                     ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
                                                        NCP_ISTRUCT(inode),
                                                        NCP_ISTRUCT(inode),
                                                        info_mask,
                                                        info_mask,
                                                        &info)) != 0)
                                                        &info)) != 0)
                {
                {
                        result = -EACCES;
                        result = -EACCES;
 
 
                        if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
                        if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
                        {
                        {
                                /* NetWare seems not to allow this. I
                                /* NetWare seems not to allow this. I
                                   do not know why. So, just tell the
                                   do not know why. So, just tell the
                                   user everything went fine. This is
                                   user everything went fine. This is
                                   a terrible hack, but I do not know
                                   a terrible hack, but I do not know
                                   how to do this correctly. */
                                   how to do this correctly. */
                                result = 0;
                                result = 0;
                        }
                        }
                }
                }
        }
        }
 
 
        if ((attr->ia_valid & ATTR_SIZE) != 0)
        if ((attr->ia_valid & ATTR_SIZE) != 0)
        {
        {
                int written;
                int written;
 
 
                DPRINTK("ncpfs: trying to change size of %s to %ld\n",
                DPRINTK("ncpfs: trying to change size of %s to %ld\n",
                        NCP_ISTRUCT(inode)->entryName, attr->ia_size);
                        NCP_ISTRUCT(inode)->entryName, attr->ia_size);
 
 
                if ((result = ncp_make_open(inode, O_RDWR)) < 0)
                if ((result = ncp_make_open(inode, O_RDWR)) < 0)
                {
                {
                        return -EACCES;
                        return -EACCES;
                }
                }
 
 
                ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
                ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
                          attr->ia_size, 0, "", &written);
                          attr->ia_size, 0, "", &written);
 
 
                /* According to ndir, the changes only take effect after
                /* According to ndir, the changes only take effect after
                   closing the file */
                   closing the file */
                ncp_close_file(NCP_SERVER(inode),
                ncp_close_file(NCP_SERVER(inode),
                               NCP_FINFO(inode)->file_handle);
                               NCP_FINFO(inode)->file_handle);
                NCP_FINFO(inode)->opened = 0;
                NCP_FINFO(inode)->opened = 0;
 
 
                result = 0;
                result = 0;
        }
        }
 
 
        ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
        ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
 
 
        return result;
        return result;
}
}
 
 
#ifdef DEBUG_NCP_MALLOC
#ifdef DEBUG_NCP_MALLOC
int ncp_malloced;
int ncp_malloced;
int ncp_current_malloced;
int ncp_current_malloced;
#endif
#endif
 
 
static struct file_system_type ncp_fs_type = {
static struct file_system_type ncp_fs_type = {
        ncp_read_super, "ncpfs", 0, NULL
        ncp_read_super, "ncpfs", 0, NULL
        };
        };
 
 
int init_ncp_fs(void)
int init_ncp_fs(void)
{
{
        return register_filesystem(&ncp_fs_type);
        return register_filesystem(&ncp_fs_type);
}
}
 
 
#ifdef MODULE
#ifdef MODULE
int
int
init_module( void)
init_module( void)
{
{
        int status;
        int status;
 
 
        DPRINTK("ncpfs: init_module called\n");
        DPRINTK("ncpfs: init_module called\n");
 
 
#ifdef DEBUG_NCP_MALLOC
#ifdef DEBUG_NCP_MALLOC
        ncp_malloced = 0;
        ncp_malloced = 0;
        ncp_current_malloced = 0;
        ncp_current_malloced = 0;
#endif
#endif
        ncp_init_dir_cache();
        ncp_init_dir_cache();
 
 
        if ((status = init_ncp_fs()) == 0)
        if ((status = init_ncp_fs()) == 0)
                register_symtab(0);
                register_symtab(0);
        return status;
        return status;
}
}
 
 
void
void
cleanup_module(void)
cleanup_module(void)
{
{
        DPRINTK("ncpfs: cleanup_module called\n");
        DPRINTK("ncpfs: cleanup_module called\n");
        ncp_free_dir_cache();
        ncp_free_dir_cache();
        unregister_filesystem(&ncp_fs_type);
        unregister_filesystem(&ncp_fs_type);
#ifdef DEBUG_NCP_MALLOC
#ifdef DEBUG_NCP_MALLOC
        printk("ncp_malloced: %d\n", ncp_malloced);
        printk("ncp_malloced: %d\n", ncp_malloced);
        printk("ncp_current_malloced: %d\n", ncp_current_malloced);
        printk("ncp_current_malloced: %d\n", ncp_current_malloced);
#endif
#endif
}
}
 
 
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.