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