linux/fs/ncpfs/inode.c
<<
>>
Prefs
   1/*
   2 *  inode.c
   3 *
   4 *  Copyright (C) 1995, 1996 by Volker Lendecke
   5 *  Modified for big endian by J.F. Chadima and David S. Miller
   6 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
   7 *  Modified 1998 Wolfram Pienkoss for NLS
   8 *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
   9 *
  10 */
  11
  12#include <linux/module.h>
  13
  14#include <asm/system.h>
  15#include <asm/uaccess.h>
  16#include <asm/byteorder.h>
  17
  18#include <linux/time.h>
  19#include <linux/kernel.h>
  20#include <linux/mm.h>
  21#include <linux/string.h>
  22#include <linux/stat.h>
  23#include <linux/errno.h>
  24#include <linux/file.h>
  25#include <linux/fcntl.h>
  26#include <linux/slab.h>
  27#include <linux/vmalloc.h>
  28#include <linux/init.h>
  29#include <linux/vfs.h>
  30#include <linux/mount.h>
  31#include <linux/seq_file.h>
  32#include <linux/namei.h>
  33
  34#include <net/sock.h>
  35
  36#include "ncp_fs.h"
  37#include "getopt.h"
  38
  39#define NCP_DEFAULT_FILE_MODE 0600
  40#define NCP_DEFAULT_DIR_MODE 0700
  41#define NCP_DEFAULT_TIME_OUT 10
  42#define NCP_DEFAULT_RETRY_COUNT 20
  43
  44static void ncp_evict_inode(struct inode *);
  45static void ncp_put_super(struct super_block *);
  46static int  ncp_statfs(struct dentry *, struct kstatfs *);
  47static int  ncp_show_options(struct seq_file *, struct vfsmount *);
  48
  49static struct kmem_cache * ncp_inode_cachep;
  50
  51static struct inode *ncp_alloc_inode(struct super_block *sb)
  52{
  53        struct ncp_inode_info *ei;
  54        ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
  55        if (!ei)
  56                return NULL;
  57        return &ei->vfs_inode;
  58}
  59
  60static void ncp_i_callback(struct rcu_head *head)
  61{
  62        struct inode *inode = container_of(head, struct inode, i_rcu);
  63        INIT_LIST_HEAD(&inode->i_dentry);
  64        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
  65}
  66
  67static void ncp_destroy_inode(struct inode *inode)
  68{
  69        call_rcu(&inode->i_rcu, ncp_i_callback);
  70}
  71
  72static void init_once(void *foo)
  73{
  74        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
  75
  76        mutex_init(&ei->open_mutex);
  77        inode_init_once(&ei->vfs_inode);
  78}
  79
  80static int init_inodecache(void)
  81{
  82        ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
  83                                             sizeof(struct ncp_inode_info),
  84                                             0, (SLAB_RECLAIM_ACCOUNT|
  85                                                SLAB_MEM_SPREAD),
  86                                             init_once);
  87        if (ncp_inode_cachep == NULL)
  88                return -ENOMEM;
  89        return 0;
  90}
  91
  92static void destroy_inodecache(void)
  93{
  94        kmem_cache_destroy(ncp_inode_cachep);
  95}
  96
  97static int ncp_remount(struct super_block *sb, int *flags, char* data)
  98{
  99        *flags |= MS_NODIRATIME;
 100        return 0;
 101}
 102
 103static const struct super_operations ncp_sops =
 104{
 105        .alloc_inode    = ncp_alloc_inode,
 106        .destroy_inode  = ncp_destroy_inode,
 107        .drop_inode     = generic_delete_inode,
 108        .evict_inode    = ncp_evict_inode,
 109        .put_super      = ncp_put_super,
 110        .statfs         = ncp_statfs,
 111        .remount_fs     = ncp_remount,
 112        .show_options   = ncp_show_options,
 113};
 114
 115/*
 116 * Fill in the ncpfs-specific information in the inode.
 117 */
 118static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
 119{
 120        NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
 121        NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
 122        NCP_FINFO(inode)->volNumber = nwinfo->volume;
 123}
 124
 125void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
 126{
 127        ncp_update_dirent(inode, nwinfo);
 128        NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
 129        NCP_FINFO(inode)->access = nwinfo->access;
 130        memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
 131                        sizeof(nwinfo->file_handle));
 132        DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
 133                nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
 134                NCP_FINFO(inode)->dirEntNum);
 135}
 136
 137static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
 138{
 139        /* NFS namespace mode overrides others if it's set. */
 140        DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
 141                nwi->entryName, nwi->nfs.mode);
 142        if (nwi->nfs.mode) {
 143                /* XXX Security? */
 144                inode->i_mode = nwi->nfs.mode;
 145        }
 146
 147        inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 148
 149        inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
 150        inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
 151        inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
 152        inode->i_atime.tv_nsec = 0;
 153        inode->i_mtime.tv_nsec = 0;
 154        inode->i_ctime.tv_nsec = 0;
 155}
 156
 157static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
 158{
 159        struct nw_info_struct *nwi = &nwinfo->i;
 160        struct ncp_server *server = NCP_SERVER(inode);
 161
 162        if (nwi->attributes & aDIR) {
 163                inode->i_mode = server->m.dir_mode;
 164                /* for directories dataStreamSize seems to be some
 165                   Object ID ??? */
 166                i_size_write(inode, NCP_BLOCK_SIZE);
 167        } else {
 168                u32 size;
 169
 170                inode->i_mode = server->m.file_mode;
 171                size = le32_to_cpu(nwi->dataStreamSize);
 172                i_size_write(inode, size);
 173#ifdef CONFIG_NCPFS_EXTRAS
 174                if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
 175                 && (nwi->attributes & aSHARED)) {
 176                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
 177                                case aHIDDEN:
 178                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
 179                                                if (/* (size >= NCP_MIN_SYMLINK_SIZE)
 180                                                 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
 181                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
 182                                                        NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
 183                                                        break;
 184                                                }
 185                                        }
 186                                        /* FALLTHROUGH */
 187                                case 0:
 188                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
 189                                                inode->i_mode |= S_IRUGO;
 190                                        break;
 191                                case aSYSTEM:
 192                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
 193                                                inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
 194                                        break;
 195                                /* case aSYSTEM|aHIDDEN: */
 196                                default:
 197                                        /* reserved combination */
 198                                        break;
 199                        }
 200                }
 201#endif
 202        }
 203        if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
 204}
 205
 206void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
 207{
 208        NCP_FINFO(inode)->flags = 0;
 209        if (!atomic_read(&NCP_FINFO(inode)->opened)) {
 210                NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
 211                ncp_update_attrs(inode, nwinfo);
 212        }
 213
 214        ncp_update_dates(inode, &nwinfo->i);
 215        ncp_update_dirent(inode, nwinfo);
 216}
 217
 218/*
 219 * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
 220 */
 221static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 222{
 223        struct ncp_server *server = NCP_SERVER(inode);
 224
 225        NCP_FINFO(inode)->flags = 0;
 226        
 227        ncp_update_attrs(inode, nwinfo);
 228
 229        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 230
 231        set_nlink(inode, 1);
 232        inode->i_uid = server->m.uid;
 233        inode->i_gid = server->m.gid;
 234
 235        ncp_update_dates(inode, &nwinfo->i);
 236        ncp_update_inode(inode, nwinfo);
 237}
 238
 239#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 240static const struct inode_operations ncp_symlink_inode_operations = {
 241        .readlink       = generic_readlink,
 242        .follow_link    = page_follow_link_light,
 243        .put_link       = page_put_link,
 244        .setattr        = ncp_notify_change,
 245};
 246#endif
 247
 248/*
 249 * Get a new inode.
 250 */
 251struct inode * 
 252ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 253{
 254        struct inode *inode;
 255
 256        if (info == NULL) {
 257                printk(KERN_ERR "ncp_iget: info is NULL\n");
 258                return NULL;
 259        }
 260
 261        inode = new_inode(sb);
 262        if (inode) {
 263                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 264
 265                inode->i_mapping->backing_dev_info = sb->s_bdi;
 266                inode->i_ino = info->ino;
 267                ncp_set_attr(inode, info);
 268                if (S_ISREG(inode->i_mode)) {
 269                        inode->i_op = &ncp_file_inode_operations;
 270                        inode->i_fop = &ncp_file_operations;
 271                } else if (S_ISDIR(inode->i_mode)) {
 272                        inode->i_op = &ncp_dir_inode_operations;
 273                        inode->i_fop = &ncp_dir_operations;
 274#ifdef CONFIG_NCPFS_NFS_NS
 275                } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
 276                        init_special_inode(inode, inode->i_mode,
 277                                new_decode_dev(info->i.nfs.rdev));
 278#endif
 279#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 280                } else if (S_ISLNK(inode->i_mode)) {
 281                        inode->i_op = &ncp_symlink_inode_operations;
 282                        inode->i_data.a_ops = &ncp_symlink_aops;
 283#endif
 284                } else {
 285                        make_bad_inode(inode);
 286                }
 287                insert_inode_hash(inode);
 288        } else
 289                printk(KERN_ERR "ncp_iget: iget failed!\n");
 290        return inode;
 291}
 292
 293static void
 294ncp_evict_inode(struct inode *inode)
 295{
 296        truncate_inode_pages(&inode->i_data, 0);
 297        end_writeback(inode);
 298
 299        if (S_ISDIR(inode->i_mode)) {
 300                DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
 301        }
 302
 303        if (ncp_make_closed(inode) != 0) {
 304                /* We can't do anything but complain. */
 305                printk(KERN_ERR "ncp_evict_inode: could not close\n");
 306        }
 307}
 308
 309static void ncp_stop_tasks(struct ncp_server *server) {
 310        struct sock* sk = server->ncp_sock->sk;
 311
 312        lock_sock(sk);
 313        sk->sk_error_report = server->error_report;
 314        sk->sk_data_ready   = server->data_ready;
 315        sk->sk_write_space  = server->write_space;
 316        release_sock(sk);
 317        del_timer_sync(&server->timeout_tm);
 318
 319        flush_work_sync(&server->rcv.tq);
 320        if (sk->sk_socket->type == SOCK_STREAM)
 321                flush_work_sync(&server->tx.tq);
 322        else
 323                flush_work_sync(&server->timeout_tq);
 324}
 325
 326static int  ncp_show_options(struct seq_file *seq, struct vfsmount *mnt)
 327{
 328        struct ncp_server *server = NCP_SBP(mnt->mnt_sb);
 329        unsigned int tmp;
 330
 331        if (server->m.uid != 0)
 332                seq_printf(seq, ",uid=%u", server->m.uid);
 333        if (server->m.gid != 0)
 334                seq_printf(seq, ",gid=%u", server->m.gid);
 335        if (server->m.mounted_uid != 0)
 336                seq_printf(seq, ",owner=%u", server->m.mounted_uid);
 337        tmp = server->m.file_mode & S_IALLUGO;
 338        if (tmp != NCP_DEFAULT_FILE_MODE)
 339                seq_printf(seq, ",mode=0%o", tmp);
 340        tmp = server->m.dir_mode & S_IALLUGO;
 341        if (tmp != NCP_DEFAULT_DIR_MODE)
 342                seq_printf(seq, ",dirmode=0%o", tmp);
 343        if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
 344                tmp = server->m.time_out * 100 / HZ;
 345                seq_printf(seq, ",timeout=%u", tmp);
 346        }
 347        if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
 348                seq_printf(seq, ",retry=%u", server->m.retry_count);
 349        if (server->m.flags != 0)
 350                seq_printf(seq, ",flags=%lu", server->m.flags);
 351        if (server->m.wdog_pid != NULL)
 352                seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
 353
 354        return 0;
 355}
 356
 357static const struct ncp_option ncp_opts[] = {
 358        { "uid",        OPT_INT,        'u' },
 359        { "gid",        OPT_INT,        'g' },
 360        { "owner",      OPT_INT,        'o' },
 361        { "mode",       OPT_INT,        'm' },
 362        { "dirmode",    OPT_INT,        'd' },
 363        { "timeout",    OPT_INT,        't' },
 364        { "retry",      OPT_INT,        'r' },
 365        { "flags",      OPT_INT,        'f' },
 366        { "wdogpid",    OPT_INT,        'w' },
 367        { "ncpfd",      OPT_INT,        'n' },
 368        { "infofd",     OPT_INT,        'i' },  /* v5 */
 369        { "version",    OPT_INT,        'v' },
 370        { NULL,         0,              0 } };
 371
 372static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
 373        int optval;
 374        char *optarg;
 375        unsigned long optint;
 376        int version = 0;
 377        int ret;
 378
 379        data->flags = 0;
 380        data->int_flags = 0;
 381        data->mounted_uid = 0;
 382        data->wdog_pid = NULL;
 383        data->ncp_fd = ~0;
 384        data->time_out = NCP_DEFAULT_TIME_OUT;
 385        data->retry_count = NCP_DEFAULT_RETRY_COUNT;
 386        data->uid = 0;
 387        data->gid = 0;
 388        data->file_mode = NCP_DEFAULT_FILE_MODE;
 389        data->dir_mode = NCP_DEFAULT_DIR_MODE;
 390        data->info_fd = -1;
 391        data->mounted_vol[0] = 0;
 392        
 393        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
 394                ret = optval;
 395                if (ret < 0)
 396                        goto err;
 397                switch (optval) {
 398                        case 'u':
 399                                data->uid = optint;
 400                                break;
 401                        case 'g':
 402                                data->gid = optint;
 403                                break;
 404                        case 'o':
 405                                data->mounted_uid = optint;
 406                                break;
 407                        case 'm':
 408                                data->file_mode = optint;
 409                                break;
 410                        case 'd':
 411                                data->dir_mode = optint;
 412                                break;
 413                        case 't':
 414                                data->time_out = optint;
 415                                break;
 416                        case 'r':
 417                                data->retry_count = optint;
 418                                break;
 419                        case 'f':
 420                                data->flags = optint;
 421                                break;
 422                        case 'w':
 423                                data->wdog_pid = find_get_pid(optint);
 424                                break;
 425                        case 'n':
 426                                data->ncp_fd = optint;
 427                                break;
 428                        case 'i':
 429                                data->info_fd = optint;
 430                                break;
 431                        case 'v':
 432                                ret = -ECHRNG;
 433                                if (optint < NCP_MOUNT_VERSION_V4)
 434                                        goto err;
 435                                if (optint > NCP_MOUNT_VERSION_V5)
 436                                        goto err;
 437                                version = optint;
 438                                break;
 439                        
 440                }
 441        }
 442        return 0;
 443err:
 444        put_pid(data->wdog_pid);
 445        data->wdog_pid = NULL;
 446        return ret;
 447}
 448
 449static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 450{
 451        struct ncp_mount_data_kernel data;
 452        struct ncp_server *server;
 453        struct file *ncp_filp;
 454        struct inode *root_inode;
 455        struct inode *sock_inode;
 456        struct socket *sock;
 457        int error;
 458        int default_bufsize;
 459#ifdef CONFIG_NCPFS_PACKET_SIGNING
 460        int options;
 461#endif
 462        struct ncp_entry_info finfo;
 463
 464        memset(&data, 0, sizeof(data));
 465        server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
 466        if (!server)
 467                return -ENOMEM;
 468        sb->s_fs_info = server;
 469
 470        error = -EFAULT;
 471        if (raw_data == NULL)
 472                goto out;
 473        switch (*(int*)raw_data) {
 474                case NCP_MOUNT_VERSION:
 475                        {
 476                                struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
 477
 478                                data.flags = md->flags;
 479                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
 480                                data.mounted_uid = md->mounted_uid;
 481                                data.wdog_pid = find_get_pid(md->wdog_pid);
 482                                data.ncp_fd = md->ncp_fd;
 483                                data.time_out = md->time_out;
 484                                data.retry_count = md->retry_count;
 485                                data.uid = md->uid;
 486                                data.gid = md->gid;
 487                                data.file_mode = md->file_mode;
 488                                data.dir_mode = md->dir_mode;
 489                                data.info_fd = -1;
 490                                memcpy(data.mounted_vol, md->mounted_vol,
 491                                        NCP_VOLNAME_LEN+1);
 492                        }
 493                        break;
 494                case NCP_MOUNT_VERSION_V4:
 495                        {
 496                                struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
 497
 498                                data.flags = md->flags;
 499                                data.mounted_uid = md->mounted_uid;
 500                                data.wdog_pid = find_get_pid(md->wdog_pid);
 501                                data.ncp_fd = md->ncp_fd;
 502                                data.time_out = md->time_out;
 503                                data.retry_count = md->retry_count;
 504                                data.uid = md->uid;
 505                                data.gid = md->gid;
 506                                data.file_mode = md->file_mode;
 507                                data.dir_mode = md->dir_mode;
 508                                data.info_fd = -1;
 509                        }
 510                        break;
 511                default:
 512                        error = -ECHRNG;
 513                        if (memcmp(raw_data, "vers", 4) == 0) {
 514                                error = ncp_parse_options(&data, raw_data);
 515                        }
 516                        if (error)
 517                                goto out;
 518                        break;
 519        }
 520        error = -EBADF;
 521        ncp_filp = fget(data.ncp_fd);
 522        if (!ncp_filp)
 523                goto out;
 524        error = -ENOTSOCK;
 525        sock_inode = ncp_filp->f_path.dentry->d_inode;
 526        if (!S_ISSOCK(sock_inode->i_mode))
 527                goto out_fput;
 528        sock = SOCKET_I(sock_inode);
 529        if (!sock)
 530                goto out_fput;
 531                
 532        if (sock->type == SOCK_STREAM)
 533                default_bufsize = 0xF000;
 534        else
 535                default_bufsize = 1024;
 536
 537        sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
 538        sb->s_maxbytes = 0xFFFFFFFFU;
 539        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 540        sb->s_blocksize_bits = 10;
 541        sb->s_magic = NCP_SUPER_MAGIC;
 542        sb->s_op = &ncp_sops;
 543        sb->s_d_op = &ncp_dentry_operations;
 544        sb->s_bdi = &server->bdi;
 545
 546        server = NCP_SBP(sb);
 547        memset(server, 0, sizeof(*server));
 548
 549        error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
 550        if (error)
 551                goto out_fput;
 552
 553        server->ncp_filp = ncp_filp;
 554        server->ncp_sock = sock;
 555        
 556        if (data.info_fd != -1) {
 557                struct socket *info_sock;
 558
 559                error = -EBADF;
 560                server->info_filp = fget(data.info_fd);
 561                if (!server->info_filp)
 562                        goto out_bdi;
 563                error = -ENOTSOCK;
 564                sock_inode = server->info_filp->f_path.dentry->d_inode;
 565                if (!S_ISSOCK(sock_inode->i_mode))
 566                        goto out_fput2;
 567                info_sock = SOCKET_I(sock_inode);
 568                if (!info_sock)
 569                        goto out_fput2;
 570                error = -EBADFD;
 571                if (info_sock->type != SOCK_STREAM)
 572                        goto out_fput2;
 573                server->info_sock = info_sock;
 574        }
 575
 576/*      server->lock = 0;       */
 577        mutex_init(&server->mutex);
 578        server->packet = NULL;
 579/*      server->buffer_size = 0;        */
 580/*      server->conn_status = 0;        */
 581/*      server->root_dentry = NULL;     */
 582/*      server->root_setuped = 0;       */
 583        mutex_init(&server->root_setup_lock);
 584#ifdef CONFIG_NCPFS_PACKET_SIGNING
 585/*      server->sign_wanted = 0;        */
 586/*      server->sign_active = 0;        */
 587#endif
 588        init_rwsem(&server->auth_rwsem);
 589        server->auth.auth_type = NCP_AUTH_NONE;
 590/*      server->auth.object_name_len = 0;       */
 591/*      server->auth.object_name = NULL;        */
 592/*      server->auth.object_type = 0;           */
 593/*      server->priv.len = 0;                   */
 594/*      server->priv.data = NULL;               */
 595
 596        server->m = data;
 597        /* Although anything producing this is buggy, it happens
 598           now because of PATH_MAX changes.. */
 599        if (server->m.time_out < 1) {
 600                server->m.time_out = 10;
 601                printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
 602        }
 603        server->m.time_out = server->m.time_out * HZ / 100;
 604        server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
 605        server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
 606
 607#ifdef CONFIG_NCPFS_NLS
 608        /* load the default NLS charsets */
 609        server->nls_vol = load_nls_default();
 610        server->nls_io = load_nls_default();
 611#endif /* CONFIG_NCPFS_NLS */
 612
 613        atomic_set(&server->dentry_ttl, 0);     /* no caching */
 614
 615        INIT_LIST_HEAD(&server->tx.requests);
 616        mutex_init(&server->rcv.creq_mutex);
 617        server->tx.creq         = NULL;
 618        server->rcv.creq        = NULL;
 619
 620        init_timer(&server->timeout_tm);
 621#undef NCP_PACKET_SIZE
 622#define NCP_PACKET_SIZE 131072
 623        error = -ENOMEM;
 624        server->packet_size = NCP_PACKET_SIZE;
 625        server->packet = vmalloc(NCP_PACKET_SIZE);
 626        if (server->packet == NULL)
 627                goto out_nls;
 628        server->txbuf = vmalloc(NCP_PACKET_SIZE);
 629        if (server->txbuf == NULL)
 630                goto out_packet;
 631        server->rxbuf = vmalloc(NCP_PACKET_SIZE);
 632        if (server->rxbuf == NULL)
 633                goto out_txbuf;
 634
 635        lock_sock(sock->sk);
 636        server->data_ready      = sock->sk->sk_data_ready;
 637        server->write_space     = sock->sk->sk_write_space;
 638        server->error_report    = sock->sk->sk_error_report;
 639        sock->sk->sk_user_data  = server;
 640        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
 641        sock->sk->sk_error_report = ncp_tcp_error_report;
 642        if (sock->type == SOCK_STREAM) {
 643                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
 644                server->rcv.len = 10;
 645                server->rcv.state = 0;
 646                INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
 647                INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
 648                sock->sk->sk_write_space = ncp_tcp_write_space;
 649        } else {
 650                INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
 651                INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
 652                server->timeout_tm.data = (unsigned long)server;
 653                server->timeout_tm.function = ncpdgram_timeout_call;
 654        }
 655        release_sock(sock->sk);
 656
 657        ncp_lock_server(server);
 658        error = ncp_connect(server);
 659        ncp_unlock_server(server);
 660        if (error < 0)
 661                goto out_rxbuf;
 662        DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
 663
 664        error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
 665#ifdef CONFIG_NCPFS_PACKET_SIGNING
 666        if (ncp_negotiate_size_and_options(server, default_bufsize,
 667                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
 668        {
 669                if (options != NCP_DEFAULT_OPTIONS)
 670                {
 671                        if (ncp_negotiate_size_and_options(server, 
 672                                default_bufsize,
 673                                options & 2, 
 674                                &(server->buffer_size), &options) != 0)
 675                                
 676                        {
 677                                goto out_disconnect;
 678                        }
 679                }
 680                ncp_lock_server(server);
 681                if (options & 2)
 682                        server->sign_wanted = 1;
 683                ncp_unlock_server(server);
 684        }
 685        else 
 686#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
 687        if (ncp_negotiate_buffersize(server, default_bufsize,
 688                                     &(server->buffer_size)) != 0)
 689                goto out_disconnect;
 690        DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
 691
 692        memset(&finfo, 0, sizeof(finfo));
 693        finfo.i.attributes      = aDIR;
 694        finfo.i.dataStreamSize  = 0;    /* ignored */
 695        finfo.i.dirEntNum       = 0;
 696        finfo.i.DosDirNum       = 0;
 697#ifdef CONFIG_NCPFS_SMALLDOS
 698        finfo.i.NSCreator       = NW_NS_DOS;
 699#endif
 700        finfo.volume            = NCP_NUMBER_OF_VOLUMES;
 701        /* set dates of mountpoint to Jan 1, 1986; 00:00 */
 702        finfo.i.creationTime    = finfo.i.modifyTime
 703                                = cpu_to_le16(0x0000);
 704        finfo.i.creationDate    = finfo.i.modifyDate
 705                                = finfo.i.lastAccessDate
 706                                = cpu_to_le16(0x0C21);
 707        finfo.i.nameLen         = 0;
 708        finfo.i.entryName[0]    = '\0';
 709
 710        finfo.opened            = 0;
 711        finfo.ino               = 2;    /* tradition */
 712
 713        server->name_space[finfo.volume] = NW_NS_DOS;
 714
 715        error = -ENOMEM;
 716        root_inode = ncp_iget(sb, &finfo);
 717        if (!root_inode)
 718                goto out_disconnect;
 719        DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 720        sb->s_root = d_alloc_root(root_inode);
 721        if (!sb->s_root)
 722                goto out_no_root;
 723        return 0;
 724
 725out_no_root:
 726        iput(root_inode);
 727out_disconnect:
 728        ncp_lock_server(server);
 729        ncp_disconnect(server);
 730        ncp_unlock_server(server);
 731out_rxbuf:
 732        ncp_stop_tasks(server);
 733        vfree(server->rxbuf);
 734out_txbuf:
 735        vfree(server->txbuf);
 736out_packet:
 737        vfree(server->packet);
 738out_nls:
 739#ifdef CONFIG_NCPFS_NLS
 740        unload_nls(server->nls_io);
 741        unload_nls(server->nls_vol);
 742#endif
 743        mutex_destroy(&server->rcv.creq_mutex);
 744        mutex_destroy(&server->root_setup_lock);
 745        mutex_destroy(&server->mutex);
 746out_fput2:
 747        if (server->info_filp)
 748                fput(server->info_filp);
 749out_bdi:
 750        bdi_destroy(&server->bdi);
 751out_fput:
 752        /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
 753         * 
 754         * The previously used put_filp(ncp_filp); was bogus, since
 755         * it doesn't perform proper unlocking.
 756         */
 757        fput(ncp_filp);
 758out:
 759        put_pid(data.wdog_pid);
 760        sb->s_fs_info = NULL;
 761        kfree(server);
 762        return error;
 763}
 764
 765static void ncp_put_super(struct super_block *sb)
 766{
 767        struct ncp_server *server = NCP_SBP(sb);
 768
 769        ncp_lock_server(server);
 770        ncp_disconnect(server);
 771        ncp_unlock_server(server);
 772
 773        ncp_stop_tasks(server);
 774
 775#ifdef CONFIG_NCPFS_NLS
 776        /* unload the NLS charsets */
 777        unload_nls(server->nls_vol);
 778        unload_nls(server->nls_io);
 779#endif /* CONFIG_NCPFS_NLS */
 780        mutex_destroy(&server->rcv.creq_mutex);
 781        mutex_destroy(&server->root_setup_lock);
 782        mutex_destroy(&server->mutex);
 783
 784        if (server->info_filp)
 785                fput(server->info_filp);
 786        fput(server->ncp_filp);
 787        kill_pid(server->m.wdog_pid, SIGTERM, 1);
 788        put_pid(server->m.wdog_pid);
 789
 790        bdi_destroy(&server->bdi);
 791        kfree(server->priv.data);
 792        kfree(server->auth.object_name);
 793        vfree(server->rxbuf);
 794        vfree(server->txbuf);
 795        vfree(server->packet);
 796        sb->s_fs_info = NULL;
 797        kfree(server);
 798}
 799
 800static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
 801{
 802        struct dentry* d;
 803        struct inode* i;
 804        struct ncp_inode_info* ni;
 805        struct ncp_server* s;
 806        struct ncp_volume_info vi;
 807        struct super_block *sb = dentry->d_sb;
 808        int err;
 809        __u8 dh;
 810        
 811        d = sb->s_root;
 812        if (!d) {
 813                goto dflt;
 814        }
 815        i = d->d_inode;
 816        if (!i) {
 817                goto dflt;
 818        }
 819        ni = NCP_FINFO(i);
 820        if (!ni) {
 821                goto dflt;
 822        }
 823        s = NCP_SBP(sb);
 824        if (!s) {
 825                goto dflt;
 826        }
 827        if (!s->m.mounted_vol[0]) {
 828                goto dflt;
 829        }
 830
 831        err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
 832        if (err) {
 833                goto dflt;
 834        }
 835        err = ncp_get_directory_info(s, dh, &vi);
 836        ncp_dirhandle_free(s, dh);
 837        if (err) {
 838                goto dflt;
 839        }
 840        buf->f_type = NCP_SUPER_MAGIC;
 841        buf->f_bsize = vi.sectors_per_block * 512;
 842        buf->f_blocks = vi.total_blocks;
 843        buf->f_bfree = vi.free_blocks;
 844        buf->f_bavail = vi.free_blocks;
 845        buf->f_files = vi.total_dir_entries;
 846        buf->f_ffree = vi.available_dir_entries;
 847        buf->f_namelen = 12;
 848        return 0;
 849
 850        /* We cannot say how much disk space is left on a mounted
 851           NetWare Server, because free space is distributed over
 852           volumes, and the current user might have disk quotas. So
 853           free space is not that simple to determine. Our decision
 854           here is to err conservatively. */
 855
 856dflt:;
 857        buf->f_type = NCP_SUPER_MAGIC;
 858        buf->f_bsize = NCP_BLOCK_SIZE;
 859        buf->f_blocks = 0;
 860        buf->f_bfree = 0;
 861        buf->f_bavail = 0;
 862        buf->f_namelen = 12;
 863        return 0;
 864}
 865
 866int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 867{
 868        struct inode *inode = dentry->d_inode;
 869        int result = 0;
 870        __le32 info_mask;
 871        struct nw_modify_dos_info info;
 872        struct ncp_server *server;
 873
 874        result = -EIO;
 875
 876        server = NCP_SERVER(inode);
 877        if (!server)    /* How this could happen? */
 878                goto out;
 879
 880        /* ageing the dentry to force validation */
 881        ncp_age_dentry(server, dentry);
 882
 883        result = inode_change_ok(inode, attr);
 884        if (result < 0)
 885                goto out;
 886
 887        result = -EPERM;
 888        if (((attr->ia_valid & ATTR_UID) &&
 889             (attr->ia_uid != server->m.uid)))
 890                goto out;
 891
 892        if (((attr->ia_valid & ATTR_GID) &&
 893             (attr->ia_gid != server->m.gid)))
 894                goto out;
 895
 896        if (((attr->ia_valid & ATTR_MODE) &&
 897             (attr->ia_mode &
 898              ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
 899                goto out;
 900
 901        info_mask = 0;
 902        memset(&info, 0, sizeof(info));
 903
 904#if 1 
 905        if ((attr->ia_valid & ATTR_MODE) != 0)
 906        {
 907                umode_t newmode = attr->ia_mode;
 908
 909                info_mask |= DM_ATTRIBUTES;
 910
 911                if (S_ISDIR(inode->i_mode)) {
 912                        newmode &= server->m.dir_mode;
 913                } else {
 914#ifdef CONFIG_NCPFS_EXTRAS                      
 915                        if (server->m.flags & NCP_MOUNT_EXTRAS) {
 916                                /* any non-default execute bit set */
 917                                if (newmode & ~server->m.file_mode & S_IXUGO)
 918                                        info.attributes |= aSHARED | aSYSTEM;
 919                                /* read for group/world and not in default file_mode */
 920                                else if (newmode & ~server->m.file_mode & S_IRUGO)
 921                                        info.attributes |= aSHARED;
 922                        } else
 923#endif
 924                                newmode &= server->m.file_mode;                 
 925                }
 926                if (newmode & S_IWUGO)
 927                        info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 928                else
 929                        info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 930
 931#ifdef CONFIG_NCPFS_NFS_NS
 932                if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
 933                        result = ncp_modify_nfs_info(server,
 934                                                     NCP_FINFO(inode)->volNumber,
 935                                                     NCP_FINFO(inode)->dirEntNum,
 936                                                     attr->ia_mode, 0);
 937                        if (result != 0)
 938                                goto out;
 939                        info.attributes &= ~(aSHARED | aSYSTEM);
 940                        {
 941                                /* mark partial success */
 942                                struct iattr tmpattr;
 943                                
 944                                tmpattr.ia_valid = ATTR_MODE;
 945                                tmpattr.ia_mode = attr->ia_mode;
 946
 947                                setattr_copy(inode, &tmpattr);
 948                                mark_inode_dirty(inode);
 949                        }
 950                }
 951#endif
 952        }
 953#endif
 954
 955        /* Do SIZE before attributes, otherwise mtime together with size does not work...
 956         */
 957        if ((attr->ia_valid & ATTR_SIZE) != 0) {
 958                int written;
 959
 960                DPRINTK("ncpfs: trying to change size to %ld\n",
 961                        attr->ia_size);
 962
 963                if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
 964                        result = -EACCES;
 965                        goto out;
 966                }
 967                ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
 968                          attr->ia_size, 0, "", &written);
 969
 970                /* According to ndir, the changes only take effect after
 971                   closing the file */
 972                ncp_inode_close(inode);
 973                result = ncp_make_closed(inode);
 974                if (result)
 975                        goto out;
 976
 977                if (attr->ia_size != i_size_read(inode)) {
 978                        result = vmtruncate(inode, attr->ia_size);
 979                        if (result)
 980                                goto out;
 981                        mark_inode_dirty(inode);
 982                }
 983        }
 984        if ((attr->ia_valid & ATTR_CTIME) != 0) {
 985                info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
 986                ncp_date_unix2dos(attr->ia_ctime.tv_sec,
 987                             &info.creationTime, &info.creationDate);
 988        }
 989        if ((attr->ia_valid & ATTR_MTIME) != 0) {
 990                info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
 991                ncp_date_unix2dos(attr->ia_mtime.tv_sec,
 992                                  &info.modifyTime, &info.modifyDate);
 993        }
 994        if ((attr->ia_valid & ATTR_ATIME) != 0) {
 995                __le16 dummy;
 996                info_mask |= (DM_LAST_ACCESS_DATE);
 997                ncp_date_unix2dos(attr->ia_atime.tv_sec,
 998                                  &dummy, &info.lastAccessDate);
 999        }
1000        if (info_mask != 0) {
1001                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1002                                      inode, info_mask, &info);
1003                if (result != 0) {
1004                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1005                                /* NetWare seems not to allow this. I
1006                                   do not know why. So, just tell the
1007                                   user everything went fine. This is
1008                                   a terrible hack, but I do not know
1009                                   how to do this correctly. */
1010                                result = 0;
1011                        } else
1012                                goto out;
1013                }
1014#ifdef CONFIG_NCPFS_STRONG              
1015                if ((!result) && (info_mask & DM_ATTRIBUTES))
1016                        NCP_FINFO(inode)->nwattr = info.attributes;
1017#endif
1018        }
1019        if (result)
1020                goto out;
1021
1022        setattr_copy(inode, attr);
1023        mark_inode_dirty(inode);
1024
1025out:
1026        if (result > 0)
1027                result = -EACCES;
1028        return result;
1029}
1030
1031static struct dentry *ncp_mount(struct file_system_type *fs_type,
1032        int flags, const char *dev_name, void *data)
1033{
1034        return mount_nodev(fs_type, flags, data, ncp_fill_super);
1035}
1036
1037static struct file_system_type ncp_fs_type = {
1038        .owner          = THIS_MODULE,
1039        .name           = "ncpfs",
1040        .mount          = ncp_mount,
1041        .kill_sb        = kill_anon_super,
1042        .fs_flags       = FS_BINARY_MOUNTDATA,
1043};
1044
1045static int __init init_ncp_fs(void)
1046{
1047        int err;
1048        DPRINTK("ncpfs: init_ncp_fs called\n");
1049
1050        err = init_inodecache();
1051        if (err)
1052                goto out1;
1053        err = register_filesystem(&ncp_fs_type);
1054        if (err)
1055                goto out;
1056        return 0;
1057out:
1058        destroy_inodecache();
1059out1:
1060        return err;
1061}
1062
1063static void __exit exit_ncp_fs(void)
1064{
1065        DPRINTK("ncpfs: exit_ncp_fs called\n");
1066        unregister_filesystem(&ncp_fs_type);
1067        destroy_inodecache();
1068}
1069
1070module_init(init_ncp_fs)
1071module_exit(exit_ncp_fs)
1072MODULE_LICENSE("GPL");
1073