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 <asm/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        .readlink       = generic_readlink,
 247        .get_link       = page_get_link,
 248        .setattr        = ncp_notify_change,
 249};
 250#endif
 251
 252/*
 253 * Get a new inode.
 254 */
 255struct inode * 
 256ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 257{
 258        struct inode *inode;
 259
 260        if (info == NULL) {
 261                pr_err("%s: info is NULL\n", __func__);
 262                return NULL;
 263        }
 264
 265        inode = new_inode(sb);
 266        if (inode) {
 267                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 268
 269                inode->i_ino = info->ino;
 270                ncp_set_attr(inode, info);
 271                if (S_ISREG(inode->i_mode)) {
 272                        inode->i_op = &ncp_file_inode_operations;
 273                        inode->i_fop = &ncp_file_operations;
 274                } else if (S_ISDIR(inode->i_mode)) {
 275                        inode->i_op = &ncp_dir_inode_operations;
 276                        inode->i_fop = &ncp_dir_operations;
 277#ifdef CONFIG_NCPFS_NFS_NS
 278                } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
 279                        init_special_inode(inode, inode->i_mode,
 280                                new_decode_dev(info->i.nfs.rdev));
 281#endif
 282#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 283                } else if (S_ISLNK(inode->i_mode)) {
 284                        inode->i_op = &ncp_symlink_inode_operations;
 285                        inode_nohighmem(inode);
 286                        inode->i_data.a_ops = &ncp_symlink_aops;
 287#endif
 288                } else {
 289                        make_bad_inode(inode);
 290                }
 291                insert_inode_hash(inode);
 292        } else
 293                pr_err("%s: iget failed!\n", __func__);
 294        return inode;
 295}
 296
 297static void
 298ncp_evict_inode(struct inode *inode)
 299{
 300        truncate_inode_pages_final(&inode->i_data);
 301        clear_inode(inode);
 302
 303        if (S_ISDIR(inode->i_mode)) {
 304                ncp_dbg(2, "put directory %ld\n", inode->i_ino);
 305        }
 306
 307        if (ncp_make_closed(inode) != 0) {
 308                /* We can't do anything but complain. */
 309                pr_err("%s: could not close\n", __func__);
 310        }
 311}
 312
 313static void ncp_stop_tasks(struct ncp_server *server) {
 314        struct sock* sk = server->ncp_sock->sk;
 315
 316        lock_sock(sk);
 317        sk->sk_error_report = server->error_report;
 318        sk->sk_data_ready   = server->data_ready;
 319        sk->sk_write_space  = server->write_space;
 320        release_sock(sk);
 321        del_timer_sync(&server->timeout_tm);
 322
 323        flush_work(&server->rcv.tq);
 324        if (sk->sk_socket->type == SOCK_STREAM)
 325                flush_work(&server->tx.tq);
 326        else
 327                flush_work(&server->timeout_tq);
 328}
 329
 330static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
 331{
 332        struct ncp_server *server = NCP_SBP(root->d_sb);
 333        unsigned int tmp;
 334
 335        if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
 336                seq_printf(seq, ",uid=%u",
 337                           from_kuid_munged(&init_user_ns, server->m.uid));
 338        if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
 339                seq_printf(seq, ",gid=%u",
 340                           from_kgid_munged(&init_user_ns, server->m.gid));
 341        if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
 342                seq_printf(seq, ",owner=%u",
 343                           from_kuid_munged(&init_user_ns, server->m.mounted_uid));
 344        tmp = server->m.file_mode & S_IALLUGO;
 345        if (tmp != NCP_DEFAULT_FILE_MODE)
 346                seq_printf(seq, ",mode=0%o", tmp);
 347        tmp = server->m.dir_mode & S_IALLUGO;
 348        if (tmp != NCP_DEFAULT_DIR_MODE)
 349                seq_printf(seq, ",dirmode=0%o", tmp);
 350        if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
 351                tmp = server->m.time_out * 100 / HZ;
 352                seq_printf(seq, ",timeout=%u", tmp);
 353        }
 354        if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
 355                seq_printf(seq, ",retry=%u", server->m.retry_count);
 356        if (server->m.flags != 0)
 357                seq_printf(seq, ",flags=%lu", server->m.flags);
 358        if (server->m.wdog_pid != NULL)
 359                seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
 360
 361        return 0;
 362}
 363
 364static const struct ncp_option ncp_opts[] = {
 365        { "uid",        OPT_INT,        'u' },
 366        { "gid",        OPT_INT,        'g' },
 367        { "owner",      OPT_INT,        'o' },
 368        { "mode",       OPT_INT,        'm' },
 369        { "dirmode",    OPT_INT,        'd' },
 370        { "timeout",    OPT_INT,        't' },
 371        { "retry",      OPT_INT,        'r' },
 372        { "flags",      OPT_INT,        'f' },
 373        { "wdogpid",    OPT_INT,        'w' },
 374        { "ncpfd",      OPT_INT,        'n' },
 375        { "infofd",     OPT_INT,        'i' },  /* v5 */
 376        { "version",    OPT_INT,        'v' },
 377        { NULL,         0,              0 } };
 378
 379static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
 380        int optval;
 381        char *optarg;
 382        unsigned long optint;
 383        int version = 0;
 384        int ret;
 385
 386        data->flags = 0;
 387        data->int_flags = 0;
 388        data->mounted_uid = GLOBAL_ROOT_UID;
 389        data->wdog_pid = NULL;
 390        data->ncp_fd = ~0;
 391        data->time_out = NCP_DEFAULT_TIME_OUT;
 392        data->retry_count = NCP_DEFAULT_RETRY_COUNT;
 393        data->uid = GLOBAL_ROOT_UID;
 394        data->gid = GLOBAL_ROOT_GID;
 395        data->file_mode = NCP_DEFAULT_FILE_MODE;
 396        data->dir_mode = NCP_DEFAULT_DIR_MODE;
 397        data->info_fd = -1;
 398        data->mounted_vol[0] = 0;
 399        
 400        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
 401                ret = optval;
 402                if (ret < 0)
 403                        goto err;
 404                switch (optval) {
 405                        case 'u':
 406                                data->uid = make_kuid(current_user_ns(), optint);
 407                                if (!uid_valid(data->uid)) {
 408                                        ret = -EINVAL;
 409                                        goto err;
 410                                }
 411                                break;
 412                        case 'g':
 413                                data->gid = make_kgid(current_user_ns(), optint);
 414                                if (!gid_valid(data->gid)) {
 415                                        ret = -EINVAL;
 416                                        goto err;
 417                                }
 418                                break;
 419                        case 'o':
 420                                data->mounted_uid = make_kuid(current_user_ns(), optint);
 421                                if (!uid_valid(data->mounted_uid)) {
 422                                        ret = -EINVAL;
 423                                        goto err;
 424                                }
 425                                break;
 426                        case 'm':
 427                                data->file_mode = optint;
 428                                break;
 429                        case 'd':
 430                                data->dir_mode = optint;
 431                                break;
 432                        case 't':
 433                                data->time_out = optint;
 434                                break;
 435                        case 'r':
 436                                data->retry_count = optint;
 437                                break;
 438                        case 'f':
 439                                data->flags = optint;
 440                                break;
 441                        case 'w':
 442                                data->wdog_pid = find_get_pid(optint);
 443                                break;
 444                        case 'n':
 445                                data->ncp_fd = optint;
 446                                break;
 447                        case 'i':
 448                                data->info_fd = optint;
 449                                break;
 450                        case 'v':
 451                                ret = -ECHRNG;
 452                                if (optint < NCP_MOUNT_VERSION_V4)
 453                                        goto err;
 454                                if (optint > NCP_MOUNT_VERSION_V5)
 455                                        goto err;
 456                                version = optint;
 457                                break;
 458                        
 459                }
 460        }
 461        return 0;
 462err:
 463        put_pid(data->wdog_pid);
 464        data->wdog_pid = NULL;
 465        return ret;
 466}
 467
 468static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 469{
 470        struct ncp_mount_data_kernel data;
 471        struct ncp_server *server;
 472        struct inode *root_inode;
 473        struct socket *sock;
 474        int error;
 475        int default_bufsize;
 476#ifdef CONFIG_NCPFS_PACKET_SIGNING
 477        int options;
 478#endif
 479        struct ncp_entry_info finfo;
 480
 481        memset(&data, 0, sizeof(data));
 482        server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
 483        if (!server)
 484                return -ENOMEM;
 485        sb->s_fs_info = server;
 486
 487        error = -EFAULT;
 488        if (raw_data == NULL)
 489                goto out;
 490        switch (*(int*)raw_data) {
 491                case NCP_MOUNT_VERSION:
 492                        {
 493                                struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
 494
 495                                data.flags = md->flags;
 496                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
 497                                data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
 498                                data.wdog_pid = find_get_pid(md->wdog_pid);
 499                                data.ncp_fd = md->ncp_fd;
 500                                data.time_out = md->time_out;
 501                                data.retry_count = md->retry_count;
 502                                data.uid = make_kuid(current_user_ns(), md->uid);
 503                                data.gid = make_kgid(current_user_ns(), md->gid);
 504                                data.file_mode = md->file_mode;
 505                                data.dir_mode = md->dir_mode;
 506                                data.info_fd = -1;
 507                                memcpy(data.mounted_vol, md->mounted_vol,
 508                                        NCP_VOLNAME_LEN+1);
 509                        }
 510                        break;
 511                case NCP_MOUNT_VERSION_V4:
 512                        {
 513                                struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
 514
 515                                data.flags = md->flags;
 516                                data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
 517                                data.wdog_pid = find_get_pid(md->wdog_pid);
 518                                data.ncp_fd = md->ncp_fd;
 519                                data.time_out = md->time_out;
 520                                data.retry_count = md->retry_count;
 521                                data.uid = make_kuid(current_user_ns(), md->uid);
 522                                data.gid = make_kgid(current_user_ns(), md->gid);
 523                                data.file_mode = md->file_mode;
 524                                data.dir_mode = md->dir_mode;
 525                                data.info_fd = -1;
 526                        }
 527                        break;
 528                default:
 529                        error = -ECHRNG;
 530                        if (memcmp(raw_data, "vers", 4) == 0) {
 531                                error = ncp_parse_options(&data, raw_data);
 532                        }
 533                        if (error)
 534                                goto out;
 535                        break;
 536        }
 537        error = -EINVAL;
 538        if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
 539            !gid_valid(data.gid))
 540                goto out;
 541        sock = sockfd_lookup(data.ncp_fd, &error);
 542        if (!sock)
 543                goto out;
 544
 545        if (sock->type == SOCK_STREAM)
 546                default_bufsize = 0xF000;
 547        else
 548                default_bufsize = 1024;
 549
 550        sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
 551        sb->s_maxbytes = 0xFFFFFFFFU;
 552        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 553        sb->s_blocksize_bits = 10;
 554        sb->s_magic = NCP_SUPER_MAGIC;
 555        sb->s_op = &ncp_sops;
 556        sb->s_d_op = &ncp_dentry_operations;
 557        sb->s_bdi = &server->bdi;
 558
 559        server = NCP_SBP(sb);
 560        memset(server, 0, sizeof(*server));
 561
 562        error = bdi_setup_and_register(&server->bdi, "ncpfs");
 563        if (error)
 564                goto out_fput;
 565
 566        server->ncp_sock = sock;
 567        
 568        if (data.info_fd != -1) {
 569                struct socket *info_sock = sockfd_lookup(data.info_fd, &error);
 570                if (!info_sock)
 571                        goto out_bdi;
 572                server->info_sock = info_sock;
 573                error = -EBADFD;
 574                if (info_sock->type != SOCK_STREAM)
 575                        goto out_fput2;
 576        }
 577
 578/*      server->lock = 0;       */
 579        mutex_init(&server->mutex);
 580        server->packet = NULL;
 581/*      server->buffer_size = 0;        */
 582/*      server->conn_status = 0;        */
 583/*      server->root_dentry = NULL;     */
 584/*      server->root_setuped = 0;       */
 585        mutex_init(&server->root_setup_lock);
 586#ifdef CONFIG_NCPFS_PACKET_SIGNING
 587/*      server->sign_wanted = 0;        */
 588/*      server->sign_active = 0;        */
 589#endif
 590        init_rwsem(&server->auth_rwsem);
 591        server->auth.auth_type = NCP_AUTH_NONE;
 592/*      server->auth.object_name_len = 0;       */
 593/*      server->auth.object_name = NULL;        */
 594/*      server->auth.object_type = 0;           */
 595/*      server->priv.len = 0;                   */
 596/*      server->priv.data = NULL;               */
 597
 598        server->m = data;
 599        /* Although anything producing this is buggy, it happens
 600           now because of PATH_MAX changes.. */
 601        if (server->m.time_out < 1) {
 602                server->m.time_out = 10;
 603                pr_info("You need to recompile your ncpfs utils..\n");
 604        }
 605        server->m.time_out = server->m.time_out * HZ / 100;
 606        server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
 607        server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
 608
 609#ifdef CONFIG_NCPFS_NLS
 610        /* load the default NLS charsets */
 611        server->nls_vol = load_nls_default();
 612        server->nls_io = load_nls_default();
 613#endif /* CONFIG_NCPFS_NLS */
 614
 615        atomic_set(&server->dentry_ttl, 0);     /* no caching */
 616
 617        INIT_LIST_HEAD(&server->tx.requests);
 618        mutex_init(&server->rcv.creq_mutex);
 619        server->tx.creq         = NULL;
 620        server->rcv.creq        = NULL;
 621
 622        init_timer(&server->timeout_tm);
 623#undef NCP_PACKET_SIZE
 624#define NCP_PACKET_SIZE 131072
 625        error = -ENOMEM;
 626        server->packet_size = NCP_PACKET_SIZE;
 627        server->packet = vmalloc(NCP_PACKET_SIZE);
 628        if (server->packet == NULL)
 629                goto out_nls;
 630        server->txbuf = vmalloc(NCP_PACKET_SIZE);
 631        if (server->txbuf == NULL)
 632                goto out_packet;
 633        server->rxbuf = vmalloc(NCP_PACKET_SIZE);
 634        if (server->rxbuf == NULL)
 635                goto out_txbuf;
 636
 637        lock_sock(sock->sk);
 638        server->data_ready      = sock->sk->sk_data_ready;
 639        server->write_space     = sock->sk->sk_write_space;
 640        server->error_report    = sock->sk->sk_error_report;
 641        sock->sk->sk_user_data  = server;
 642        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
 643        sock->sk->sk_error_report = ncp_tcp_error_report;
 644        if (sock->type == SOCK_STREAM) {
 645                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
 646                server->rcv.len = 10;
 647                server->rcv.state = 0;
 648                INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
 649                INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
 650                sock->sk->sk_write_space = ncp_tcp_write_space;
 651        } else {
 652                INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
 653                INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
 654                server->timeout_tm.data = (unsigned long)server;
 655                server->timeout_tm.function = ncpdgram_timeout_call;
 656        }
 657        release_sock(sock->sk);
 658
 659        ncp_lock_server(server);
 660        error = ncp_connect(server);
 661        ncp_unlock_server(server);
 662        if (error < 0)
 663                goto out_rxbuf;
 664        ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
 665
 666        error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
 667#ifdef CONFIG_NCPFS_PACKET_SIGNING
 668        if (ncp_negotiate_size_and_options(server, default_bufsize,
 669                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
 670        {
 671                if (options != NCP_DEFAULT_OPTIONS)
 672                {
 673                        if (ncp_negotiate_size_and_options(server, 
 674                                default_bufsize,
 675                                options & 2, 
 676                                &(server->buffer_size), &options) != 0)
 677                                
 678                        {
 679                                goto out_disconnect;
 680                        }
 681                }
 682                ncp_lock_server(server);
 683                if (options & 2)
 684                        server->sign_wanted = 1;
 685                ncp_unlock_server(server);
 686        }
 687        else 
 688#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
 689        if (ncp_negotiate_buffersize(server, default_bufsize,
 690                                     &(server->buffer_size)) != 0)
 691                goto out_disconnect;
 692        ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
 693
 694        memset(&finfo, 0, sizeof(finfo));
 695        finfo.i.attributes      = aDIR;
 696        finfo.i.dataStreamSize  = 0;    /* ignored */
 697        finfo.i.dirEntNum       = 0;
 698        finfo.i.DosDirNum       = 0;
 699#ifdef CONFIG_NCPFS_SMALLDOS
 700        finfo.i.NSCreator       = NW_NS_DOS;
 701#endif
 702        finfo.volume            = NCP_NUMBER_OF_VOLUMES;
 703        /* set dates of mountpoint to Jan 1, 1986; 00:00 */
 704        finfo.i.creationTime    = finfo.i.modifyTime
 705                                = cpu_to_le16(0x0000);
 706        finfo.i.creationDate    = finfo.i.modifyDate
 707                                = finfo.i.lastAccessDate
 708                                = cpu_to_le16(0x0C21);
 709        finfo.i.nameLen         = 0;
 710        finfo.i.entryName[0]    = '\0';
 711
 712        finfo.opened            = 0;
 713        finfo.ino               = 2;    /* tradition */
 714
 715        server->name_space[finfo.volume] = NW_NS_DOS;
 716
 717        error = -ENOMEM;
 718        root_inode = ncp_iget(sb, &finfo);
 719        if (!root_inode)
 720                goto out_disconnect;
 721        ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 722        sb->s_root = d_make_root(root_inode);
 723        if (!sb->s_root)
 724                goto out_disconnect;
 725        return 0;
 726
 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_sock)
 748                sockfd_put(server->info_sock);
 749out_bdi:
 750        bdi_destroy(&server->bdi);
 751out_fput:
 752        sockfd_put(sock);
 753out:
 754        put_pid(data.wdog_pid);
 755        sb->s_fs_info = NULL;
 756        kfree(server);
 757        return error;
 758}
 759
 760static void delayed_free(struct rcu_head *p)
 761{
 762        struct ncp_server *server = container_of(p, struct ncp_server, rcu);
 763#ifdef CONFIG_NCPFS_NLS
 764        /* unload the NLS charsets */
 765        unload_nls(server->nls_vol);
 766        unload_nls(server->nls_io);
 767#endif /* CONFIG_NCPFS_NLS */
 768        kfree(server);
 769}
 770
 771static void ncp_put_super(struct super_block *sb)
 772{
 773        struct ncp_server *server = NCP_SBP(sb);
 774
 775        ncp_lock_server(server);
 776        ncp_disconnect(server);
 777        ncp_unlock_server(server);
 778
 779        ncp_stop_tasks(server);
 780
 781        mutex_destroy(&server->rcv.creq_mutex);
 782        mutex_destroy(&server->root_setup_lock);
 783        mutex_destroy(&server->mutex);
 784
 785        if (server->info_sock)
 786                sockfd_put(server->info_sock);
 787        sockfd_put(server->ncp_sock);
 788        kill_pid(server->m.wdog_pid, SIGTERM, 1);
 789        put_pid(server->m.wdog_pid);
 790
 791        bdi_destroy(&server->bdi);
 792        kfree(server->priv.data);
 793        kfree(server->auth.object_name);
 794        vfree(server->rxbuf);
 795        vfree(server->txbuf);
 796        vfree(server->packet);
 797        call_rcu(&server->rcu, delayed_free);
 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_inode(d);
 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 = d_inode(dentry);
 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        result = -EPERM;
 881        if (IS_DEADDIR(d_inode(dentry)))
 882                goto out;
 883
 884        /* ageing the dentry to force validation */
 885        ncp_age_dentry(server, dentry);
 886
 887        result = inode_change_ok(inode, attr);
 888        if (result < 0)
 889                goto out;
 890
 891        result = -EPERM;
 892        if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
 893                goto out;
 894
 895        if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
 896                goto out;
 897
 898        if (((attr->ia_valid & ATTR_MODE) &&
 899             (attr->ia_mode &
 900              ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
 901                goto out;
 902
 903        info_mask = 0;
 904        memset(&info, 0, sizeof(info));
 905
 906#if 1 
 907        if ((attr->ia_valid & ATTR_MODE) != 0)
 908        {
 909                umode_t newmode = attr->ia_mode;
 910
 911                info_mask |= DM_ATTRIBUTES;
 912
 913                if (S_ISDIR(inode->i_mode)) {
 914                        newmode &= server->m.dir_mode;
 915                } else {
 916#ifdef CONFIG_NCPFS_EXTRAS                      
 917                        if (server->m.flags & NCP_MOUNT_EXTRAS) {
 918                                /* any non-default execute bit set */
 919                                if (newmode & ~server->m.file_mode & S_IXUGO)
 920                                        info.attributes |= aSHARED | aSYSTEM;
 921                                /* read for group/world and not in default file_mode */
 922                                else if (newmode & ~server->m.file_mode & S_IRUGO)
 923                                        info.attributes |= aSHARED;
 924                        } else
 925#endif
 926                                newmode &= server->m.file_mode;                 
 927                }
 928                if (newmode & S_IWUGO)
 929                        info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 930                else
 931                        info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 932
 933#ifdef CONFIG_NCPFS_NFS_NS
 934                if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
 935                        result = ncp_modify_nfs_info(server,
 936                                                     NCP_FINFO(inode)->volNumber,
 937                                                     NCP_FINFO(inode)->dirEntNum,
 938                                                     attr->ia_mode, 0);
 939                        if (result != 0)
 940                                goto out;
 941                        info.attributes &= ~(aSHARED | aSYSTEM);
 942                        {
 943                                /* mark partial success */
 944                                struct iattr tmpattr;
 945                                
 946                                tmpattr.ia_valid = ATTR_MODE;
 947                                tmpattr.ia_mode = attr->ia_mode;
 948
 949                                setattr_copy(inode, &tmpattr);
 950                                mark_inode_dirty(inode);
 951                        }
 952                }
 953#endif
 954        }
 955#endif
 956
 957        /* Do SIZE before attributes, otherwise mtime together with size does not work...
 958         */
 959        if ((attr->ia_valid & ATTR_SIZE) != 0) {
 960                int written;
 961
 962                ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
 963
 964                if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
 965                        result = -EACCES;
 966                        goto out;
 967                }
 968                ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
 969                          attr->ia_size, 0, "", &written);
 970
 971                /* According to ndir, the changes only take effect after
 972                   closing the file */
 973                ncp_inode_close(inode);
 974                result = ncp_make_closed(inode);
 975                if (result)
 976                        goto out;
 977
 978                if (attr->ia_size != i_size_read(inode)) {
 979                        truncate_setsize(inode, attr->ia_size);
 980                        mark_inode_dirty(inode);
 981                }
 982        }
 983        if ((attr->ia_valid & ATTR_CTIME) != 0) {
 984                info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
 985                ncp_date_unix2dos(attr->ia_ctime.tv_sec,
 986                             &info.creationTime, &info.creationDate);
 987        }
 988        if ((attr->ia_valid & ATTR_MTIME) != 0) {
 989                info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
 990                ncp_date_unix2dos(attr->ia_mtime.tv_sec,
 991                                  &info.modifyTime, &info.modifyDate);
 992        }
 993        if ((attr->ia_valid & ATTR_ATIME) != 0) {
 994                __le16 dummy;
 995                info_mask |= (DM_LAST_ACCESS_DATE);
 996                ncp_date_unix2dos(attr->ia_atime.tv_sec,
 997                                  &dummy, &info.lastAccessDate);
 998        }
 999        if (info_mask != 0) {
1000                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1001                                      inode, info_mask, &info);
1002                if (result != 0) {
1003                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1004                                /* NetWare seems not to allow this. I
1005                                   do not know why. So, just tell the
1006                                   user everything went fine. This is
1007                                   a terrible hack, but I do not know
1008                                   how to do this correctly. */
1009                                result = 0;
1010                        } else
1011                                goto out;
1012                }
1013#ifdef CONFIG_NCPFS_STRONG              
1014                if ((!result) && (info_mask & DM_ATTRIBUTES))
1015                        NCP_FINFO(inode)->nwattr = info.attributes;
1016#endif
1017        }
1018        if (result)
1019                goto out;
1020
1021        setattr_copy(inode, attr);
1022        mark_inode_dirty(inode);
1023
1024out:
1025        if (result > 0)
1026                result = -EACCES;
1027        return result;
1028}
1029
1030static struct dentry *ncp_mount(struct file_system_type *fs_type,
1031        int flags, const char *dev_name, void *data)
1032{
1033        return mount_nodev(fs_type, flags, data, ncp_fill_super);
1034}
1035
1036static struct file_system_type ncp_fs_type = {
1037        .owner          = THIS_MODULE,
1038        .name           = "ncpfs",
1039        .mount          = ncp_mount,
1040        .kill_sb        = kill_anon_super,
1041        .fs_flags       = FS_BINARY_MOUNTDATA,
1042};
1043MODULE_ALIAS_FS("ncpfs");
1044
1045static int __init init_ncp_fs(void)
1046{
1047        int err;
1048        ncp_dbg(1, "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        ncp_dbg(1, "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