The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ncpfs/inode.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  *
    9  */
   10 
   11 #include <linux/config.h>
   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/sched.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/locks.h>
   25 #include <linux/file.h>
   26 #include <linux/fcntl.h>
   27 #include <linux/slab.h>
   28 #include <linux/vmalloc.h>
   29 #include <linux/init.h>
   30 
   31 #include <linux/ncp_fs.h>
   32 
   33 #include "ncplib_kernel.h"
   34 
   35 static void ncp_delete_inode(struct inode *);
   36 static void ncp_put_super(struct super_block *);
   37 static int  ncp_statfs(struct super_block *, struct statfs *);
   38 
   39 static struct super_operations ncp_sops =
   40 {
   41         put_inode:      force_delete,
   42         delete_inode:   ncp_delete_inode,
   43         put_super:      ncp_put_super,
   44         statfs:         ncp_statfs,
   45 };
   46 
   47 extern struct dentry_operations ncp_root_dentry_operations;
   48 #ifdef CONFIG_NCPFS_EXTRAS
   49 extern struct address_space_operations ncp_symlink_aops;
   50 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
   51 #endif
   52 
   53 /*
   54  * Fill in the ncpfs-specific information in the inode.
   55  */
   56 void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
   57 {
   58         NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
   59         NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
   60         NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
   61 
   62 #ifdef CONFIG_NCPFS_STRONG
   63         NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
   64 #endif
   65         NCP_FINFO(inode)->access = nwinfo->access;
   66         NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
   67         memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
   68                         sizeof(nwinfo->file_handle));
   69         DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
   70                 nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
   71                 NCP_FINFO(inode)->dirEntNum);
   72 }
   73 
   74 void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
   75 {
   76         struct nw_info_struct *nwi = &nwinfo->i;
   77         struct ncp_server *server = NCP_SERVER(inode);
   78 
   79         if (!atomic_read(&NCP_FINFO(inode)->opened)) {
   80 #ifdef CONFIG_NCPFS_STRONG
   81                 NCP_FINFO(inode)->nwattr = nwi->attributes;
   82 #endif
   83                 if (nwi->attributes & aDIR) {
   84                         inode->i_mode = server->m.dir_mode;
   85                         inode->i_size = NCP_BLOCK_SIZE;
   86                 } else {
   87                         inode->i_mode = server->m.file_mode;
   88                         inode->i_size = le32_to_cpu(nwi->dataStreamSize);
   89 #ifdef CONFIG_NCPFS_EXTRAS
   90                         if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
   91                                 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
   92                                         case aHIDDEN:
   93                                                 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
   94                                                         if ( /* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
   95                                                          && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
   96                                                                 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
   97                                                                 break;
   98                                                         }
   99                                                 }
  100                                                 /* FALLTHROUGH */
  101                                         case 0:
  102                                                 if (server->m.flags & NCP_MOUNT_EXTRAS)
  103                                                         inode->i_mode |= 0444;
  104                                                 break;
  105                                         case aSYSTEM:
  106                                                 if (server->m.flags & NCP_MOUNT_EXTRAS)
  107                                                         inode->i_mode |= (inode->i_mode >> 2) & 0111;
  108                                                 break;
  109                                         /* case aSYSTEM|aHIDDEN: */
  110                                         default:
  111                                                 /* reserved combination */
  112                                                 break;
  113                                 }
  114                         }
  115 #endif
  116                 }
  117                 if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
  118         }
  119         inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
  120 
  121         inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
  122                                            le16_to_cpu(nwi->modifyDate));
  123         inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
  124                                            le16_to_cpu(nwi->creationDate));
  125         inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate));
  126 
  127         NCP_FINFO(inode)->DosDirNum = nwi->DosDirNum;
  128         NCP_FINFO(inode)->dirEntNum = nwi->dirEntNum;
  129         NCP_FINFO(inode)->volNumber = nwi->volNumber;
  130 }
  131 
  132 /*
  133  * Fill in the inode based on the ncp_entry_info structure.
  134  */
  135 static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
  136 {
  137         struct nw_info_struct *nwi = &nwinfo->i;
  138         struct ncp_server *server = NCP_SERVER(inode);
  139 
  140         if (nwi->attributes & aDIR) {
  141                 inode->i_mode = server->m.dir_mode;
  142                 /* for directories dataStreamSize seems to be some
  143                    Object ID ??? */
  144                 inode->i_size = NCP_BLOCK_SIZE;
  145         } else {
  146                 inode->i_mode = server->m.file_mode;
  147                 inode->i_size = le32_to_cpu(nwi->dataStreamSize);
  148 #ifdef CONFIG_NCPFS_EXTRAS
  149                 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 
  150                  && (nwi->attributes & aSHARED)) {
  151                         switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
  152                                 case aHIDDEN:
  153                                         if (server->m.flags & NCP_MOUNT_SYMLINKS) {
  154                                                 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
  155                                                  && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
  156                                                         inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
  157                                                         break;
  158                                                 }
  159                                         }
  160                                         /* FALLTHROUGH */
  161                                 case 0:
  162                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
  163                                                 inode->i_mode |= 0444;
  164                                         break;
  165                                 case aSYSTEM:
  166                                         if (server->m.flags & NCP_MOUNT_EXTRAS)
  167                                                 inode->i_mode |= (inode->i_mode >> 2) & 0111;
  168                                         break;
  169                                 /* case aSYSTEM|aHIDDEN: */
  170                                 default:
  171                                         /* reserved combination */
  172                                         break;
  173                         }
  174                 }
  175 #endif
  176         }
  177         if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
  178 
  179         DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
  180 
  181         inode->i_nlink = 1;
  182         inode->i_uid = server->m.uid;
  183         inode->i_gid = server->m.gid;
  184         inode->i_rdev = 0;
  185         inode->i_blksize = NCP_BLOCK_SIZE;
  186 
  187         inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
  188 
  189         inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
  190                                            le16_to_cpu(nwi->modifyDate));
  191         inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
  192                                            le16_to_cpu(nwi->creationDate));
  193         inode->i_atime = ncp_date_dos2unix(0,
  194                                            le16_to_cpu(nwi->lastAccessDate));
  195         ncp_update_inode(inode, nwinfo);
  196 }
  197 
  198 static struct inode_operations ncp_symlink_inode_operations = {
  199         readlink:       page_readlink,
  200         follow_link:    page_follow_link,
  201         setattr:        ncp_notify_change,
  202 };
  203 
  204 /*
  205  * Get a new inode.
  206  */
  207 struct inode * 
  208 ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
  209 {
  210         struct inode *inode;
  211 
  212         if (info == NULL) {
  213                 printk(KERN_ERR "ncp_iget: info is NULL\n");
  214                 return NULL;
  215         }
  216 
  217         inode = new_inode(sb);
  218         if (inode) {
  219                 init_MUTEX(&NCP_FINFO(inode)->open_sem);
  220                 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
  221 
  222                 inode->i_ino = info->ino;
  223                 ncp_set_attr(inode, info);
  224                 if (S_ISREG(inode->i_mode)) {
  225                         inode->i_op = &ncp_file_inode_operations;
  226                         inode->i_fop = &ncp_file_operations;
  227                 } else if (S_ISDIR(inode->i_mode)) {
  228                         inode->i_op = &ncp_dir_inode_operations;
  229                         inode->i_fop = &ncp_dir_operations;
  230 #ifdef CONFIG_NCPFS_EXTRAS
  231                 } else if (S_ISLNK(inode->i_mode)) {
  232                         inode->i_op = &ncp_symlink_inode_operations;
  233                         inode->i_data.a_ops = &ncp_symlink_aops;
  234 #endif
  235                 }
  236                 insert_inode_hash(inode);
  237         } else
  238                 printk(KERN_ERR "ncp_iget: iget failed!\n");
  239         return inode;
  240 }
  241 
  242 static void
  243 ncp_delete_inode(struct inode *inode)
  244 {
  245         if (S_ISDIR(inode->i_mode)) {
  246                 DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
  247         }
  248 
  249         if (ncp_make_closed(inode) != 0) {
  250                 /* We can't do anything but complain. */
  251                 printk(KERN_ERR "ncp_delete_inode: could not close\n");
  252         }
  253         clear_inode(inode);
  254 }
  255 
  256 struct super_block *
  257 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
  258 {
  259         struct ncp_mount_data_kernel data;
  260         struct ncp_server *server;
  261         struct file *ncp_filp;
  262         struct inode *root_inode;
  263         struct inode *sock_inode;
  264         struct socket *sock;
  265         int error;
  266         int default_bufsize;
  267 #ifdef CONFIG_NCPFS_PACKET_SIGNING
  268         int options;
  269 #endif
  270         struct ncp_entry_info finfo;
  271 
  272         if (raw_data == NULL)
  273                 goto out_no_data;
  274         switch (*(int*)raw_data) {
  275                 case NCP_MOUNT_VERSION:
  276                         {
  277                                 struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
  278 
  279                                 data.flags = md->flags;
  280                                 data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
  281                                 data.mounted_uid = md->mounted_uid;
  282                                 data.wdog_pid = md->wdog_pid;
  283                                 data.ncp_fd = md->ncp_fd;
  284                                 data.time_out = md->time_out;
  285                                 data.retry_count = md->retry_count;
  286                                 data.uid = md->uid;
  287                                 data.gid = md->gid;
  288                                 data.file_mode = md->file_mode;
  289                                 data.dir_mode = md->dir_mode;
  290                                 memcpy(data.mounted_vol, md->mounted_vol,
  291                                         NCP_VOLNAME_LEN+1);
  292                         }
  293                         break;
  294                 case NCP_MOUNT_VERSION_V4:
  295                         {
  296                                 struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
  297 
  298                                 data.flags = md->flags;
  299                                 data.int_flags = 0;
  300                                 data.mounted_uid = md->mounted_uid;
  301                                 data.wdog_pid = md->wdog_pid;
  302                                 data.ncp_fd = md->ncp_fd;
  303                                 data.time_out = md->time_out;
  304                                 data.retry_count = md->retry_count;
  305                                 data.uid = md->uid;
  306                                 data.gid = md->gid;
  307                                 data.file_mode = md->file_mode;
  308                                 data.dir_mode = md->dir_mode;
  309                                 data.mounted_vol[0] = 0;
  310                         }
  311                         break;
  312                 default:
  313                         goto out_bad_mount;
  314         }
  315         ncp_filp = fget(data.ncp_fd);
  316         if (!ncp_filp)
  317                 goto out_bad_file;
  318         sock_inode = ncp_filp->f_dentry->d_inode;
  319         if (!S_ISSOCK(sock_inode->i_mode))
  320                 goto out_bad_file2;
  321         sock = &sock_inode->u.socket_i;
  322         if (!sock)
  323                 goto out_bad_file2;
  324                 
  325         if (sock->type == SOCK_STREAM)
  326                 default_bufsize = 61440;
  327         else
  328                 default_bufsize = 1024;
  329 
  330         sb->s_blocksize = 1024; /* Eh...  Is this correct? */
  331         sb->s_blocksize_bits = 10;
  332         sb->s_magic = NCP_SUPER_MAGIC;
  333         sb->s_op = &ncp_sops;
  334 
  335         server = NCP_SBP(sb);
  336         memset(server, 0, sizeof(*server));
  337 
  338         server->ncp_filp = ncp_filp;
  339 /*      server->lock = 0;       */
  340         init_MUTEX(&server->sem);
  341         server->packet = NULL;
  342 /*      server->buffer_size = 0;        */
  343 /*      server->conn_status = 0;        */
  344 /*      server->root_dentry = NULL;     */
  345 /*      server->root_setuped = 0;       */
  346 #ifdef CONFIG_NCPFS_PACKET_SIGNING
  347 /*      server->sign_wanted = 0;        */
  348 /*      server->sign_active = 0;        */
  349 #endif
  350         server->auth.auth_type = NCP_AUTH_NONE;
  351 /*      server->auth.object_name_len = 0;       */
  352 /*      server->auth.object_name = NULL;        */
  353 /*      server->auth.object_type = 0;           */
  354 /*      server->priv.len = 0;                   */
  355 /*      server->priv.data = NULL;               */
  356 
  357         server->m = data;
  358         /* Althought anything producing this is buggy, it happens
  359            now because of PATH_MAX changes.. */
  360         if (server->m.time_out < 1) {
  361                 server->m.time_out = 10;
  362                 printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
  363         }
  364         server->m.time_out = server->m.time_out * HZ / 100;
  365         server->m.file_mode = (server->m.file_mode &
  366                                (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
  367         server->m.dir_mode = (server->m.dir_mode &
  368                               (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
  369 
  370 #ifdef CONFIG_NCPFS_NLS
  371         /* load the default NLS charsets */
  372         server->nls_vol = load_nls_default();
  373         server->nls_io = load_nls_default();
  374 #endif /* CONFIG_NCPFS_NLS */
  375 
  376         server->dentry_ttl = 0; /* no caching */
  377 
  378 #undef NCP_PACKET_SIZE
  379 #define NCP_PACKET_SIZE 65536
  380         server->packet_size = NCP_PACKET_SIZE;
  381         server->packet = vmalloc(NCP_PACKET_SIZE);
  382         if (server->packet == NULL)
  383                 goto out_no_packet;
  384 
  385         ncp_lock_server(server);
  386         error = ncp_connect(server);
  387         ncp_unlock_server(server);
  388         if (error < 0)
  389                 goto out_no_connect;
  390         DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
  391 
  392 #ifdef CONFIG_NCPFS_PACKET_SIGNING
  393         if (ncp_negotiate_size_and_options(server, default_bufsize,
  394                 NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
  395         {
  396                 if (options != NCP_DEFAULT_OPTIONS)
  397                 {
  398                         if (ncp_negotiate_size_and_options(server, 
  399                                 default_bufsize,
  400                                 options & 2, 
  401                                 &(server->buffer_size), &options) != 0)
  402                                 
  403                         {
  404                                 goto out_no_bufsize;
  405                         }
  406                 }
  407                 if (options & 2)
  408                         server->sign_wanted = 1;
  409         }
  410         else 
  411 #endif  /* CONFIG_NCPFS_PACKET_SIGNING */
  412         if (ncp_negotiate_buffersize(server, default_bufsize,
  413                                      &(server->buffer_size)) != 0)
  414                 goto out_no_bufsize;
  415         DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
  416 
  417         memset(&finfo, 0, sizeof(finfo));
  418         finfo.i.attributes      = aDIR;
  419         finfo.i.dataStreamSize  = NCP_BLOCK_SIZE;
  420         finfo.i.dirEntNum       = 0;
  421         finfo.i.DosDirNum       = 0;
  422 #ifdef CONFIG_NCPFS_SMALLDOS
  423         finfo.i.NSCreator       = NW_NS_DOS;
  424 #endif
  425         finfo.i.volNumber       = NCP_NUMBER_OF_VOLUMES + 1;    /* illegal volnum */
  426         /* set dates of mountpoint to Jan 1, 1986; 00:00 */
  427         finfo.i.creationTime    = finfo.i.modifyTime
  428                                 = cpu_to_le16(0x0000);
  429         finfo.i.creationDate    = finfo.i.modifyDate
  430                                 = finfo.i.lastAccessDate
  431                                 = cpu_to_le16(0x0C21);
  432         finfo.i.nameLen         = 0;
  433         finfo.i.entryName[0]    = '\0';
  434 
  435         finfo.opened            = 0;
  436         finfo.ino               = 2;    /* tradition */
  437 
  438         server->name_space[finfo.i.volNumber] = NW_NS_DOS;
  439         root_inode = ncp_iget(sb, &finfo);
  440         if (!root_inode)
  441                 goto out_no_root;
  442         DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
  443         sb->s_root = d_alloc_root(root_inode);
  444         if (!sb->s_root)
  445                 goto out_no_root;
  446         sb->s_root->d_op = &ncp_root_dentry_operations;
  447         return sb;
  448 
  449 out_no_root:
  450         printk(KERN_ERR "ncp_read_super: get root inode failed\n");
  451         iput(root_inode);
  452         goto out_disconnect;
  453 out_no_bufsize:
  454         printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
  455 out_disconnect:
  456         ncp_lock_server(server);
  457         ncp_disconnect(server);
  458         ncp_unlock_server(server);
  459         goto out_free_packet;
  460 out_no_connect:
  461         printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
  462 out_free_packet:
  463         vfree(server->packet);
  464         goto out_free_server;
  465 out_no_packet:
  466         printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
  467 out_free_server:
  468 #ifdef CONFIG_NCPFS_NLS
  469         unload_nls(server->nls_io);
  470         unload_nls(server->nls_vol);
  471 #endif
  472         /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
  473          * 
  474          * The previously used put_filp(ncp_filp); was bogous, since
  475          * it doesn't proper unlocking.
  476          */
  477         fput(ncp_filp);
  478         goto out;
  479 
  480 out_bad_file2:
  481         fput(ncp_filp);
  482 out_bad_file:
  483         printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
  484         goto out;
  485 out_bad_mount:
  486         printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
  487                 NCP_MOUNT_VERSION);
  488         goto out;
  489 out_no_data:
  490         printk(KERN_ERR "ncp_read_super: missing data argument\n");
  491 out:
  492         return NULL;
  493 }
  494 
  495 static void ncp_put_super(struct super_block *sb)
  496 {
  497         struct ncp_server *server = NCP_SBP(sb);
  498 
  499         ncp_lock_server(server);
  500         ncp_disconnect(server);
  501         ncp_unlock_server(server);
  502 
  503 #ifdef CONFIG_NCPFS_NLS
  504         /* unload the NLS charsets */
  505         if (server->nls_vol)
  506         {
  507                 unload_nls(server->nls_vol);
  508                 server->nls_vol = NULL;
  509         }
  510         if (server->nls_io)
  511         {
  512                 unload_nls(server->nls_io);
  513                 server->nls_io = NULL;
  514         }
  515 #endif /* CONFIG_NCPFS_NLS */
  516 
  517         fput(server->ncp_filp);
  518         kill_proc(server->m.wdog_pid, SIGTERM, 1);
  519 
  520         if (server->priv.data) 
  521                 ncp_kfree_s(server->priv.data, server->priv.len);
  522         if (server->auth.object_name)
  523                 ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
  524         vfree(server->packet);
  525 
  526 }
  527 
  528 static int ncp_statfs(struct super_block *sb, struct statfs *buf)
  529 {
  530         /* We cannot say how much disk space is left on a mounted
  531            NetWare Server, because free space is distributed over
  532            volumes, and the current user might have disk quotas. So
  533            free space is not that simple to determine. Our decision
  534            here is to err conservatively. */
  535 
  536         buf->f_type = NCP_SUPER_MAGIC;
  537         buf->f_bsize = NCP_BLOCK_SIZE;
  538         buf->f_blocks = 0;
  539         buf->f_bfree = 0;
  540         buf->f_bavail = 0;
  541         buf->f_namelen = 12;
  542         return 0;
  543 }
  544 
  545 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
  546 {
  547         struct inode *inode = dentry->d_inode;
  548         int result = 0;
  549         int info_mask;
  550         struct nw_modify_dos_info info;
  551         struct ncp_server *server;
  552 
  553         result = -EIO;
  554 
  555         server = NCP_SERVER(inode);
  556         if ((!server) || !ncp_conn_valid(server))
  557                 goto out;
  558 
  559         /* ageing the dentry to force validation */
  560         ncp_age_dentry(server, dentry);
  561 
  562         result = inode_change_ok(inode, attr);
  563         if (result < 0)
  564                 goto out;
  565 
  566         result = -EPERM;
  567         if (((attr->ia_valid & ATTR_UID) &&
  568              (attr->ia_uid != server->m.uid)))
  569                 goto out;
  570 
  571         if (((attr->ia_valid & ATTR_GID) &&
  572              (attr->ia_gid != server->m.gid)))
  573                 goto out;
  574 
  575         if (((attr->ia_valid & ATTR_MODE) &&
  576              (attr->ia_mode &
  577               ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
  578                 goto out;
  579 
  580         info_mask = 0;
  581         memset(&info, 0, sizeof(info));
  582 
  583 #if 1 
  584         if ((attr->ia_valid & ATTR_MODE) != 0)
  585         {
  586                 if (S_ISDIR(inode->i_mode)) {
  587                         umode_t newmode;
  588 
  589                         info_mask |= DM_ATTRIBUTES;
  590                         newmode = attr->ia_mode;
  591                         newmode &= NCP_SERVER(inode)->m.dir_mode;
  592 
  593                         if (newmode & 0222)
  594                                 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  595                         else
  596                                 info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  597                 } else if (!S_ISREG(inode->i_mode))
  598                 {
  599                         return -EPERM;
  600                 }
  601                 else
  602                 {
  603                         umode_t newmode;
  604 #ifdef CONFIG_NCPFS_EXTRAS                      
  605                         int extras;
  606                         
  607                         extras = server->m.flags & NCP_MOUNT_EXTRAS;
  608 #endif
  609                         info_mask |= DM_ATTRIBUTES;
  610                         newmode=attr->ia_mode;
  611 #ifdef CONFIG_NCPFS_EXTRAS
  612                         if (!extras)
  613 #endif
  614                                 newmode &= server->m.file_mode;
  615 
  616                         if (newmode & 0222) /* any write bit set */
  617                         {
  618                                 info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  619                         }
  620                         else
  621                         {
  622                                 info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  623                         }
  624 #ifdef CONFIG_NCPFS_EXTRAS
  625                         if (extras) {
  626                                 if (newmode & 0111) /* any execute bit set */
  627                                         info.attributes |= aSHARED | aSYSTEM;
  628                                 /* read for group/world and not in default file_mode */
  629                                 else if (newmode & ~server->m.file_mode & 0444)
  630                                         info.attributes |= aSHARED;
  631                         }
  632 #endif
  633                 }
  634         }
  635 #endif
  636 
  637         if ((attr->ia_valid & ATTR_CTIME) != 0) {
  638                 info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
  639                 ncp_date_unix2dos(attr->ia_ctime,
  640                              &(info.creationTime), &(info.creationDate));
  641                 info.creationTime = le16_to_cpu(info.creationTime);
  642                 info.creationDate = le16_to_cpu(info.creationDate);
  643         }
  644         if ((attr->ia_valid & ATTR_MTIME) != 0) {
  645                 info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
  646                 ncp_date_unix2dos(attr->ia_mtime,
  647                                   &(info.modifyTime), &(info.modifyDate));
  648                 info.modifyTime = le16_to_cpu(info.modifyTime);
  649                 info.modifyDate = le16_to_cpu(info.modifyDate);
  650         }
  651         if ((attr->ia_valid & ATTR_ATIME) != 0) {
  652                 __u16 dummy;
  653                 info_mask |= (DM_LAST_ACCESS_DATE);
  654                 ncp_date_unix2dos(attr->ia_atime,
  655                                   &(dummy), &(info.lastAccessDate));
  656                 info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
  657         }
  658         if (info_mask != 0) {
  659                 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
  660                                       inode, info_mask, &info);
  661                 if (result != 0) {
  662                         result = -EACCES;
  663 
  664                         if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
  665                                 /* NetWare seems not to allow this. I
  666                                    do not know why. So, just tell the
  667                                    user everything went fine. This is
  668                                    a terrible hack, but I do not know
  669                                    how to do this correctly. */
  670                                 result = 0;
  671                         }
  672                 }
  673 #ifdef CONFIG_NCPFS_STRONG              
  674                 if ((!result) && (info_mask & DM_ATTRIBUTES))
  675                         NCP_FINFO(inode)->nwattr = info.attributes;
  676 #endif
  677         }
  678         if ((attr->ia_valid & ATTR_SIZE) != 0) {
  679                 int written;
  680 
  681                 DPRINTK("ncpfs: trying to change size to %ld\n",
  682                         attr->ia_size);
  683 
  684                 if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
  685                         return -EACCES;
  686                 }
  687                 ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
  688                           attr->ia_size, 0, "", &written);
  689 
  690                 /* According to ndir, the changes only take effect after
  691                    closing the file */
  692                 ncp_inode_close(inode);
  693                 result = ncp_make_closed(inode);
  694                 if (!result)
  695                         result = vmtruncate(inode, attr->ia_size);
  696         }
  697 out:
  698         return result;
  699 }
  700 
  701 #ifdef DEBUG_NCP_MALLOC
  702 int ncp_malloced;
  703 int ncp_current_malloced;
  704 #endif
  705 
  706 static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
  707 
  708 static int __init init_ncp_fs(void)
  709 {
  710         DPRINTK("ncpfs: init_module called\n");
  711 
  712 #ifdef DEBUG_NCP_MALLOC
  713         ncp_malloced = 0;
  714         ncp_current_malloced = 0;
  715 #endif
  716         return register_filesystem(&ncp_fs_type);
  717 }
  718 
  719 static void __exit exit_ncp_fs(void)
  720 {
  721         DPRINTK("ncpfs: cleanup_module called\n");
  722         unregister_filesystem(&ncp_fs_type);
  723 #ifdef DEBUG_NCP_MALLOC
  724         PRINTK("ncp_malloced: %d\n", ncp_malloced);
  725         PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
  726 #endif
  727 }
  728 
  729 EXPORT_NO_SYMBOLS;
  730 
  731 module_init(init_ncp_fs)
  732 module_exit(exit_ncp_fs)
  733 MODULE_LICENSE("GPL");

Cache object: c8b949cba217e14facc458a24bf690d6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.