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/uaccess.h>
  15#include <asm/byteorder.h>
  16
  17#include <linux/time.h>
  18#include <linux/kernel.h>
  19#include <linux/mm.h>
  20#include <linux/string.h>
  21#include <linux/stat.h>
  22#include <linux/errno.h>
  23#include <linux/file.h>
  24#include <linux/fcntl.h>
  25#include <linux/slab.h>
  26#include <linux/vmalloc.h>
  27#include <linux/init.h>
  28#include <linux/vfs.h>
  29#include <linux/mount.h>
  30#include <linux/seq_file.h>
  31#include <linux/namei.h>
  32
  33#include <net/sock.h>
  34
  35#include "ncp_fs.h"
  36#include "getopt.h"
  37
  38#define NCP_DEFAULT_FILE_MODE 0600
  39#define NCP_DEFAULT_DIR_MODE 0700
  40#define NCP_DEFAULT_TIME_OUT 10
  41#define NCP_DEFAULT_RETRY_COUNT 20
  42
  43static void ncp_evict_inode(struct inode *);
  44static void ncp_put_super(struct super_block *);
  45static int  ncp_statfs(struct dentry *, struct kstatfs *);
  46static int  ncp_show_options(struct seq_file *, struct dentry *);
  47
  48static struct kmem_cache * ncp_inode_cachep;
  49
  50static struct inode *ncp_alloc_inode(struct super_block *sb)
  51{
  52        struct ncp_inode_info *ei;
  53        ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
  54        if (!ei)
  55                return NULL;
  56        return &ei->vfs_inode;
  57}
  58
  59static void ncp_i_callback(struct rcu_head *head)
  60{
  61        struct inode *inode = container_of(head, struct inode, i_rcu);
  62        kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
  63}
  64
  65static void ncp_destroy_inode(struct inode *inode)
  66{
  67        call_rcu(&inode->i_rcu, ncp_i_callback);
  68}
  69
  70static void init_once(void *foo)
  71{
  72        struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
  73
  74        mutex_init(&ei->open_mutex);
  75        inode_init_once(&ei->vfs_inode);
  76}
  77
  78static int init_inodecache(void)
  79{
  80        ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
  81                                             sizeof(struct ncp_inode_info),
  82                                             0, (SLAB_RECLAIM_ACCOUNT|
  83                                                SLAB_MEM_SPREAD),
  84                                             init_once);
  85        if (ncp_inode_cachep == NULL)
  86                return -ENOMEM;
  87        return 0;
  88}
  89
  90static void destroy_inodecache(void)
  91{
  92        /*
  93         * Make sure all delayed rcu free inodes are flushed before we
  94         * destroy cache.
  95         */
  96        rcu_barrier();
  97        kmem_cache_destroy(ncp_inode_cachep);
  98}
  99
 100static int ncp_remount(struct super_block *sb, int *flags, char* data)
 101{
 102        *flags |= MS_NODIRATIME;
 103        return 0;
 104}
 105
 106static const struct super_operations ncp_sops =
 107{
 108        .alloc_inode    = ncp_alloc_inode,
 109        .destroy_inode  = ncp_destroy_inode,
 110        .drop_inode     = generic_delete_inode,
 111        .evict_inode    = ncp_evict_inode,
 112        .put_super      = ncp_put_super,
 113        .statfs         = ncp_statfs,
 114        .remount_fs     = ncp_remount,
 115        .show_options   = ncp_show_options,
 116};
 117
 118/*
 119 * Fill in the ncpfs-specific information in the inode.
 120 */
 121static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
 122{
 123        NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
 124        NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
 125        NCP_FINFO(inode)->volNumber = nwinfo->volume;
 126}
 127
 128void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
 129{
 130        ncp_update_dirent(inode, nwinfo);
 131        NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
 132        NCP_FINFO(inode)->access = nwinfo->access;
 133        memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
 134                        sizeof(nwinfo->file_handle));
 135        DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
 136                nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
 137                NCP_FINFO(inode)->dirEntNum);
 138}
 139
 140static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
 141{
 142        /* NFS namespace mode overrides others if it's set. */
 143        DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
 144                nwi->entryName, nwi->nfs.mode);
 145        if (nwi->nfs.mode) {
 146                /* XXX Security? */
 147                inode->i_mode = nwi->nfs.mode;
 148        }
 149
 150        inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
 151
 152        inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
 153        inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
 154        inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
 155        inode->i_atime.tv_nsec = 0;
 156        inode->i_mtime.tv_nsec = 0;
 157        inode->i_ctime.tv_nsec = 0;
 158}
 159
 160static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
 161{
 162        struct nw_info_struct *nwi = &nwinfo->i;
 163        struct ncp_server *server = NCP_SERVER(inode);
 164
 165        if (nwi->attributes & aDIR) {
 166                inode->i_mode = server->m.dir_mode;
 167                /* for directories dataStreamSize seems to be some
 168                   Object ID ??? */
 169                i_size_write(inode, NCP_BLOCK_SIZE);
 170        } else {
 171                u32 size;
 172
 173                inode->i_mode = server->m.file_mode;
 174                size = le32_to_cpu(nwi->dataStreamSize);
 175                i_size_write(inode, size);
 176#ifdef CONFIG_NCPFS_EXTRAS
 177                if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
 178                 && (nwi->attributes & aSHARED)) {
 179                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
 180                                case aHIDDEN:
 181                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
 182                                                if (/* (size >= NCP_MIN_SYMLINK_SIZE)
 183                                                 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
 184                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
 185                                                        NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
 186                                                        break;
 187                                                }
 188                                        }
 189                                        /* FALLTHROUGH */
 190                                case 0:
 191                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
 192                                                inode->i_mode |= S_IRUGO;
 193                                        break;
 194                                case aSYSTEM:
 195                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
 196                                                inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
 197                                        break;
 198                                /* case aSYSTEM|aHIDDEN: */
 199                                default:
 200                                        /* reserved combination */
 201                                        break;
 202                        }
 203                }
 204#endif
 205        }
 206        if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
 207}
 208
 209void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
 210{
 211        NCP_FINFO(inode)->flags = 0;
 212        if (!atomic_read(&NCP_FINFO(inode)->opened)) {
 213                NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
 214                ncp_update_attrs(inode, nwinfo);
 215        }
 216
 217        ncp_update_dates(inode, &nwinfo->i);
 218        ncp_update_dirent(inode, nwinfo);
 219}
 220
 221/*
 222 * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
 223 */
 224static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 225{
 226        struct ncp_server *server = NCP_SERVER(inode);
 227
 228        NCP_FINFO(inode)->flags = 0;
 229        
 230        ncp_update_attrs(inode, nwinfo);
 231
 232        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 233
 234        set_nlink(inode, 1);
 235        inode->i_uid = server->m.uid;
 236        inode->i_gid = server->m.gid;
 237
 238        ncp_update_dates(inode, &nwinfo->i);
 239        ncp_update_inode(inode, nwinfo);
 240}
 241
 242#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 243static const struct inode_operations ncp_symlink_inode_operations = {
 244        .readlink       = generic_readlink,
 245        .follow_link    = page_follow_link_light,
 246        .put_link       = page_put_link,
 247        .setattr        = ncp_notify_change,
 248};
 249#endif
 250
 251/*
 252 * Get a new inode.
 253 */
 254struct inode * 
 255ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 256{
 257        struct inode *inode;
 258
 259        if (info == NULL) {
 260                printk(KERN_ERR "ncp_iget: info is NULL\n");
 261                return NULL;
 262        }
 263
 264        inode = new_inode(sb);
 265        if (inode) {
 266                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
 267
 268                inode->i_mapping->backing_dev_info = sb->s_bdi;
 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->i_data.a_ops = &ncp_symlink_aops;
 286#endif
 287                } else {
 288                        make_bad_inode(inode);
 289                }
 290                insert_inode_hash(inode);
 291        } else
 292                printk(KERN_ERR "ncp_iget: iget failed!\n");
 293        return inode;
 294}
 295
 296static void
 297ncp_evict_inode(struct inode *inode)
 298{
 299        truncate_inode_pages(&inode->i_data, 0);
 300        clear_inode(inode);
 301
 302        if (S_ISDIR(inode->i_mode)) {
 303                DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
 304        }
 305
 306        if (ncp_make_closed(inode) != 0) {
 307                /* We can't do anything but complain. */
 308                printk(KERN_ERR "ncp_evict_inode: could not close\n");
 309        }
 310}
 311
 312static void ncp_stop_tasks(struct ncp_server *server) {
 313        struct sock* sk = server->ncp_sock->sk;
 314
 315        lock_sock(sk);
 316        sk->sk_error_report = server->error_report;
 317        sk->sk_data_ready   = server->data_ready;
 318        sk->sk_write_space  = server->write_space;
 319        release_sock(sk);
 320        del_timer_sync(&server->timeout_tm);
 321
 322        flush_work(&server->rcv.tq);
 323        if (sk->sk_socket->type == SOCK_STREAM)
 324                flush_work(&server->tx.tq);
 325        else
 326                flush_work(&server->timeout_tq);
 327}
 328
 329static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
 330{
 331        struct ncp_server *server = NCP_SBP(root->d_sb);
 332        unsigned int tmp;
 333
 334        if (server->m.uid != 0)
 335                seq_printf(seq, ",uid=%u", server->m.uid);
 336        if (server->m.gid != 0)
 337                seq_printf(seq, ",gid=%u", server->m.gid);
 338        if (server->m.mounted_uid != 0)
 339                seq_printf(seq, ",owner=%u", server->m.mounted_uid);
 340        tmp = server->m.file_mode & S_IALLUGO;
 341        if (tmp != NCP_DEFAULT_FILE_MODE)
 342                seq_printf(seq, ",mode=0%o", tmp);
 343        tmp = server->m.dir_mode & S_IALLUGO;
 344        if (tmp != NCP_DEFAULT_DIR_MODE)
 345                seq_printf(seq, ",dirmode=0%o", tmp);
 346        if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
 347                tmp = server->m.time_out * 100 / HZ;
 348                seq_printf(seq, ",timeout=%u", tmp);
 349        }
 350        if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
 351                seq_printf(seq, ",retry=%u", server->m.retry_count);
 352        if (server->m.flags != 0)
 353                seq_printf(seq, ",flags=%lu", server->m.flags);
 354        if (server->m.wdog_pid != NULL)
 355                seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
 356
 357        return 0;
 358}
 359
 360static const struct ncp_option ncp_opts[] = {
 361        { "uid",        OPT_INT,        'u' },
 362        { "gid",        OPT_INT,        'g' },
 363        { "owner",      OPT_INT,        'o' },
 364        { "mode",       OPT_INT,        'm' },
 365        { "dirmode",    OPT_INT,        'd' },
 366        { "timeout",    OPT_INT,        't' },
 367        { "retry",      OPT_INT,        'r' },
 368        { "flags",      OPT_INT,        'f' },
 369        { "wdogpid",    OPT_INT,        'w' },
 370        { "ncpfd",      OPT_INT,        'n' },
 371        { "infofd",     OPT_INT,        'i' },  /* v5 */
 372        { "version",    OPT_INT,        'v' },
 373        { NULL,         0,              0 } };
 374
 375static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
 376        int optval;
 377        char *optarg;
 378        unsigned long optint;
 379        int version = 0;
 380        int ret;
 381
 382        data->flags = 0;
 383        data->int_flags = 0;
 384        data->mounted_uid = 0;
 385        data->wdog_pid = NULL;
 386        data->ncp_fd = ~0;
 387        data->time_out = NCP_DEFAULT_TIME_OUT;
 388        data->retry_count = NCP_DEFAULT_RETRY_COUNT;
 389        data->uid = 0;
 390        data->gid = 0;
 391        data->file_mode = NCP_DEFAULT_FILE_MODE;
 392        data->dir_mode = NCP_DEFAULT_DIR_MODE;
 393        data->info_fd = -1;
 394        data->mounted_vol[0] = 0;
 395        
 396        while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
 397                ret = optval;
 398                if (ret < 0)
 399                        goto err;
 400                switch (optval) {
 401                        case 'u':
 402                                data->uid = optint;
 403                                break;
 404                        case 'g':
 405                                data->gid = optint;
 406                                break;
 407                        case 'o':
 408                                data->mounted_uid = optint;
 409                                break;
 410                        case 'm':
 411                                data->file_mode = optint;
 412                                break;
 413                        case 'd':
 414                                data->dir_mode = optint;
 415                                break;
 416                        case 't':
 417                                data->time_out = optint;
 418                                break;
 419                        case 'r':
 420                                data->retry_count = optint;
 421                                break;
 422                        case 'f':
 423                                data->flags = optint;
 424                                break;
 425                        case 'w':
 426                                data->wdog_pid = find_get_pid(optint);
 427                                break;
 428                        case 'n':
 429                                data->ncp_fd = optint;
 430                                break;
 431                        case 'i':
 432                                data->info_fd = optint;
 433                                break;
 434                        case 'v':
 435                                ret = -ECHRNG;
 436                                if (optint < NCP_MOUNT_VERSION_V4)
 437                                        goto err;
 438                                if (optint > NCP_MOUNT_VERSION_V5)
 439                                        goto err;
 440                                version = optint;
 441                                break;
 442                        
 443                }
 444        }
 445        return 0;
 446err:
 447        put_pid(data->wdog_pid);
 448        data->wdog_pid = NULL;
 449        return ret;
 450}
 451
 452static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 453{
 454        struct ncp_mount_data_kernel data;
 455        struct ncp_server *server;
 456        struct file *ncp_filp;
 457        struct inode *root_inode;
 458        struct inode *sock_inode;
 459        struct socket *sock;
 460        int error;
 461        int default_bufsize;
 462#ifdef CONFIG_NCPFS_PACKET_SIGNING
 463        int options;
 464#endif
 465        struct ncp_entry_info finfo;
 466
 467        memset(&data, 0, sizeof(data));
 468        server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
 469        if (!server)
 470                return -ENOMEM;
 471        sb->s_fs_info = server;
 472
 473        error = -EFAULT;
 474        if (raw_data == NULL)
 475                goto out;
 476        switch (*(int*)raw_data) {
 477                case NCP_MOUNT_VERSION:
 478                        {
 479                                struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
 480
 481                                data.flags = md->flags;
 482                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
 483                                data.mounted_uid = md->mounted_uid;
 484                                data.wdog_pid = find_get_pid(md->wdog_pid);
 485                                data.ncp_fd = md->ncp_fd;
 486                                data.time_out = md->time_out;
 487                                data.retry_count = md->retry_count;
 488                                data.uid = md->uid;
 489                                data.gid = md->gid;
 490                                data.file_mode = md->file_mode;
 491                                data.dir_mode = md->dir_mode;
 492                                data.info_fd = -1;
 493                                memcpy(data.mounted_vol, md->mounted_vol,
 494                                        NCP_VOLNAME_LEN+1);
 495                        }
 496                        break;
 497                case NCP_MOUNT_VERSION_V4:
 498                        {
 499                                struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
 500
 501                                data.flags = md->flags;
 502                                data.mounted_uid = md->mounted_uid;
 503                                data.wdog_pid = find_get_pid(md->wdog_pid);
 504                                data.ncp_fd = md->ncp_fd;
 505                                data.time_out = md->time_out;
 506                                data.retry_count = md->retry_count;
 507                                data.uid = md->uid;
 508                                data.gid = md->gid;
 509                                data.file_mode = md->file_mode;
 510                                data.dir_mode = md->dir_mode;
 511                                data.info_fd = -1;
 512                        }
 513                        break;
 514                default:
 515                        error = -ECHRNG;
 516                        if (memcmp(raw_data, "vers", 4) == 0) {
 517                                error = ncp_parse_options(&data, raw_data);
 518                        }
 519                        if (error)
 520                                goto out;
 521                        break;
 522        }
 523        error = -EBADF;
 524        ncp_filp = fget(data.ncp_fd);
 525        if (!ncp_filp)
 526                goto out;
 527        error = -ENOTSOCK;
 528        sock_inode = ncp_filp->f_path.dentry->d_inode;
 529        if (!S_ISSOCK(sock_inode->i_mode))
 530                goto out_fput;
 531        sock = SOCKET_I(sock_inode);
 532        if (!sock)
 533                goto out_fput;
 534                
 535        if (sock->type == SOCK_STREAM)
 536                default_bufsize = 0xF000;
 537        else
 538                default_bufsize = 1024;
 539
 540        sb->s_flags |= MS_NODIRATIME;   /* probably even noatime */
 541        sb->s_maxbytes = 0xFFFFFFFFU;
 542        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 543        sb->s_blocksize_bits = 10;
 544        sb->s_magic = NCP_SUPER_MAGIC;
 545        sb->s_op = &ncp_sops;
 546        sb->s_d_op = &ncp_dentry_operations;
 547        sb->s_bdi = &server->bdi;
 548
 549        server = NCP_SBP(sb);
 550        memset(server, 0, sizeof(*server));
 551
 552        error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
 553        if (error)
 554                goto out_fput;
 555
 556        server->ncp_filp = ncp_filp;
 557        server->ncp_sock = sock;
 558        
 559        if (data.info_fd != -1) {
 560                struct socket *info_sock;
 561
 562                error = -EBADF;
 563                server->info_filp = fget(data.info_fd);
 564                if (!server->info_filp)
 565                        goto out_bdi;
 566                error = -ENOTSOCK;
 567                sock_inode = server->info_filp->f_path.dentry->d_inode;
 568                if (!S_ISSOCK(sock_inode->i_mode))
 569                        goto out_fput2;
 570                info_sock = SOCKET_I(sock_inode);
 571                if (!info_sock)
 572                        goto out_fput2;
 573                error = -EBADFD;
 574                if (info_sock->type != SOCK_STREAM)
 575                        goto out_fput2;
 576                server->info_sock = info_sock;
 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                printk(KERN_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        DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) 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        DPRINTK("ncpfs: 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        DPRINTK("ncp_fill_super: 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_filp)
 749                fput(server->info_filp);
 750out_bdi:
 751        bdi_destroy(&server->bdi);
 752out_fput:
 753        /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
 754         * 
 755         * The previously used put_filp(ncp_filp); was bogus, since
 756         * it doesn't perform proper unlocking.
 757         */
 758        fput(ncp_filp);
 759out:
 760        put_pid(data.wdog_pid);
 761        sb->s_fs_info = NULL;
 762        kfree(server);
 763        return error;
 764}
 765
 766static void ncp_put_super(struct super_block *sb)
 767{
 768        struct ncp_server *server = NCP_SBP(sb);
 769
 770        ncp_lock_server(server);
 771        ncp_disconnect(server);
 772        ncp_unlock_server(server);
 773
 774        ncp_stop_tasks(server);
 775
 776#ifdef CONFIG_NCPFS_NLS
 777        /* unload the NLS charsets */
 778        unload_nls(server->nls_vol);
 779        unload_nls(server->nls_io);
 780#endif /* CONFIG_NCPFS_NLS */
 781        mutex_destroy(&server->rcv.creq_mutex);
 782        mutex_destroy(&server->root_setup_lock);
 783        mutex_destroy(&server->mutex);
 784
 785        if (server->info_filp)
 786                fput(server->info_filp);
 787        fput(server->ncp_filp);
 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        sb->s_fs_info = NULL;
 798        kfree(server);
 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        /* ageing the dentry to force validation */
 882        ncp_age_dentry(server, dentry);
 883
 884        result = inode_change_ok(inode, attr);
 885        if (result < 0)
 886                goto out;
 887
 888        result = -EPERM;
 889        if (((attr->ia_valid & ATTR_UID) &&
 890             (attr->ia_uid != server->m.uid)))
 891                goto out;
 892
 893        if (((attr->ia_valid & ATTR_GID) &&
 894             (attr->ia_gid != server->m.gid)))
 895                goto out;
 896
 897        if (((attr->ia_valid & ATTR_MODE) &&
 898             (attr->ia_mode &
 899              ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
 900                goto out;
 901
 902        info_mask = 0;
 903        memset(&info, 0, sizeof(info));
 904
 905#if 1 
 906        if ((attr->ia_valid & ATTR_MODE) != 0)
 907        {
 908                umode_t newmode = attr->ia_mode;
 909
 910                info_mask |= DM_ATTRIBUTES;
 911
 912                if (S_ISDIR(inode->i_mode)) {
 913                        newmode &= server->m.dir_mode;
 914                } else {
 915#ifdef CONFIG_NCPFS_EXTRAS                      
 916                        if (server->m.flags & NCP_MOUNT_EXTRAS) {
 917                                /* any non-default execute bit set */
 918                                if (newmode & ~server->m.file_mode & S_IXUGO)
 919                                        info.attributes |= aSHARED | aSYSTEM;
 920                                /* read for group/world and not in default file_mode */
 921                                else if (newmode & ~server->m.file_mode & S_IRUGO)
 922                                        info.attributes |= aSHARED;
 923                        } else
 924#endif
 925                                newmode &= server->m.file_mode;                 
 926                }
 927                if (newmode & S_IWUGO)
 928                        info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 929                else
 930                        info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 931
 932#ifdef CONFIG_NCPFS_NFS_NS
 933                if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
 934                        result = ncp_modify_nfs_info(server,
 935                                                     NCP_FINFO(inode)->volNumber,
 936                                                     NCP_FINFO(inode)->dirEntNum,
 937                                                     attr->ia_mode, 0);
 938                        if (result != 0)
 939                                goto out;
 940                        info.attributes &= ~(aSHARED | aSYSTEM);
 941                        {
 942                                /* mark partial success */
 943                                struct iattr tmpattr;
 944                                
 945                                tmpattr.ia_valid = ATTR_MODE;
 946                                tmpattr.ia_mode = attr->ia_mode;
 947
 948                                setattr_copy(inode, &tmpattr);
 949                                mark_inode_dirty(inode);
 950                        }
 951                }
 952#endif
 953        }
 954#endif
 955
 956        /* Do SIZE before attributes, otherwise mtime together with size does not work...
 957         */
 958        if ((attr->ia_valid & ATTR_SIZE) != 0) {
 959                int written;
 960
 961                DPRINTK("ncpfs: trying to change size to %ld\n",
 962                        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                        result = vmtruncate(inode, attr->ia_size);
 980                        if (result)
 981                                goto out;
 982                        mark_inode_dirty(inode);
 983                }
 984        }
 985        if ((attr->ia_valid & ATTR_CTIME) != 0) {
 986                info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
 987                ncp_date_unix2dos(attr->ia_ctime.tv_sec,
 988                             &info.creationTime, &info.creationDate);
 989        }
 990        if ((attr->ia_valid & ATTR_MTIME) != 0) {
 991                info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
 992                ncp_date_unix2dos(attr->ia_mtime.tv_sec,
 993                                  &info.modifyTime, &info.modifyDate);
 994        }
 995        if ((attr->ia_valid & ATTR_ATIME) != 0) {
 996                __le16 dummy;
 997                info_mask |= (DM_LAST_ACCESS_DATE);
 998                ncp_date_unix2dos(attr->ia_atime.tv_sec,
 999                                  &dummy, &info.lastAccessDate);
1000        }
1001        if (info_mask != 0) {
1002                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1003                                      inode, info_mask, &info);
1004                if (result != 0) {
1005                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1006                                /* NetWare seems not to allow this. I
1007                                   do not know why. So, just tell the
1008                                   user everything went fine. This is
1009                                   a terrible hack, but I do not know
1010                                   how to do this correctly. */
1011                                result = 0;
1012                        } else
1013                                goto out;
1014                }
1015#ifdef CONFIG_NCPFS_STRONG              
1016                if ((!result) && (info_mask & DM_ATTRIBUTES))
1017                        NCP_FINFO(inode)->nwattr = info.attributes;
1018#endif
1019        }
1020        if (result)
1021                goto out;
1022
1023        setattr_copy(inode, attr);
1024        mark_inode_dirty(inode);
1025
1026out:
1027        if (result > 0)
1028                result = -EACCES;
1029        return result;
1030}
1031
1032static struct dentry *ncp_mount(struct file_system_type *fs_type,
1033        int flags, const char *dev_name, void *data)
1034{
1035        return mount_nodev(fs_type, flags, data, ncp_fill_super);
1036}
1037
1038static struct file_system_type ncp_fs_type = {
1039        .owner          = THIS_MODULE,
1040        .name           = "ncpfs",
1041        .mount          = ncp_mount,
1042        .kill_sb        = kill_anon_super,
1043        .fs_flags       = FS_BINARY_MOUNTDATA,
1044};
1045
1046static int __init init_ncp_fs(void)
1047{
1048        int err;
1049        DPRINTK("ncpfs: init_ncp_fs 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        DPRINTK("ncpfs: exit_ncp_fs 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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.