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_trigger_message
  6. ncp_statfs
  7. ncp_notify_change
  8. init_ncp_fs
  9. init_module
  10. cleanup_module

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

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