OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [hfs/] [file_cap.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.