root/fs/ncpfs/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ncp_read_inode
  2. ncp_put_inode
  3. ncp_read_super
  4. ncp_put_super
  5. ncp_statfs
  6. ncp_notify_change
  7. init_ncp_fs
  8. init_module
  9. cleanup_module

   1 /*
   2  *  inode.c
   3  *
   4  *  Copyright (C) 1995 by Volker Lendecke
   5  *
   6  */
   7 
   8 #include <linux/module.h>
   9 
  10 #include <asm/system.h>
  11 #include <asm/segment.h>
  12 
  13 #include <linux/sched.h>
  14 #include <linux/ncp_fs.h>
  15 #include <linux/kernel.h>
  16 #include <linux/mm.h>
  17 #include <linux/string.h>
  18 #include <linux/stat.h>
  19 #include <linux/errno.h>
  20 #include <linux/locks.h>
  21 #include <linux/fcntl.h>
  22 #include <linux/malloc.h>
  23 #include "ncplib_kernel.h"
  24 
  25 extern int close_fp(struct file *filp);
  26 
  27 static void ncp_put_inode(struct inode *);
  28 static void ncp_read_inode(struct inode *);
  29 static void ncp_put_super(struct super_block *);
  30 static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
  31 static int ncp_notify_change(struct inode *inode, struct iattr *attr);
  32 
  33 static struct super_operations ncp_sops = {
  34         ncp_read_inode,         /* read inode */
  35         ncp_notify_change,      /* notify change */
  36         NULL,                   /* write inode */
  37         ncp_put_inode,          /* put inode */
  38         ncp_put_super,          /* put superblock */
  39         NULL,                   /* write superblock */
  40         ncp_statfs,             /* stat filesystem */
  41         NULL
  42 };
  43 
  44 /* ncp_read_inode: Called from iget, it only traverses the allocated
  45    ncp_inode_info's and initializes the inode from the data found
  46    there.  It does not allocate or deallocate anything. */
  47 
  48 static void
  49 ncp_read_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  50 {
  51         /* Our task should be extremely simple here. We only have to
  52            look up the infomation somebody else (ncp_iget) put into
  53            the inode tree. The address of this information is the
  54            inode->i_ino. Just to make sure everything went well, we
  55            check it's there. */
  56 
  57         struct ncp_inode_info *inode_info
  58                 = (struct ncp_inode_info *)(inode->i_ino);
  59 
  60 #if 1
  61         struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
  62         struct ncp_inode_info *check_info = root;
  63 
  64         do
  65         {
  66                 if (inode_info == check_info)
  67                 {
  68                         if (check_info->state == NCP_INODE_LOOKED_UP)
  69                         {
  70                                 DDPRINTK("ncp_read_inode: found it!\n");
  71                                 goto good;
  72                         }
  73                         else
  74                         {
  75                                 printk("ncp_read_inode: "
  76                                        "state != NCP_INODE_LOOKED_UP\n");
  77                                 goto good;
  78                         }
  79                 }
  80                 check_info = check_info->next;
  81         }
  82         while (check_info != root);
  83 
  84         /* Ok, now we're in trouble. The inode info is not there. What
  85            should we do now??? */
  86         printk("ncp_read_inode: inode info not found\n");
  87         return;
  88 
  89  good:
  90         DDPRINTK("ncp_read_inode: read entry %s\n",
  91                  inode_info->finfo.i.entryName);
  92 #endif
  93         inode_info->state = NCP_INODE_VALID;
  94 
  95         NCP_INOP(inode) = inode_info;
  96 
  97         if (NCP_ISTRUCT(inode)->attributes & aDIR)
  98         {
  99                 inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
 100                 /* for directories in dataStreamSize seems to be some
 101                    Object ID ??? */
 102                 inode->i_size = 512;
 103         }
 104         else
 105         {
 106                 inode->i_mode = NCP_SERVER(inode)->m.file_mode;
 107                 inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
 108         }
 109 
 110         DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
 111 
 112         inode->i_nlink   = 1;
 113         inode->i_uid     = NCP_SERVER(inode)->m.uid;
 114         inode->i_gid     = NCP_SERVER(inode)->m.gid;
 115         inode->i_blksize = 1024;
 116         inode->i_rdev    = 0;
 117 
 118         if ((inode->i_blksize != 0) && (inode->i_size != 0))
 119         {
 120                 inode->i_blocks =
 121                         (inode->i_size - 1) / inode->i_blksize + 1;
 122         }
 123         else
 124         {
 125                 inode->i_blocks = 0;
 126         }
 127 
 128         inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
 129                                            NCP_ISTRUCT(inode)->modifyDate);
 130         inode->i_ctime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->creationTime,
 131                                            NCP_ISTRUCT(inode)->creationDate);
 132         inode->i_atime = ncp_date_dos2unix(0,
 133                                            NCP_ISTRUCT(inode)->lastAccessDate);
 134 
 135         if (S_ISREG(inode->i_mode))
 136         {
 137                 inode->i_op = &ncp_file_inode_operations;
 138         }
 139         else if (S_ISDIR(inode->i_mode))
 140         {
 141                 inode->i_op = &ncp_dir_inode_operations;
 142         }
 143         else
 144         {
 145                 inode->i_op = NULL;
 146         }
 147 }
 148 
 149 static void
 150 ncp_put_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         struct nw_file_info *finfo = NCP_FINFO(inode);
 153 
 154         if (finfo->opened != 0)
 155         {
 156                 if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
 157                 {
 158                         /* We can't do anything but complain. */
 159                         printk("ncp_put_inode: could not close\n");
 160                 }
 161         }
 162 
 163         DDPRINTK("ncp_put_inode: put %s\n",
 164                 finfo->i.entryName);
 165 
 166         ncp_free_inode_info(NCP_INOP(inode));
 167 
 168         if (S_ISDIR(inode->i_mode))
 169         {
 170                 DDPRINTK("ncp_put_inode: put directory %ld\n",
 171                          inode->i_ino);
 172                 ncp_invalid_dir_cache(inode->i_ino);
 173         }                
 174 
 175         clear_inode(inode);
 176 }
 177 
 178 struct super_block *
 179 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
 182         struct ncp_server *server;
 183         struct file *ncp_filp;
 184         struct file *wdog_filp;
 185         kdev_t dev = sb->s_dev;
 186         int error;
 187 
 188         if (data == NULL)
 189         {
 190                 printk("ncp_read_super: missing data argument\n");
 191                 sb->s_dev = 0;
 192                 return NULL;
 193         }
 194 
 195         if (data->version != NCP_MOUNT_VERSION)
 196         {
 197                 printk("ncp warning: mount version %s than kernel\n",
 198                        (data->version < NCP_MOUNT_VERSION) ?
 199                        "older" : "newer");
 200         }
 201 
 202         if (   (data->ncp_fd >= NR_OPEN)
 203             || ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
 204             || (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
 205         {
 206                 printk("ncp_read_super: invalid ncp socket\n");
 207                 sb->s_dev = 0;
 208                 return NULL;
 209         }
 210 
 211         if (   (data->wdog_fd >= NR_OPEN)
 212             || ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
 213             || (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
 214         {
 215                 printk("ncp_read_super: invalid wdog socket\n");
 216                 sb->s_dev = 0;
 217                 return NULL;
 218         }
 219 
 220         /* We must malloc our own super-block info */
 221         server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
 222                                                    GFP_KERNEL);
 223 
 224         if (server == NULL)
 225         {
 226                 printk("ncp_read_super: could not alloc ncp_server\n");
 227                 return NULL;
 228         }
 229 
 230         ncp_filp->f_count += 1;
 231         wdog_filp->f_count += 1;
 232 
 233         lock_super(sb);
 234 
 235         NCP_SBP(sb) = server;
 236         
 237         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
 238         sb->s_blocksize_bits = 10;
 239         sb->s_magic = NCP_SUPER_MAGIC;
 240         sb->s_dev = dev;
 241         sb->s_op = &ncp_sops;
 242 
 243         server->ncp_filp    = ncp_filp;
 244         server->wdog_filp   = wdog_filp;
 245         server->lock        = 0;
 246         server->wait        = NULL;
 247         server->packet      = NULL;
 248         server->buffer_size = 0;
 249 
 250         server->m = *data;
 251         server->m.file_mode = (server->m.file_mode &
 252                                (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
 253         server->m.dir_mode  = (server->m.dir_mode &
 254                                (S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
 255 
 256         server->packet_size = NCP_PACKET_SIZE;
 257         server->packet      = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
 258 
 259         if (server->packet == NULL)
 260         {
 261                 printk("ncpfs: could not alloc packet\n");
 262                 error = -ENOMEM;
 263                 unlock_super(sb);
 264                 goto fail;
 265         }
 266    
 267         ncp_init_root(server);
 268 
 269         /*
 270          * Make the connection to the server
 271          */
 272 
 273         if (ncp_catch_watchdog(server) != 0)
 274         {
 275                 printk("ncp_read_super: Could not catch watchdog\n");
 276                 error = -EINVAL;
 277                 unlock_super(sb);
 278                 goto fail;
 279         }
 280 
 281         ncp_lock_server(server);
 282         error = ncp_connect(server);
 283         ncp_unlock_server(server);
 284         unlock_super(sb);
 285 
 286         if (error < 0)
 287         {
 288                 sb->s_dev = 0;
 289                 printk("ncp_read_super: Failed connection, bailing out "
 290                        "(error = %d).\n", -error);
 291                 ncp_kfree_s(server->packet, server->packet_size);
 292                 ncp_dont_catch_watchdog(server);
 293                 goto fail;
 294         }
 295 
 296         DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
 297 
 298         if (!(sb->s_mounted = iget(sb, (int)&(server->root))))
 299         {
 300                 sb->s_dev = 0;
 301                 printk("ncp_read_super: get root inode failed\n");
 302                 goto disconnect;
 303         }
 304 
 305         if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
 306                                      &(server->buffer_size)) != 0)
 307         {
 308                 sb->s_dev = 0;
 309                 printk("ncp_read_super: could not get bufsize\n");
 310                 goto disconnect;
 311         }
 312 
 313         DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
 314 
 315         MOD_INC_USE_COUNT;
 316         return sb;
 317 
 318  disconnect:
 319         ncp_lock_server(server);
 320         ncp_disconnect(server);
 321         ncp_unlock_server(server);
 322         ncp_kfree_s(server->packet, server->packet_size);
 323         ncp_dont_catch_watchdog(server);
 324  fail:
 325         ncp_filp->f_count -= 1;
 326         wdog_filp->f_count -= 1;
 327         ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
 328         return NULL;
 329 }
 330 
 331 static void
 332 ncp_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334         struct ncp_server *server = NCP_SBP(sb);
 335 
 336         lock_super(sb);
 337 
 338         ncp_lock_server(server);
 339         ncp_disconnect(server);
 340         ncp_unlock_server(server);
 341 
 342         close_fp(server->ncp_filp);
 343 
 344         ncp_dont_catch_watchdog(server);
 345         close_fp(server->wdog_filp);
 346 
 347         ncp_free_all_inodes(server);
 348 
 349         ncp_kfree_s(server->packet, server->packet_size);
 350 
 351         sb->s_dev = 0;
 352         ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
 353         NCP_SBP(sb) = NULL;
 354 
 355         unlock_super(sb);
 356 
 357         MOD_DEC_USE_COUNT;
 358 }
 359 
 360 static void 
 361 ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 362 {
 363         struct statfs tmp;
 364         
 365         /* We cannot say how much disk space is left on a mounted
 366            NetWare Server, because free space is distributed over
 367            volumes, and the current user might have disk quotas. So
 368            free space is not that simple to determine. Our decision
 369            here is to err conservatively. */
 370 
 371         tmp.f_type = NCP_SUPER_MAGIC;
 372         tmp.f_bsize = 512;
 373         tmp.f_blocks = 0;
 374         tmp.f_bfree = 0;
 375         tmp.f_bavail = 0;
 376         tmp.f_files = -1;
 377         tmp.f_ffree = -1;
 378         tmp.f_namelen = 12;
 379         memcpy_tofs(buf, &tmp, bufsiz);
 380 }
 381 
 382 static int
 383 ncp_notify_change(struct inode *inode, struct iattr *attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 384 {
 385         int result = 0;
 386         int info_mask;
 387         struct nw_modify_dos_info info;
 388 
 389         if ((result = inode_change_ok(inode, attr)) < 0)
 390                 return result;
 391 
 392         if (((attr->ia_valid & ATTR_UID) && 
 393              (attr->ia_uid != NCP_SERVER(inode)->m.uid)))
 394                 return -EPERM;
 395 
 396         if (((attr->ia_valid & ATTR_GID) && 
 397              (attr->ia_uid != NCP_SERVER(inode)->m.gid)))
 398                 return -EPERM;
 399 
 400         if (((attr->ia_valid & ATTR_MODE) &&
 401              (attr->ia_mode &
 402               ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
 403                 return -EPERM;
 404 
 405         info_mask = 0;
 406         memset(&info, 0, sizeof(info));
 407 
 408         if ((attr->ia_valid & ATTR_CTIME) != 0)
 409         {
 410                 info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
 411                 ncp_date_unix2dos(attr->ia_ctime,
 412                                   &(info.creationTime), &(info.creationDate));
 413         }
 414         
 415         if ((attr->ia_valid & ATTR_MTIME) != 0)
 416         {
 417                 info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
 418                 ncp_date_unix2dos(attr->ia_mtime,
 419                                   &(info.modifyTime), &(info.modifyDate));
 420         }
 421         
 422         if ((attr->ia_valid & ATTR_ATIME) != 0)
 423         {
 424                 __u16 dummy;
 425                 info_mask |= (DM_LAST_ACCESS_DATE);
 426                 ncp_date_unix2dos(attr->ia_ctime,
 427                                   &(dummy), &(info.lastAccessDate));
 428         }
 429 
 430         if (info_mask != 0)
 431         {
 432                 if ((result =
 433                      ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
 434                                                         NCP_ISTRUCT(inode),
 435                                                         info_mask,
 436                                                         &info)) != 0)
 437                 {
 438                         result = -EACCES;
 439 
 440                         if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
 441                         {
 442                                 /* NetWare seems not to allow this. I
 443                                    do not know why. So, just tell the
 444                                    user everything went fine. This is
 445                                    a terrible hack, but I do not know
 446                                    how to do this correctly. */
 447                                 result = 0;
 448                         }
 449                 }
 450         }
 451 
 452         if ((attr->ia_valid & ATTR_SIZE) != 0)
 453         {
 454                 int written;
 455 
 456                 DPRINTK("ncpfs: trying to change size of %s to %ld\n",
 457                         NCP_ISTRUCT(inode)->entryName, attr->ia_size);
 458 
 459                 if ((result = ncp_make_open(inode, O_RDWR)) < 0)
 460                 {
 461                         return -EACCES;
 462                 }
 463 
 464                 ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
 465                           attr->ia_size, 0, "", &written);
 466 
 467                 /* According to ndir, the changes only take effect after
 468                    closing the file */
 469                 ncp_close_file(NCP_SERVER(inode),
 470                                NCP_FINFO(inode)->file_handle);
 471                 NCP_FINFO(inode)->opened = 0;
 472 
 473                 result = 0;
 474         }
 475 
 476         ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
 477 
 478         return result;
 479 }
 480                 
 481 #ifdef DEBUG_NCP_MALLOC
 482 int ncp_malloced;
 483 int ncp_current_malloced;
 484 #endif
 485 
 486 static struct file_system_type ncp_fs_type = {
 487         ncp_read_super, "ncpfs", 0, NULL
 488         };
 489 
 490 int init_ncp_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 491 {
 492         return register_filesystem(&ncp_fs_type);
 493 }
 494 
 495 #ifdef MODULE
 496 init_module( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 497 {
 498         int status;
 499 
 500         DPRINTK("ncpfs: init_module called\n");
 501 
 502 #ifdef DEBUG_NCP_MALLOC
 503         ncp_malloced = 0;
 504         ncp_current_malloced = 0;
 505 #endif
 506         ncp_init_dir_cache();
 507 
 508         if ((status = init_ncp_fs()) == 0)
 509                 register_symtab(0);
 510         return status;
 511 }
 512 
 513 void
 514 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516         DPRINTK("ncpfs: cleanup_module called\n");
 517         ncp_free_dir_cache();
 518         unregister_filesystem(&ncp_fs_type);
 519 #ifdef DEBUG_NCP_MALLOC
 520         printk("ncp_malloced: %d\n", ncp_malloced);
 521         printk("ncp_current_malloced: %d\n", ncp_current_malloced);
 522 #endif
 523 }
 524 
 525 #endif

/* [previous][next][first][last][top][bottom][index][help] */