The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/hfs/file_cap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   23 #include "hfs.h"
   24 #include <linux/hfs_fs_sb.h>
   25 #include <linux/hfs_fs_i.h>
   26 #include <linux/hfs_fs.h>
   27 
   28 /*================ Forward declarations ================*/
   29 static loff_t      cap_info_llseek(struct file *, loff_t,
   30                                    int);
   31 static hfs_rwret_t cap_info_read(struct file *, char *,
   32                                  hfs_rwarg_t, loff_t *);
   33 static hfs_rwret_t cap_info_write(struct file *, const char *,
   34                                   hfs_rwarg_t, loff_t *);
   35 /*================ Function-like macros ================*/
   36 
   37 /*
   38  * OVERLAPS()
   39  *
   40  * Determines if a given range overlaps the specified structure member
   41  */
   42 #define OVERLAPS(START, END, TYPE, MEMB) \
   43         ((END > offsetof(TYPE, MEMB)) && \
   44          (START < offsetof(TYPE, MEMB) + sizeof(((TYPE *)0)->MEMB)))
   45 
   46 /*================ Global variables ================*/
   47 
   48 struct file_operations hfs_cap_info_operations = {
   49         llseek:         cap_info_llseek,
   50         read:           cap_info_read,
   51         write:          cap_info_write,
   52         fsync:          file_fsync,
   53 };
   54 
   55 struct inode_operations hfs_cap_info_inode_operations = {
   56         setattr:        hfs_notify_change_cap,
   57 };
   58 
   59 /*================ File-local functions ================*/
   60 
   61 /*
   62  * cap_build_meta()
   63  *
   64  * Build the metadata structure.
   65  */
   66 static void cap_build_meta(struct hfs_cap_info *meta,
   67                            struct hfs_cat_entry *entry)
   68 {
   69         memset(meta, 0, sizeof(*meta));
   70         memcpy(meta->fi_fndr, &entry->info, 32);
   71         if ((entry->type == HFS_CDR_FIL) &&
   72             (entry->u.file.flags & HFS_FIL_LOCK)) {
   73                 /* Couple the locked bit of the file to the
   74                    AFP {write,rename,delete} inhibit bits. */
   75                 hfs_put_hs(HFS_AFP_RDONLY, meta->fi_attr);
   76         }
   77         meta->fi_magic1 = HFS_CAP_MAGIC1;
   78         meta->fi_version = HFS_CAP_VERSION;
   79         meta->fi_magic = HFS_CAP_MAGIC;
   80         meta->fi_bitmap = HFS_CAP_LONGNAME;
   81         memcpy(meta->fi_macfilename, entry->key.CName.Name,
   82                entry->key.CName.Len);
   83         meta->fi_datemagic = HFS_CAP_DMAGIC;
   84         meta->fi_datevalid = HFS_CAP_MDATE | HFS_CAP_CDATE;
   85         hfs_put_nl(hfs_m_to_htime(entry->create_date), meta->fi_ctime);
   86         hfs_put_nl(hfs_m_to_htime(entry->modify_date), meta->fi_mtime);
   87         hfs_put_nl(CURRENT_TIME,                       meta->fi_utime);
   88 }
   89 
   90 static loff_t cap_info_llseek(struct file *file, loff_t offset, int origin)
   91 {
   92         long long retval;
   93 
   94         switch (origin) {
   95                 case 2:
   96                         offset += file->f_dentry->d_inode->i_size;
   97                         break;
   98                 case 1:
   99                         offset += file->f_pos;
  100         }
  101         retval = -EINVAL;
  102         if (offset>=0 && offset<=HFS_FORK_MAX) {
  103                 if (offset != file->f_pos) {
  104                         file->f_pos = offset;
  105                         file->f_reada = 0;
  106                         file->f_version = ++event;
  107                 }
  108                 retval = offset;
  109         }
  110         return retval;
  111 }
  112 
  113 /*
  114  * cap_info_read()
  115  *
  116  * This is the read() entry in the file_operations structure for CAP
  117  * metadata files.  The purpose is to transfer up to 'count' bytes
  118  * from the file corresponding to 'inode' beginning at offset
  119  * 'file->f_pos' to user-space at the address 'buf'.  The return value
  120  * is the number of bytes actually transferred.
  121  */
  122 static hfs_rwret_t cap_info_read(struct file *filp, char *buf,
  123                                  hfs_rwarg_t count, loff_t *ppos)
  124 {
  125         struct inode *inode = filp->f_dentry->d_inode;
  126         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  127         hfs_s32 left, size, read = 0;
  128         hfs_u32 pos;
  129 
  130         if (!S_ISREG(inode->i_mode)) {
  131                 hfs_warn("hfs_cap_info_read: mode = %07o\n", inode->i_mode);
  132                 return -EINVAL;
  133         }
  134 
  135         pos = *ppos;
  136         if (pos > HFS_FORK_MAX) {
  137                 return 0;
  138         }
  139         size = inode->i_size;
  140         if (pos > size) {
  141                 left = 0;
  142         } else {
  143                 left = size - pos;
  144         }
  145         if (left > count) {
  146                 left = count;
  147         }
  148         if (left <= 0) {
  149                 return 0;
  150         }
  151 
  152         if (pos < sizeof(struct hfs_cap_info)) {
  153                 int memcount = sizeof(struct hfs_cap_info) - pos;
  154                 struct hfs_cap_info meta;
  155 
  156                 if (memcount > left) {
  157                         memcount = left;
  158                 }
  159                 cap_build_meta(&meta, entry);
  160                 memcount -= copy_to_user(buf, ((char *)&meta) + pos, memcount);
  161                 left -= memcount;
  162                 read += memcount;
  163                 pos += memcount;
  164                 buf += memcount;
  165         }
  166 
  167         if (left > 0) {
  168                 clear_user(buf, left);
  169                 pos += left;
  170         }
  171 
  172         if (read) {
  173                 inode->i_atime = CURRENT_TIME;
  174                 *ppos = pos;
  175                 mark_inode_dirty(inode);
  176         }
  177 
  178         return read;
  179 }
  180 
  181 /*
  182  * cap_info_write()
  183  *
  184  * This is the write() entry in the file_operations structure for CAP
  185  * metadata files.  The purpose is to transfer up to 'count' bytes
  186  * to the file corresponding to 'inode' beginning at offset
  187  * '*ppos' from user-space at the address 'buf'.
  188  * The return value is the number of bytes actually transferred.
  189  */
  190 static hfs_rwret_t cap_info_write(struct file *filp, const char *buf, 
  191                                   hfs_rwarg_t count, loff_t *ppos)
  192 {
  193         struct inode *inode = filp->f_dentry->d_inode;
  194         hfs_u32 pos;
  195 
  196         if (!S_ISREG(inode->i_mode)) {
  197                 hfs_warn("hfs_file_write: mode = %07o\n", inode->i_mode);
  198                 return -EINVAL;
  199         }
  200         if (count <= 0) {
  201                 return 0;
  202         }
  203         
  204         pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
  205 
  206         if (pos > HFS_FORK_MAX) {
  207                 return 0;
  208         }
  209 
  210         *ppos += count;
  211         if (*ppos > HFS_FORK_MAX) {
  212                 *ppos = HFS_FORK_MAX;
  213                 count = HFS_FORK_MAX - pos;
  214         }
  215 
  216         if (*ppos > inode->i_size)
  217                 inode->i_size = *ppos;
  218 
  219         /* Only deal with the part we store in memory */
  220         if (pos < sizeof(struct hfs_cap_info)) {
  221                 int end, mem_count;
  222                 struct hfs_cat_entry *entry = HFS_I(inode)->entry;
  223                 struct hfs_cap_info meta;
  224 
  225                 mem_count = sizeof(struct hfs_cap_info) - pos;
  226                 if (mem_count > count) {
  227                         mem_count = count;
  228                 }
  229                 end = pos + mem_count;
  230 
  231                 cap_build_meta(&meta, entry);
  232                 mem_count -= copy_from_user(((char *)&meta) + pos, buf, mem_count);
  233 
  234                 /* Update finder attributes if changed */
  235                 if (OVERLAPS(pos, end, struct hfs_cap_info, fi_fndr)) {
  236                         memcpy(&entry->info, meta.fi_fndr, 32);
  237                         hfs_cat_mark_dirty(entry);
  238                 }
  239 
  240                 /* Update file flags if changed */
  241                 if (OVERLAPS(pos, end, struct hfs_cap_info, fi_attr) &&
  242                     (entry->type == HFS_CDR_FIL)) {
  243                         int locked = hfs_get_ns(&meta.fi_attr) &
  244                                                         htons(HFS_AFP_WRI);
  245                         hfs_u8 new_flags;
  246 
  247                         if (locked) {
  248                                 new_flags = entry->u.file.flags | HFS_FIL_LOCK;
  249                         } else {
  250                                 new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
  251                         }
  252 
  253                         if (new_flags != entry->u.file.flags) {
  254                                 entry->u.file.flags = new_flags;
  255                                 hfs_cat_mark_dirty(entry);
  256                                 hfs_file_fix_mode(entry);
  257                         }
  258                 }
  259 
  260                 /* Update CrDat if changed */
  261                 if (OVERLAPS(pos, end, struct hfs_cap_info, fi_ctime)) {
  262                         entry->create_date =
  263                                 hfs_h_to_mtime(hfs_get_nl(meta.fi_ctime));
  264                         hfs_cat_mark_dirty(entry);
  265                 }
  266 
  267                 /* Update MdDat if changed */
  268                 if (OVERLAPS(pos, end, struct hfs_cap_info, fi_mtime)) {
  269                         entry->modify_date =
  270                                 hfs_h_to_mtime(hfs_get_nl(meta.fi_mtime));
  271                         hfs_cat_mark_dirty(entry);
  272                 }
  273         }
  274 
  275         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
  276         mark_inode_dirty(inode);
  277         return count;
  278 }

Cache object: 31d86713b04332f63a4940ab9a9dbb82


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.