symlink.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * linux/fs/ncpfs/symlink.c
  3. *
  4. * Code for allowing symbolic links on NCPFS (i.e. NetWare)
  5. * Symbolic links are not supported on native NetWare, so we use an
  6. * infrequently-used flag (Sh) and store a two-word magic header in
  7. * the file to make sure we don't accidentally use a non-link file
  8. * as a link.
  9. *
  10. * When using the NFS namespace, we set the mode to indicate a symlink and
  11. * don't bother with the magic numbers.
  12. *
  13. * from linux/fs/ext2/symlink.c
  14. *
  15. * Copyright (C) 1998-99, Frank A. Vorstenbosch
  16. *
  17. * ncpfs symlink handling code
  18. * NLS support (c) 1999 Petr Vandrovec
  19. * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
  20. *
  21. */
  22. #include <asm/uaccess.h>
  23. #include <linux/errno.h>
  24. #include <linux/fs.h>
  25. #include <linux/time.h>
  26. #include <linux/slab.h>
  27. #include <linux/mm.h>
  28. #include <linux/stat.h>
  29. #include "ncp_fs.h"
  30. /* these magic numbers must appear in the symlink file -- this makes it a bit
  31. more resilient against the magic attributes being set on random files. */
  32. #define NCP_SYMLINK_MAGIC0 cpu_to_le32(0x6c6d7973) /* "symlnk->" */
  33. #define NCP_SYMLINK_MAGIC1 cpu_to_le32(0x3e2d6b6e)
  34. /* ----- read a symbolic link ------------------------------------------ */
  35. static int ncp_symlink_readpage(struct file *file, struct page *page)
  36. {
  37. struct inode *inode = page->mapping->host;
  38. int error, length, len;
  39. char *link, *rawlink;
  40. char *buf = kmap(page);
  41. error = -ENOMEM;
  42. rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
  43. if (!rawlink)
  44. goto fail;
  45. if (ncp_make_open(inode,O_RDONLY))
  46. goto failEIO;
  47. error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
  48. 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length);
  49. ncp_inode_close(inode);
  50. /* Close file handle if no other users... */
  51. ncp_make_closed(inode);
  52. if (error)
  53. goto failEIO;
  54. if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
  55. if (length<NCP_MIN_SYMLINK_SIZE ||
  56. ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
  57. ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
  58. goto failEIO;
  59. link = rawlink + 8;
  60. length -= 8;
  61. } else {
  62. link = rawlink;
  63. }
  64. len = NCP_MAX_SYMLINK_SIZE;
  65. error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
  66. kfree(rawlink);
  67. if (error)
  68. goto fail;
  69. SetPageUptodate(page);
  70. kunmap(page);
  71. unlock_page(page);
  72. return 0;
  73. failEIO:
  74. error = -EIO;
  75. kfree(rawlink);
  76. fail:
  77. SetPageError(page);
  78. kunmap(page);
  79. unlock_page(page);
  80. return error;
  81. }
  82. /*
  83. * symlinks can't do much...
  84. */
  85. const struct address_space_operations ncp_symlink_aops = {
  86. .readpage = ncp_symlink_readpage,
  87. };
  88. /* ----- create a new symbolic link -------------------------------------- */
  89. int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
  90. struct inode *inode;
  91. char *rawlink;
  92. int length, err, i, outlen;
  93. int kludge;
  94. int mode;
  95. __le32 attr;
  96. unsigned int hdr;
  97. DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
  98. if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
  99. kludge = 0;
  100. else
  101. #ifdef CONFIG_NCPFS_EXTRAS
  102. if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)
  103. kludge = 1;
  104. else
  105. #endif
  106. /* EPERM is returned by VFS if symlink procedure does not exist */
  107. return -EPERM;
  108. rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
  109. if (!rawlink)
  110. return -ENOMEM;
  111. if (kludge) {
  112. mode = 0;
  113. attr = aSHARED | aHIDDEN;
  114. ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
  115. ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
  116. hdr = 8;
  117. } else {
  118. mode = S_IFLNK | S_IRWXUGO;
  119. attr = 0;
  120. hdr = 0;
  121. }
  122. length = strlen(symname);
  123. /* map to/from server charset, do not touch upper/lower case as
  124. symlink can point out of ncp filesystem */
  125. outlen = NCP_MAX_SYMLINK_SIZE - hdr;
  126. err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0);
  127. if (err)
  128. goto failfree;
  129. outlen += hdr;
  130. err = -EIO;
  131. if (ncp_create_new(dir,dentry,mode,0,attr)) {
  132. goto failfree;
  133. }
  134. inode=dentry->d_inode;
  135. if (ncp_make_open(inode, O_WRONLY))
  136. goto failfree;
  137. if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
  138. 0, outlen, rawlink, &i) || i!=outlen) {
  139. goto fail;
  140. }
  141. ncp_inode_close(inode);
  142. ncp_make_closed(inode);
  143. kfree(rawlink);
  144. return 0;
  145. fail:;
  146. ncp_inode_close(inode);
  147. ncp_make_closed(inode);
  148. failfree:;
  149. kfree(rawlink);
  150. return err;
  151. }
  152. /* ----- EOF ----- */