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),
  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        .follow_link    = page_follow_link_light,
 248        .put_link       = page_put_link,
 249        .setattr        = ncp_notify_change,
 250};
 251#endif
 252
 253/*
 254 * Get a new inode.
 255 */
 256struct inode * 
 257ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 258{
 259        struct inode *inode;
 260
 261        if (info == NULL) {
 262                pr_err("%s: info is NULL\n", __func__);
 263                return NULL;
 264        }
 265
 266        inode = new_inode(sb);
 267        if (inode) {
 268                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 269
 270                inode->i_mapping->backing_dev_info = sb->s_bdi;
 271                inode->i_ino = info->ino;
 272                ncp_set_attr(inode, info);
 273                if (S_ISREG(inode->i_mode)) {
 274                        inode->i_op = &ncp_file_inode_operations;
 275                        inode->i_fop = &ncp_file_operations;
 276                } else if (S_ISDIR(inode->i_mode)) {
 277                        inode->i_op = &ncp_dir_inode_operations;
 278                        inode->i_fop = &ncp_dir_operations;
 279#ifdef CONFIG_NCPFS_NFS_NS
 280                } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
 281                        init_special_inode(inode, inode->i_mode,
 282                                new_decode_dev(info->i.nfs.rdev));
 283#endif
 284#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 285                } else if (S_ISLNK(inode->i_mode)) {
 286                        inode->i_op = &ncp_symlink_inode_operations;
 287                        inode->i_data.a_ops = &ncp_symlink_aops;
 288#endif
 289                } else {
 290                        make_bad_inode(inode);
 291                }
 292                insert_inode_hash(inode);
 293        } else
 294                pr_err("%s: iget failed!\n", __func__);
 295        return inode;
 296}
 297
 298static void
 299ncp_evict_inode(struct inode *inode)
 300{
 301        truncate_inode_pages_final(&inode->i_data);
 302        clear_inode(inode);
 303
 304        if (S_ISDIR(inode->i_mode)) {
 305                ncp_dbg(2, "put directory %ld\n", inode->i_ino);
 306        }
 307
 308        if (ncp_make_closed(inode) != 0) {
 309                /* We can't do anything but complain. */
 310                pr_err("%s: could not close\n", __func__);
 311        }
 312}
 313
 314static void ncp_stop_tasks(struct ncp_server *server) {
 315        struct sock* sk = server->ncp_sock->sk;
 316
 317        lock_sock(sk);
 318        sk->sk_error_report = server->error_report;
 319        sk->sk_data_ready   = server->data_ready;
 320        sk->sk_write_space  = server->write_space;
 321        release_sock(sk);
 322        del_timer_sync(&server->timeout_tm);
 323
 324        flush_work(&server->rcv.tq);
 325        if (sk->sk_socket->type == SOCK_STREAM)
 326                flush_work(&server->tx.tq);
 327        else
 328                flush_work(&server->timeout_tq);
 329}
 330
 331static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
 332{
 333        struct ncp_server *server = NCP_SBP(root->d_sb);
 334        unsigned int tmp;
 335
 336        if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
 337                seq_printf(seq, ",uid=%u",
 338                           from_kuid_munged(&init_user_ns, server->m.uid));
 339        if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
 340                seq_printf(seq, ",gid=%u",
 341                           from_kgid_munged(&init_user_ns, server->m.gid));
 342        if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
 343                seq_printf(seq, ",owner=%u",
 344                           from_kuid_munged(&init_user_ns, server->m.mounted_uid));
 345        tmp = server->m.file_mode & S_IALLUGO;
 346        if (tmp != NCP_DEFAULT_FILE_MODE)
 347                seq_printf(seq, ",mode=0%o", tmp);
 348        tmp = server->m.dir_mode & S_IALLUGO;
 349        if (tmp != NCP_DEFAULT_DIR_MODE)
 350                seq_printf(seq, ",dirmode=0%o", tmp);
 351        if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
 352                tmp = server->m.time_out * 100 / HZ;
 353                seq_printf(seq, ",timeout=%u", tmp);
 354        }
 355        if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
 356                seq_printf(seq, ",retry=%u", server->m.retry_count);
 357        if (server->m.flags != 0)
 358                seq_printf(seq, ",flags=%lu", server->m.flags);
 359        if (server->m.wdog_pid != NULL)
 360                seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
 361
 362        return 0;
 363}
 364
 365static const struct ncp_option ncp_opts[] = {
 366        { "uid",        OPT_INT,        'u' },
 367        { "gid",        OPT_INT,        'g' },
 368        { "owner",      OPT_INT,        'o' },
 369        { "mode",       OPT_INT,        'm' },
 370        { "dirmode",    OPT_INT,        'd' },
 371        { "timeout",    OPT_INT,        't' },
 372        { "retry",      OPT_INT,        'r' },
 373        { "flags",      OPT_INT,        'f' },
 374        { "wdogpid",    OPT_INT,        'w' },
 375        { "ncpfd",      OPT_INT,        'n' },
 376        { "infofd",     OPT_INT,        'i' },  /* v5 */
 377        { "version",    OPT_INT,        'v' },
 378        { NULL,         0,              0 } };
 379
 380static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
 381        int optval;
 382        char *optarg;
 383        unsigned long optint;
 384        int version = 0;
 385        int ret;
 386
 387        data->flags = 0;
 388        data->int_flags = 0;
 389        data->mounted_uid = GLOBAL_ROOT_UID;
 390        data->wdog_pid = NULL;
 391        data->ncp_fd = ~0;
 392        data->time_out = NCP_DEFAULT_TIME_OUT;
 393        data->retry_count = NCP_DEFAULT_RETRY_COUNT;
 394        data->uid = GLOBAL_ROOT_UID;
 395        data->gid = GLOBAL_ROOT_GID;
 396        data->file_mode = NCP_DEFAULT_FILE_MODE;
 397        data->dir_mode = NCP_DEFAULT_DIR_MODE;
 398        data->info_fd = -1;
 399        data->mounted_vol[0] = 0;
 400        
 401        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
 402                ret = optval;
 403                if (ret < 0)
 404                        goto err;
 405                switch (optval) {
 406                        case 'u':
 407                                data->uid = make_kuid(current_user_ns(), optint);
 408                                if (!uid_valid(data->uid)) {
 409                                        ret = -EINVAL;
 410                                        goto err;
 411                                }
 412                                break;
 413                        case 'g':
 414                                data->gid = make_kgid(current_user_ns(), optint);
 415                                if (!gid_valid(data->gid)) {
 416                                        ret = -EINVAL;
 417                                        goto err;
 418                                }
 419                                break;
 420                        case 'o':
 421                                data->mounted_uid = make_kuid(current_user_ns(), optint);
 422                                if (!uid_valid(data->mounted_uid)) {
 423                                        ret = -EINVAL;
 424                                        goto err;
 425                                }
 426                                break;
 427                        case 'm':
 428                                data->file_mode = optint;
 429                                break;
 430                        case 'd':
 431                                data->dir_mode = optint;
 432                                break;
 433                        case 't':
 434                                data->time_out = optint;
 435                                break;
 436                        case 'r':
 437                                data->retry_count = optint;
 438                                break;
 439                        case 'f':
 440                                data->flags = optint;
 441                                break;
 442                        case 'w':
 443                                data->wdog_pid = find_get_pid(optint);
 444                                break;
 445                        case 'n':
 446                                data->ncp_fd = optint;
 447                                break;
 448                        case 'i':
 449                                data->info_fd = optint;
 450                                break;
 451                        case 'v':
 452                                ret = -ECHRNG;
 453                                if (optint < NCP_MOUNT_VERSION_V4)
 454                                        goto err;
 455                                if (optint > NCP_MOUNT_VERSION_V5)
 456                                        goto err;
 457                                version = optint;
 458                                break;
 459                        
 460                }
 461        }
 462        return 0;
 463err:
 464        put_pid(data->wdog_pid);
 465        data->wdog_pid = NULL;
 466        return ret;
 467}
 468
 469static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 470{
 471        struct ncp_mount_data_kernel data;
 472        struct ncp_server *server;
 473        struct inode *root_inode;
 474        struct socket *sock;
 475        int error;
 476        int default_bufsize;
 477#ifdef CONFIG_NCPFS_PACKET_SIGNING
 478        int options;
 479#endif
 480        struct ncp_entry_info finfo;
 481
 482        memset(&data, 0, sizeof(data));
 483        server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
 484        if (!server)
 485                return -ENOMEM;
 486        sb->s_fs_info = server;
 487
 488        error = -EFAULT;
 489        if (raw_data == NULL)
 490                goto out;
 491        switch (*(int*)raw_data) {
 492                case NCP_MOUNT_VERSION:
 493                        {
 494                                struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
 495
 496                                data.flags = md->flags;
 497                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
 498                                data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
 499                                data.wdog_pid = find_get_pid(md->wdog_pid);
 500                                data.ncp_fd = md->ncp_fd;
 501                                data.time_out = md->time_out;
 502                                data.retry_count = md->retry_count;
 503                                data.uid = make_kuid(current_user_ns(), md->uid);
 504                                data.gid = make_kgid(current_user_ns(), md->gid);
 505                                data.file_mode = md->file_mode;
 506                                data.dir_mode = md->dir_mode;
 507                                data.info_fd = -1;
 508                                memcpy(data.mounted_vol, md->mounted_vol,
 509                                        NCP_VOLNAME_LEN+1);
 510                        }
 511                        break;
 512                case NCP_MOUNT_VERSION_V4:
 513                        {
 514                                struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
 515
 516                                data.flags = md->flags;
 517                                data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
 518                                data.wdog_pid = find_get_pid(md->wdog_pid);
 519                                data.ncp_fd = md->ncp_fd;
 520                                data.time_out = md->time_out;
 521                                data.retry_count = md->retry_count;
 522                                data.uid = make_kuid(current_user_ns(), md->uid);
 523                                data.gid = make_kgid(current_user_ns(), md->gid);
 524                                data.file_mode = md->file_mode;
 525                                data.dir_mode = md->dir_mode;
 526                                data.info_fd = -1;
 527                        }
 528                        break;
 529                default:
 530                        error = -ECHRNG;
 531                        if (memcmp(raw_data, "vers", 4) == 0) {
 532                                error = ncp_parse_options(&data, raw_data);
 533                        }
 534                        if (error)
 535                                goto out;
 536                        break;
 537        }
 538        error = -EINVAL;
 539        if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
 540            !gid_valid(data.gid))
 541                goto out;
 542        sock = sockfd_lookup(data.ncp_fd, &error);
 543        if (!sock)
 544                goto out;
 545
 546        if (sock->type == SOCK_STREAM)
 547                default_bufsize = 0xF000;
 548        else
 549                default_bufsize = 1024;
 550
 551        sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
 552        sb->s_maxbytes = 0xFFFFFFFFU;
 553        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 554        sb->s_blocksize_bits = 10;
 555        sb->s_magic = NCP_SUPER_MAGIC;
 556        sb->s_op = &ncp_sops;
 557        sb->s_d_op = &ncp_dentry_operations;
 558        sb->s_bdi = &server->bdi;
 559
 560        server = NCP_SBP(sb);
 561        memset(server, 0, sizeof(*server));
 562
 563        error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
 564        if (error)
 565                goto out_fput;
 566
 567        server->ncp_sock = sock;
 568        
 569        if (data.info_fd != -1) {
 570                struct socket *info_sock = sockfd_lookup(data.info_fd, &error);
 571                if (!info_sock)
 572                        goto out_bdi;
 573                server->info_sock = info_sock;
 574                error = -EBADFD;
 575                if (info_sock->type != SOCK_STREAM)
 576                        goto out_fput2;
 577        }
 578
 579/*      server->lock = 0;       */
 580        mutex_init(&server->mutex);
 581        server->packet = NULL;
 582/*      server->buffer_size = 0;        */
 583/*      server->conn_status = 0;        */
 584/*      server->root_dentry = NULL;     */
 585/*      server->root_setuped = 0;       */
 586        mutex_init(&server->root_setup_lock);
 587#ifdef CONFIG_NCPFS_PACKET_SIGNING
 588/*      server->sign_wanted = 0;        */
 589/*      server->sign_active = 0;        */
 590#endif
 591        init_rwsem(&server->auth_rwsem);
 592        server->auth.auth_type = NCP_AUTH_NONE;
 593/*      server->auth.object_name_len = 0;       */
 594/*      server->auth.object_name = NULL;        */
 595/*      server->auth.object_type = 0;           */
 596/*      server->priv.len = 0;                   */
 597/*      server->priv.data = NULL;               */
 598
 599        server->m = data;
 600        /* Although anything producing this is buggy, it happens
 601           now because of PATH_MAX changes.. */
 602        if (server->m.time_out < 1) {
 603                server->m.time_out = 10;
 604                pr_info("You need to recompile your ncpfs utils..\n");
 605        }
 606        server->m.time_out = server->m.time_out * HZ / 100;
 607        server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
 608        server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
 609
 610#ifdef CONFIG_NCPFS_NLS
 611        /* load the default NLS charsets */
 612        server->nls_vol = load_nls_default();
 613        server->nls_io = load_nls_default();
 614#endif /* CONFIG_NCPFS_NLS */
 615
 616        atomic_set(&server->dentry_ttl, 0);     /* no caching */
 617
 618        INIT_LIST_HEAD(&server->tx.requests);
 619        mutex_init(&server->rcv.creq_mutex);
 620        server->tx.creq         = NULL;
 621        server->rcv.creq        = NULL;
 622
 623        init_timer(&server->timeout_tm);
 624#undef NCP_PACKET_SIZE
 625#define NCP_PACKET_SIZE 131072
 626        error = -ENOMEM;
 627        server->packet_size = NCP_PACKET_SIZE;
 628        server->packet = vmalloc(NCP_PACKET_SIZE);
 629        if (server->packet == NULL)
 630                goto out_nls;
 631        server->txbuf = vmalloc(NCP_PACKET_SIZE);
 632        if (server->txbuf == NULL)
 633                goto out_packet;
 634        server->rxbuf = vmalloc(NCP_PACKET_SIZE);
 635        if (server->rxbuf == NULL)
 636                goto out_txbuf;
 637
 638        lock_sock(sock->sk);
 639        server->data_ready      = sock->sk->sk_data_ready;
 640        server->write_space     = sock->sk->sk_write_space;
 641        server->error_report    = sock->sk->sk_error_report;
 642        sock->sk->sk_user_data  = server;
 643        sock->sk->sk_data_ready   = ncp_tcp_data_ready;
 644        sock->sk->sk_error_report = ncp_tcp_error_report;
 645        if (sock->type == SOCK_STREAM) {
 646                server->rcv.ptr = (unsigned char*)&server->rcv.buf;
 647                server->rcv.len = 10;
 648                server->rcv.state = 0;
 649                INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
 650                INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
 651                sock->sk->sk_write_space = ncp_tcp_write_space;
 652        } else {
 653                INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
 654                INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
 655                server->timeout_tm.data = (unsigned long)server;
 656                server->timeout_tm.function = ncpdgram_timeout_call;
 657        }
 658        release_sock(sock->sk);
 659
 660        ncp_lock_server(server);
 661        error = ncp_connect(server);
 662        ncp_unlock_server(server);
 663        if (error < 0)
 664                goto out_rxbuf;
 665        ncp_dbg(1, "NCP_SBP(sb) = %p\n", NCP_SBP(sb));
 666
 667        error = -EMSGSIZE;      /* -EREMOTESIDEINCOMPATIBLE */
 668#ifdef CONFIG_NCPFS_PACKET_SIGNING
 669        if (ncp_negotiate_size_and_options(server, default_bufsize,
 670                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
 671        {
 672                if (options != NCP_DEFAULT_OPTIONS)
 673                {
 674                        if (ncp_negotiate_size_and_options(server, 
 675                                default_bufsize,
 676                                options & 2, 
 677                                &(server->buffer_size), &options) != 0)
 678                                
 679                        {
 680                                goto out_disconnect;
 681                        }
 682                }
 683                ncp_lock_server(server);
 684                if (options & 2)
 685                        server->sign_wanted = 1;
 686                ncp_unlock_server(server);
 687        }
 688        else 
 689#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
 690        if (ncp_negotiate_buffersize(server, default_bufsize,
 691                                     &(server->buffer_size)) != 0)
 692                goto out_disconnect;
 693        ncp_dbg(1, "bufsize = %d\n", server->buffer_size);
 694
 695        memset(&finfo, 0, sizeof(finfo));
 696        finfo.i.attributes      = aDIR;
 697        finfo.i.dataStreamSize  = 0;    /* ignored */
 698        finfo.i.dirEntNum       = 0;
 699        finfo.i.DosDirNum       = 0;
 700#ifdef CONFIG_NCPFS_SMALLDOS
 701        finfo.i.NSCreator       = NW_NS_DOS;
 702#endif
 703        finfo.volume            = NCP_NUMBER_OF_VOLUMES;
 704        /* set dates of mountpoint to Jan 1, 1986; 00:00 */
 705        finfo.i.creationTime    = finfo.i.modifyTime
 706                                = cpu_to_le16(0x0000);
 707        finfo.i.creationDate    = finfo.i.modifyDate
 708                                = finfo.i.lastAccessDate
 709                                = cpu_to_le16(0x0C21);
 710        finfo.i.nameLen         = 0;
 711        finfo.i.entryName[0]    = '\0';
 712
 713        finfo.opened            = 0;
 714        finfo.ino               = 2;    /* tradition */
 715
 716        server->name_space[finfo.volume] = NW_NS_DOS;
 717
 718        error = -ENOMEM;
 719        root_inode = ncp_iget(sb, &finfo);
 720        if (!root_inode)
 721                goto out_disconnect;
 722        ncp_dbg(1, "root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
 723        sb->s_root = d_make_root(root_inode);
 724        if (!sb->s_root)
 725                goto out_disconnect;
 726        return 0;
 727
 728out_disconnect:
 729        ncp_lock_server(server);
 730        ncp_disconnect(server);
 731        ncp_unlock_server(server);
 732out_rxbuf:
 733        ncp_stop_tasks(server);
 734        vfree(server->rxbuf);
 735out_txbuf:
 736        vfree(server->txbuf);
 737out_packet:
 738        vfree(server->packet);
 739out_nls:
 740#ifdef CONFIG_NCPFS_NLS
 741        unload_nls(server->nls_io);
 742        unload_nls(server->nls_vol);
 743#endif
 744        mutex_destroy(&server->rcv.creq_mutex);
 745        mutex_destroy(&server->root_setup_lock);
 746        mutex_destroy(&server->mutex);
 747out_fput2:
 748        if (server->info_sock)
 749                sockfd_put(server->info_sock);
 750out_bdi:
 751        bdi_destroy(&server->bdi);
 752out_fput:
 753        sockfd_put(sock);
 754out:
 755        put_pid(data.wdog_pid);
 756        sb->s_fs_info = NULL;
 757        kfree(server);
 758        return error;
 759}
 760
 761static void delayed_free(struct rcu_head *p)
 762{
 763        struct ncp_server *server = container_of(p, struct ncp_server, rcu);
 764#ifdef CONFIG_NCPFS_NLS
 765        /* unload the NLS charsets */
 766        unload_nls(server->nls_vol);
 767        unload_nls(server->nls_io);
 768#endif /* CONFIG_NCPFS_NLS */
 769        kfree(server);
 770}
 771
 772static void ncp_put_super(struct super_block *sb)
 773{
 774        struct ncp_server *server = NCP_SBP(sb);
 775
 776        ncp_lock_server(server);
 777        ncp_disconnect(server);
 778        ncp_unlock_server(server);
 779
 780        ncp_stop_tasks(server);
 781
 782        mutex_destroy(&server->rcv.creq_mutex);
 783        mutex_destroy(&server->root_setup_lock);
 784        mutex_destroy(&server->mutex);
 785
 786        if (server->info_sock)
 787                sockfd_put(server->info_sock);
 788        sockfd_put(server->ncp_sock);
 789        kill_pid(server->m.wdog_pid, SIGTERM, 1);
 790        put_pid(server->m.wdog_pid);
 791
 792        bdi_destroy(&server->bdi);
 793        kfree(server->priv.data);
 794        kfree(server->auth.object_name);
 795        vfree(server->rxbuf);
 796        vfree(server->txbuf);
 797        vfree(server->packet);
 798        call_rcu(&server->rcu, delayed_free);
 799}
 800
 801static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
 802{
 803        struct dentry* d;
 804        struct inode* i;
 805        struct ncp_inode_info* ni;
 806        struct ncp_server* s;
 807        struct ncp_volume_info vi;
 808        struct super_block *sb = dentry->d_sb;
 809        int err;
 810        __u8 dh;
 811        
 812        d = sb->s_root;
 813        if (!d) {
 814                goto dflt;
 815        }
 816        i = d->d_inode;
 817        if (!i) {
 818                goto dflt;
 819        }
 820        ni = NCP_FINFO(i);
 821        if (!ni) {
 822                goto dflt;
 823        }
 824        s = NCP_SBP(sb);
 825        if (!s) {
 826                goto dflt;
 827        }
 828        if (!s->m.mounted_vol[0]) {
 829                goto dflt;
 830        }
 831
 832        err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
 833        if (err) {
 834                goto dflt;
 835        }
 836        err = ncp_get_directory_info(s, dh, &vi);
 837        ncp_dirhandle_free(s, dh);
 838        if (err) {
 839                goto dflt;
 840        }
 841        buf->f_type = NCP_SUPER_MAGIC;
 842        buf->f_bsize = vi.sectors_per_block * 512;
 843        buf->f_blocks = vi.total_blocks;
 844        buf->f_bfree = vi.free_blocks;
 845        buf->f_bavail = vi.free_blocks;
 846        buf->f_files = vi.total_dir_entries;
 847        buf->f_ffree = vi.available_dir_entries;
 848        buf->f_namelen = 12;
 849        return 0;
 850
 851        /* We cannot say how much disk space is left on a mounted
 852           NetWare Server, because free space is distributed over
 853           volumes, and the current user might have disk quotas. So
 854           free space is not that simple to determine. Our decision
 855           here is to err conservatively. */
 856
 857dflt:;
 858        buf->f_type = NCP_SUPER_MAGIC;
 859        buf->f_bsize = NCP_BLOCK_SIZE;
 860        buf->f_blocks = 0;
 861        buf->f_bfree = 0;
 862        buf->f_bavail = 0;
 863        buf->f_namelen = 12;
 864        return 0;
 865}
 866
 867int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
 868{
 869        struct inode *inode = dentry->d_inode;
 870        int result = 0;
 871        __le32 info_mask;
 872        struct nw_modify_dos_info info;
 873        struct ncp_server *server;
 874
 875        result = -EIO;
 876
 877        server = NCP_SERVER(inode);
 878        if (!server)    /* How this could happen? */
 879                goto out;
 880
 881        result = -EPERM;
 882        if (IS_DEADDIR(dentry->d_inode))
 883                goto out;
 884
 885        /* ageing the dentry to force validation */
 886        ncp_age_dentry(server, dentry);
 887
 888        result = inode_change_ok(inode, attr);
 889        if (result < 0)
 890                goto out;
 891
 892        result = -EPERM;
 893        if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
 894                goto out;
 895
 896        if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
 897                goto out;
 898
 899        if (((attr->ia_valid & ATTR_MODE) &&
 900             (attr->ia_mode &
 901              ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
 902                goto out;
 903
 904        info_mask = 0;
 905        memset(&info, 0, sizeof(info));
 906
 907#if 1 
 908        if ((attr->ia_valid & ATTR_MODE) != 0)
 909        {
 910                umode_t newmode = attr->ia_mode;
 911
 912                info_mask |= DM_ATTRIBUTES;
 913
 914                if (S_ISDIR(inode->i_mode)) {
 915                        newmode &= server->m.dir_mode;
 916                } else {
 917#ifdef CONFIG_NCPFS_EXTRAS                      
 918                        if (server->m.flags & NCP_MOUNT_EXTRAS) {
 919                                /* any non-default execute bit set */
 920                                if (newmode & ~server->m.file_mode & S_IXUGO)
 921                                        info.attributes |= aSHARED | aSYSTEM;
 922                                /* read for group/world and not in default file_mode */
 923                                else if (newmode & ~server->m.file_mode & S_IRUGO)
 924                                        info.attributes |= aSHARED;
 925                        } else
 926#endif
 927                                newmode &= server->m.file_mode;                 
 928                }
 929                if (newmode & S_IWUGO)
 930                        info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 931                else
 932                        info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 933
 934#ifdef CONFIG_NCPFS_NFS_NS
 935                if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
 936                        result = ncp_modify_nfs_info(server,
 937                                                     NCP_FINFO(inode)->volNumber,
 938                                                     NCP_FINFO(inode)->dirEntNum,
 939                                                     attr->ia_mode, 0);
 940                        if (result != 0)
 941                                goto out;
 942                        info.attributes &= ~(aSHARED | aSYSTEM);
 943                        {
 944                                /* mark partial success */
 945                                struct iattr tmpattr;
 946                                
 947                                tmpattr.ia_valid = ATTR_MODE;
 948                                tmpattr.ia_mode = attr->ia_mode;
 949
 950                                setattr_copy(inode, &tmpattr);
 951                                mark_inode_dirty(inode);
 952                        }
 953                }
 954#endif
 955        }
 956#endif
 957
 958        /* Do SIZE before attributes, otherwise mtime together with size does not work...
 959         */
 960        if ((attr->ia_valid & ATTR_SIZE) != 0) {
 961                int written;
 962
 963                ncp_dbg(1, "trying to change size to %llu\n", attr->ia_size);
 964
 965                if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
 966                        result = -EACCES;
 967                        goto out;
 968                }
 969                ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
 970                          attr->ia_size, 0, "", &written);
 971
 972                /* According to ndir, the changes only take effect after
 973                   closing the file */
 974                ncp_inode_close(inode);
 975                result = ncp_make_closed(inode);
 976                if (result)
 977                        goto out;
 978
 979                if (attr->ia_size != i_size_read(inode)) {
 980                        truncate_setsize(inode, attr->ia_size);
 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};
1044MODULE_ALIAS_FS("ncpfs");
1045
1046static int __init init_ncp_fs(void)
1047{
1048        int err;
1049        ncp_dbg(1, "called\n");
1050
1051        err = init_inodecache();
1052        if (err)
1053                goto out1;
1054        err = register_filesystem(&ncp_fs_type);
1055        if (err)
1056                goto out;
1057        return 0;
1058out:
1059        destroy_inodecache();
1060out1:
1061        return err;
1062}
1063
1064static void __exit exit_ncp_fs(void)
1065{
1066        ncp_dbg(1, "called\n");
1067        unregister_filesystem(&ncp_fs_type);
1068        destroy_inodecache();
1069}
1070
1071module_init(init_ncp_fs)
1072module_exit(exit_ncp_fs)
1073MODULE_LICENSE("GPL");
1074