linux/fs/affs/symlink.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/affs/symlink.c
   3 *
   4 *  1995  Hans-Joachim Widmaier - Modified for affs.
   5 *
   6 *  Copyright (C) 1991, 1992  Linus Torvalds
   7 *
   8 *  affs symlink handling code
   9 */
  10
  11#include "affs.h"
  12
  13static int affs_symlink_readpage(struct file *file, struct page *page)
  14{
  15        struct buffer_head *bh;
  16        struct inode *inode = page->mapping->host;
  17        char *link = kmap(page);
  18        struct slink_front *lf;
  19        int err;
  20        int                      i, j;
  21        char                     c;
  22        char                     lc;
  23
  24        pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
  25
  26        err = -EIO;
  27        bh = affs_bread(inode->i_sb, inode->i_ino);
  28        if (!bh)
  29                goto fail;
  30        i  = 0;
  31        j  = 0;
  32        lf = (struct slink_front *)bh->b_data;
  33        lc = 0;
  34
  35        if (strchr(lf->symname,':')) {  /* Handle assign or volume name */
  36                struct affs_sb_info *sbi = AFFS_SB(inode->i_sb);
  37                char *pf;
  38                spin_lock(&sbi->symlink_lock);
  39                pf = sbi->s_prefix ? sbi->s_prefix : "/";
  40                while (i < 1023 && (c = pf[i]))
  41                        link[i++] = c;
  42                spin_unlock(&sbi->symlink_lock);
  43                while (i < 1023 && lf->symname[j] != ':')
  44                        link[i++] = lf->symname[j++];
  45                if (i < 1023)
  46                        link[i++] = '/';
  47                j++;
  48                lc = '/';
  49        }
  50        while (i < 1023 && (c = lf->symname[j])) {
  51                if (c == '/' && lc == '/' && i < 1020) {        /* parent dir */
  52                        link[i++] = '.';
  53                        link[i++] = '.';
  54                }
  55                link[i++] = c;
  56                lc = c;
  57                j++;
  58        }
  59        link[i] = '\0';
  60        affs_brelse(bh);
  61        SetPageUptodate(page);
  62        kunmap(page);
  63        unlock_page(page);
  64        return 0;
  65fail:
  66        SetPageError(page);
  67        kunmap(page);
  68        unlock_page(page);
  69        return err;
  70}
  71
  72const struct address_space_operations affs_symlink_aops = {
  73        .readpage       = affs_symlink_readpage,
  74};
  75
  76const struct inode_operations affs_symlink_inode_operations = {
  77        .readlink       = generic_readlink,
  78        .follow_link    = page_follow_link_light,
  79        .put_link       = page_put_link,
  80        .setattr        = affs_notify_change,
  81};
  82