file_cap.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/hfs/file_cap.c
  3.  *
  4.  * Copyright (C) 1995-1997  Paul H. Hargrove
  5.  * This file may be distributed under the terms of the GNU General Public License.
  6.  *
  7.  * This file contains the file_ops and inode_ops for the metadata
  8.  * files under the CAP representation.
  9.  *
  10.  * The source code distribution of the Columbia AppleTalk Package for
  11.  * UNIX, version 6.0, (CAP) was used as a specification of the
  12.  * location and format of files used by CAP's Aufs.  No code from CAP
  13.  * appears in hfs_fs.  hfs_fs is not a work ``derived'' from CAP in
  14.  * the sense of intellectual property law.
  15.  *
  16.  * "XXX" in a comment is a note to myself to consider changing something.
  17.  *
  18.  * In function preconditions the term "valid" applied to a pointer to
  19.  * a structure means that the pointer is non-NULL and the structure it
  20.  * points to has all fields initialized to consistent values.
  21.  */
  22. #include "hfs.h"
  23. #include <linux/hfs_fs_sb.h>
  24. #include <linux/hfs_fs_i.h>
  25. #include <linux/hfs_fs.h>
  26. /*================ Forward declarations ================*/
  27. static loff_t      cap_info_llseek(struct file *, loff_t,
  28.                                    int);
  29. static hfs_rwret_t cap_info_read(struct file *, char *,
  30.  hfs_rwarg_t, loff_t *);
  31. static hfs_rwret_t cap_info_write(struct file *, const char *,
  32.   hfs_rwarg_t, loff_t *);
  33. /*================ Function-like macros ================*/
  34. /*
  35.  * OVERLAPS()
  36.  *
  37.  * Determines if a given range overlaps the specified structure member
  38.  */
  39. #define OVERLAPS(START, END, TYPE, MEMB) 
  40. ((END > offsetof(TYPE, MEMB)) && 
  41.  (START < offsetof(TYPE, MEMB) + sizeof(((TYPE *)0)->MEMB)))
  42. /*================ Global variables ================*/
  43. struct file_operations hfs_cap_info_operations = {
  44. llseek: cap_info_llseek,
  45. read: cap_info_read,
  46. write: cap_info_write,
  47. fsync: file_fsync,
  48. };
  49. struct inode_operations hfs_cap_info_inode_operations = {
  50. setattr: hfs_notify_change_cap,
  51. };
  52. /*================ File-local functions ================*/
  53. /*
  54.  * cap_build_meta()
  55.  *
  56.  * Build the metadata structure.
  57.  */
  58. static void cap_build_meta(struct hfs_cap_info *meta,
  59.    struct hfs_cat_entry *entry)
  60. {
  61. memset(meta, 0, sizeof(*meta));
  62. memcpy(meta->fi_fndr, &entry->info, 32);
  63. if ((entry->type == HFS_CDR_FIL) &&
  64.     (entry->u.file.flags & HFS_FIL_LOCK)) {
  65. /* Couple the locked bit of the file to the
  66.    AFP {write,rename,delete} inhibit bits. */
  67. hfs_put_hs(HFS_AFP_RDONLY, meta->fi_attr);
  68. }
  69. meta->fi_magic1 = HFS_CAP_MAGIC1;
  70. meta->fi_version = HFS_CAP_VERSION;
  71. meta->fi_magic = HFS_CAP_MAGIC;
  72. meta->fi_bitmap = HFS_CAP_LONGNAME;
  73. memcpy(meta->fi_macfilename, entry->key.CName.Name,
  74.        entry->key.CName.Len);
  75. meta->fi_datemagic = HFS_CAP_DMAGIC;
  76. meta->fi_datevalid = HFS_CAP_MDATE | HFS_CAP_CDATE;
  77. hfs_put_nl(hfs_m_to_htime(entry->create_date), meta->fi_ctime);
  78. hfs_put_nl(hfs_m_to_htime(entry->modify_date), meta->fi_mtime);
  79. hfs_put_nl(CURRENT_TIME,                       meta->fi_utime);
  80. }
  81. static loff_t cap_info_llseek(struct file *file, loff_t offset, int origin)
  82. {
  83. long long retval;
  84. switch (origin) {
  85. case 2:
  86. offset += file->f_dentry->d_inode->i_size;
  87. break;
  88. case 1:
  89. offset += file->f_pos;
  90. }
  91. retval = -EINVAL;
  92. if (offset>=0 && offset<=HFS_FORK_MAX) {
  93. if (offset != file->f_pos) {
  94. file->f_pos = offset;
  95. file->f_reada = 0;
  96. file->f_version = ++event;
  97. }
  98. retval = offset;
  99. }
  100. return retval;
  101. }
  102. /*
  103.  * cap_info_read()
  104.  *
  105.  * This is the read() entry in the file_operations structure for CAP
  106.  * metadata files.  The purpose is to transfer up to 'count' bytes
  107.  * from the file corresponding to 'inode' beginning at offset
  108.  * 'file->f_pos' to user-space at the address 'buf'.  The return value
  109.  * is the number of bytes actually transferred.
  110.  */
  111. static hfs_rwret_t cap_info_read(struct file *filp, char *buf,
  112.  hfs_rwarg_t count, loff_t *ppos)
  113. {
  114. struct inode *inode = filp->f_dentry->d_inode;
  115. struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  116. hfs_s32 left, size, read = 0;
  117. hfs_u32 pos;
  118. if (!S_ISREG(inode->i_mode)) {
  119. hfs_warn("hfs_cap_info_read: mode = %07on", inode->i_mode);
  120. return -EINVAL;
  121. }
  122. pos = *ppos;
  123. if (pos > HFS_FORK_MAX) {
  124. return 0;
  125. }
  126. size = inode->i_size;
  127. if (pos > size) {
  128. left = 0;
  129. } else {
  130. left = size - pos;
  131. }
  132. if (left > count) {
  133. left = count;
  134. }
  135. if (left <= 0) {
  136. return 0;
  137. }
  138. if (pos < sizeof(struct hfs_cap_info)) {
  139. int memcount = sizeof(struct hfs_cap_info) - pos;
  140. struct hfs_cap_info meta;
  141. if (memcount > left) {
  142. memcount = left;
  143. }
  144. cap_build_meta(&meta, entry);
  145. memcount -= copy_to_user(buf, ((char *)&meta) + pos, memcount);
  146. left -= memcount;
  147. read += memcount;
  148. pos += memcount;
  149. buf += memcount;
  150. }
  151. if (left > 0) {
  152. clear_user(buf, left);
  153.         pos += left;
  154. }
  155. if (read) {
  156. inode->i_atime = CURRENT_TIME;
  157. *ppos = pos;
  158. mark_inode_dirty(inode);
  159. }
  160. return read;
  161. }
  162. /*
  163.  * cap_info_write()
  164.  *
  165.  * This is the write() entry in the file_operations structure for CAP
  166.  * metadata files.  The purpose is to transfer up to 'count' bytes
  167.  * to the file corresponding to 'inode' beginning at offset
  168.  * '*ppos' from user-space at the address 'buf'.
  169.  * The return value is the number of bytes actually transferred.
  170.  */
  171. static hfs_rwret_t cap_info_write(struct file *filp, const char *buf, 
  172.   hfs_rwarg_t count, loff_t *ppos)
  173. {
  174.         struct inode *inode = filp->f_dentry->d_inode;
  175. hfs_u32 pos;
  176. if (!S_ISREG(inode->i_mode)) {
  177. hfs_warn("hfs_file_write: mode = %07on", inode->i_mode);
  178. return -EINVAL;
  179. }
  180. if (count <= 0) {
  181. return 0;
  182. }
  183. pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
  184. if (pos > HFS_FORK_MAX) {
  185. return 0;
  186. }
  187. *ppos += count;
  188. if (*ppos > HFS_FORK_MAX) {
  189. *ppos = HFS_FORK_MAX;
  190. count = HFS_FORK_MAX - pos;
  191. }
  192. if (*ppos > inode->i_size)
  193.         inode->i_size = *ppos;
  194. /* Only deal with the part we store in memory */
  195. if (pos < sizeof(struct hfs_cap_info)) {
  196. int end, mem_count;
  197. struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  198. struct hfs_cap_info meta;
  199. mem_count = sizeof(struct hfs_cap_info) - pos;
  200. if (mem_count > count) {
  201. mem_count = count;
  202. }
  203. end = pos + mem_count;
  204. cap_build_meta(&meta, entry);
  205. mem_count -= copy_from_user(((char *)&meta) + pos, buf, mem_count);
  206. /* Update finder attributes if changed */
  207. if (OVERLAPS(pos, end, struct hfs_cap_info, fi_fndr)) {
  208. memcpy(&entry->info, meta.fi_fndr, 32);
  209. hfs_cat_mark_dirty(entry);
  210. }
  211. /* Update file flags if changed */
  212. if (OVERLAPS(pos, end, struct hfs_cap_info, fi_attr) &&
  213.     (entry->type == HFS_CDR_FIL)) {
  214. int locked = hfs_get_ns(&meta.fi_attr) &
  215. htons(HFS_AFP_WRI);
  216. hfs_u8 new_flags;
  217. if (locked) {
  218. new_flags = entry->u.file.flags | HFS_FIL_LOCK;
  219. } else {
  220. new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
  221. }
  222. if (new_flags != entry->u.file.flags) {
  223. entry->u.file.flags = new_flags;
  224. hfs_cat_mark_dirty(entry);
  225. hfs_file_fix_mode(entry);
  226. }
  227. }
  228. /* Update CrDat if changed */
  229. if (OVERLAPS(pos, end, struct hfs_cap_info, fi_ctime)) {
  230. entry->create_date =
  231. hfs_h_to_mtime(hfs_get_nl(meta.fi_ctime));
  232. hfs_cat_mark_dirty(entry);
  233. }
  234. /* Update MdDat if changed */
  235. if (OVERLAPS(pos, end, struct hfs_cap_info, fi_mtime)) {
  236. entry->modify_date =
  237. hfs_h_to_mtime(hfs_get_nl(meta.fi_mtime));
  238. hfs_cat_mark_dirty(entry);
  239. }
  240. }
  241. inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  242. mark_inode_dirty(inode);
  243. return count;
  244. }