Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
symlink.c
Go to the documentation of this file.
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 
13 static 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;
65 fail:
66  SetPageError(page);
67  kunmap(page);
68  unlock_page(page);
69  return err;
70 }
71 
73  .readpage = affs_symlink_readpage,
74 };
75 
77  .readlink = generic_readlink,
78  .follow_link = page_follow_link_light,
79  .put_link = page_put_link,
80  .setattr = affs_notify_change,
81 };