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