symlink.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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 <linux/config.h>
  23. #include <asm/uaccess.h>
  24. #include <linux/errno.h>
  25. #include <linux/fs.h>
  26. #include <linux/ncp_fs.h>
  27. #include <linux/time.h>
  28. #include <linux/mm.h>
  29. #include <linux/stat.h>
  30. #include "ncplib_kernel.h"
  31. /* these magic numbers must appear in the symlink file -- this makes it a bit
  32. more resilient against the magic attributes being set on random files. */
  33. #define NCP_SYMLINK_MAGIC0 cpu_to_le32(0x6c6d7973) /* "symlnk->" */
  34. #define NCP_SYMLINK_MAGIC1 cpu_to_le32(0x3e2d6b6e)
  35. /* ----- read a symbolic link ------------------------------------------ */
  36. static int ncp_symlink_readpage(struct file *file, struct page *page)
  37. {
  38. struct inode *inode = page->mapping->host;
  39. int error, length, len;
  40. char *link, *rawlink;
  41. char *buf = kmap(page);
  42. error = -ENOMEM;
  43. rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
  44. if (!rawlink)
  45. goto fail;
  46. if (ncp_make_open(inode,O_RDONLY))
  47. goto failEIO;
  48. error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
  49. 0,NCP_MAX_SYMLINK_SIZE,rawlink,&length);
  50. ncp_inode_close(inode);
  51. /* Close file handle if no other users... */
  52. ncp_make_closed(inode);
  53. if (error)
  54. goto failEIO;
  55. if (NCP_FINFO(inode)->flags & NCPI_KLUDGE_SYMLINK) {
  56. if (length<NCP_MIN_SYMLINK_SIZE ||
  57. ((__le32 *)rawlink)[0]!=NCP_SYMLINK_MAGIC0 ||
  58. ((__le32 *)rawlink)[1]!=NCP_SYMLINK_MAGIC1)
  59. goto failEIO;
  60. link = rawlink + 8;
  61. length -= 8;
  62. } else {
  63. link = rawlink;
  64. }
  65. len = NCP_MAX_SYMLINK_SIZE;
  66. error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link, length, 0);
  67. kfree(rawlink);
  68. if (error)
  69. goto fail;
  70. SetPageUptodate(page);
  71. kunmap(page);
  72. unlock_page(page);
  73. return 0;
  74. failEIO:
  75. error = -EIO;
  76. kfree(rawlink);
  77. fail:
  78. SetPageError(page);
  79. kunmap(page);
  80. unlock_page(page);
  81. return error;
  82. }
  83. /*
  84. * symlinks can't do much...
  85. */
  86. struct address_space_operations ncp_symlink_aops = {
  87. .readpage = ncp_symlink_readpage,
  88. };
  89. /* ----- create a new symbolic link -------------------------------------- */
  90. int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
  91. struct inode *inode;
  92. char *rawlink;
  93. int length, err, i, outlen;
  94. int kludge;
  95. int mode;
  96. __le32 attr;
  97. unsigned int hdr;
  98. DPRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
  99. if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber))
  100. kludge = 0;
  101. else
  102. #ifdef CONFIG_NCPFS_EXTRAS
  103. if (NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS)
  104. kludge = 1;
  105. else
  106. #endif
  107. /* EPERM is returned by VFS if symlink procedure does not exist */
  108. return -EPERM;
  109. rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
  110. if (!rawlink)
  111. return -ENOMEM;
  112. if (kludge) {
  113. mode = 0;
  114. attr = aSHARED | aHIDDEN;
  115. ((__le32 *)rawlink)[0]=NCP_SYMLINK_MAGIC0;
  116. ((__le32 *)rawlink)[1]=NCP_SYMLINK_MAGIC1;
  117. hdr = 8;
  118. } else {
  119. mode = S_IFLNK | S_IRWXUGO;
  120. attr = 0;
  121. hdr = 0;
  122. }
  123. length = strlen(symname);
  124. /* map to/from server charset, do not touch upper/lower case as
  125. symlink can point out of ncp filesystem */
  126. outlen = NCP_MAX_SYMLINK_SIZE - hdr;
  127. err = ncp_io2vol(NCP_SERVER(dir), rawlink + hdr, &outlen, symname, length, 0);
  128. if (err)
  129. goto failfree;
  130. outlen += hdr;
  131. err = -EIO;
  132. if (ncp_create_new(dir,dentry,mode,0,attr)) {
  133. goto failfree;
  134. }
  135. inode=dentry->d_inode;
  136. if (ncp_make_open(inode, O_WRONLY))
  137. goto failfree;
  138. if (ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
  139. 0, outlen, rawlink, &i) || i!=outlen) {
  140. goto fail;
  141. }
  142. ncp_inode_close(inode);
  143. ncp_make_closed(inode);
  144. kfree(rawlink);
  145. return 0;
  146. fail:;
  147. ncp_inode_close(inode);
  148. ncp_make_closed(inode);
  149. failfree:;
  150. kfree(rawlink);
  151. return err;
  152. }
  153. /* ----- EOF ----- */