1 |
62 |
marcus.erl |
#include <linux/fs.h>
|
2 |
|
|
#include <linux/buffer_head.h>
|
3 |
|
|
#include <linux/exportfs.h>
|
4 |
|
|
#include <linux/iso_fs.h>
|
5 |
|
|
#include <asm/unaligned.h>
|
6 |
|
|
|
7 |
|
|
enum isofs_file_format {
|
8 |
|
|
isofs_file_normal = 0,
|
9 |
|
|
isofs_file_sparse = 1,
|
10 |
|
|
isofs_file_compressed = 2,
|
11 |
|
|
};
|
12 |
|
|
|
13 |
|
|
/*
|
14 |
|
|
* iso fs inode data in memory
|
15 |
|
|
*/
|
16 |
|
|
struct iso_inode_info {
|
17 |
|
|
unsigned long i_iget5_block;
|
18 |
|
|
unsigned long i_iget5_offset;
|
19 |
|
|
unsigned int i_first_extent;
|
20 |
|
|
unsigned char i_file_format;
|
21 |
|
|
unsigned char i_format_parm[3];
|
22 |
|
|
unsigned long i_next_section_block;
|
23 |
|
|
unsigned long i_next_section_offset;
|
24 |
|
|
off_t i_section_size;
|
25 |
|
|
struct inode vfs_inode;
|
26 |
|
|
};
|
27 |
|
|
|
28 |
|
|
/*
|
29 |
|
|
* iso9660 super-block data in memory
|
30 |
|
|
*/
|
31 |
|
|
struct isofs_sb_info {
|
32 |
|
|
unsigned long s_ninodes;
|
33 |
|
|
unsigned long s_nzones;
|
34 |
|
|
unsigned long s_firstdatazone;
|
35 |
|
|
unsigned long s_log_zone_size;
|
36 |
|
|
unsigned long s_max_size;
|
37 |
|
|
|
38 |
|
|
unsigned char s_high_sierra; /* A simple flag */
|
39 |
|
|
unsigned char s_mapping;
|
40 |
|
|
int s_rock_offset; /* offset of SUSP fields within SU area */
|
41 |
|
|
unsigned char s_rock;
|
42 |
|
|
unsigned char s_joliet_level;
|
43 |
|
|
unsigned char s_utf8;
|
44 |
|
|
unsigned char s_cruft; /* Broken disks with high
|
45 |
|
|
byte of length containing
|
46 |
|
|
junk */
|
47 |
|
|
unsigned char s_unhide;
|
48 |
|
|
unsigned char s_nosuid;
|
49 |
|
|
unsigned char s_nodev;
|
50 |
|
|
unsigned char s_nocompress;
|
51 |
|
|
unsigned char s_hide;
|
52 |
|
|
unsigned char s_showassoc;
|
53 |
|
|
|
54 |
|
|
mode_t s_mode;
|
55 |
|
|
gid_t s_gid;
|
56 |
|
|
uid_t s_uid;
|
57 |
|
|
struct nls_table *s_nls_iocharset; /* Native language support table */
|
58 |
|
|
};
|
59 |
|
|
|
60 |
|
|
static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb)
|
61 |
|
|
{
|
62 |
|
|
return sb->s_fs_info;
|
63 |
|
|
}
|
64 |
|
|
|
65 |
|
|
static inline struct iso_inode_info *ISOFS_I(struct inode *inode)
|
66 |
|
|
{
|
67 |
|
|
return container_of(inode, struct iso_inode_info, vfs_inode);
|
68 |
|
|
}
|
69 |
|
|
|
70 |
|
|
static inline int isonum_711(char *p)
|
71 |
|
|
{
|
72 |
|
|
return *(u8 *)p;
|
73 |
|
|
}
|
74 |
|
|
static inline int isonum_712(char *p)
|
75 |
|
|
{
|
76 |
|
|
return *(s8 *)p;
|
77 |
|
|
}
|
78 |
|
|
static inline unsigned int isonum_721(char *p)
|
79 |
|
|
{
|
80 |
|
|
return le16_to_cpu(get_unaligned((__le16 *)p));
|
81 |
|
|
}
|
82 |
|
|
static inline unsigned int isonum_722(char *p)
|
83 |
|
|
{
|
84 |
|
|
return be16_to_cpu(get_unaligned((__le16 *)p));
|
85 |
|
|
}
|
86 |
|
|
static inline unsigned int isonum_723(char *p)
|
87 |
|
|
{
|
88 |
|
|
/* Ignore bigendian datum due to broken mastering programs */
|
89 |
|
|
return le16_to_cpu(get_unaligned((__le16 *)p));
|
90 |
|
|
}
|
91 |
|
|
static inline unsigned int isonum_731(char *p)
|
92 |
|
|
{
|
93 |
|
|
return le32_to_cpu(get_unaligned((__le32 *)p));
|
94 |
|
|
}
|
95 |
|
|
static inline unsigned int isonum_732(char *p)
|
96 |
|
|
{
|
97 |
|
|
return be32_to_cpu(get_unaligned((__le32 *)p));
|
98 |
|
|
}
|
99 |
|
|
static inline unsigned int isonum_733(char *p)
|
100 |
|
|
{
|
101 |
|
|
/* Ignore bigendian datum due to broken mastering programs */
|
102 |
|
|
return le32_to_cpu(get_unaligned((__le32 *)p));
|
103 |
|
|
}
|
104 |
|
|
extern int iso_date(char *, int);
|
105 |
|
|
|
106 |
|
|
struct inode; /* To make gcc happy */
|
107 |
|
|
|
108 |
|
|
extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *);
|
109 |
|
|
extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *);
|
110 |
|
|
extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *);
|
111 |
|
|
|
112 |
|
|
int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
|
113 |
|
|
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
|
114 |
|
|
|
115 |
|
|
extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
|
116 |
|
|
extern struct buffer_head *isofs_bread(struct inode *, sector_t);
|
117 |
|
|
extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
|
118 |
|
|
|
119 |
|
|
extern struct inode *isofs_iget(struct super_block *sb,
|
120 |
|
|
unsigned long block,
|
121 |
|
|
unsigned long offset);
|
122 |
|
|
|
123 |
|
|
/* Because the inode number is no longer relevant to finding the
|
124 |
|
|
* underlying meta-data for an inode, we are free to choose a more
|
125 |
|
|
* convenient 32-bit number as the inode number. The inode numbering
|
126 |
|
|
* scheme was recommended by Sergey Vlasov and Eric Lammerts. */
|
127 |
|
|
static inline unsigned long isofs_get_ino(unsigned long block,
|
128 |
|
|
unsigned long offset,
|
129 |
|
|
unsigned long bufbits)
|
130 |
|
|
{
|
131 |
|
|
return (block << (bufbits - 5)) | (offset >> 5);
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
/* Every directory can have many redundant directory entries scattered
|
135 |
|
|
* throughout the directory tree. First there is the directory entry
|
136 |
|
|
* with the name of the directory stored in the parent directory.
|
137 |
|
|
* Then, there is the "." directory entry stored in the directory
|
138 |
|
|
* itself. Finally, there are possibly many ".." directory entries
|
139 |
|
|
* stored in all the subdirectories.
|
140 |
|
|
*
|
141 |
|
|
* In order for the NFS get_parent() method to work and for the
|
142 |
|
|
* general consistency of the dcache, we need to make sure the
|
143 |
|
|
* "i_iget5_block" and "i_iget5_offset" all point to exactly one of
|
144 |
|
|
* the many redundant entries for each directory. We normalize the
|
145 |
|
|
* block and offset by always making them point to the "." directory.
|
146 |
|
|
*
|
147 |
|
|
* Notice that we do not use the entry for the directory with the name
|
148 |
|
|
* that is located in the parent directory. Even though choosing this
|
149 |
|
|
* first directory is more natural, it is much easier to find the "."
|
150 |
|
|
* entry in the NFS get_parent() method because it is implicitly
|
151 |
|
|
* encoded in the "extent + ext_attr_length" fields of _all_ the
|
152 |
|
|
* redundant entries for the directory. Thus, it can always be
|
153 |
|
|
* reached regardless of which directory entry you have in hand.
|
154 |
|
|
*
|
155 |
|
|
* This works because the "." entry is simply the first directory
|
156 |
|
|
* record when you start reading the file that holds all the directory
|
157 |
|
|
* records, and this file starts at "extent + ext_attr_length" blocks.
|
158 |
|
|
* Because the "." entry is always the first entry listed in the
|
159 |
|
|
* directories file, the normalized "offset" value is always 0.
|
160 |
|
|
*
|
161 |
|
|
* You should pass the directory entry in "de". On return, "block"
|
162 |
|
|
* and "offset" will hold normalized values. Only directories are
|
163 |
|
|
* affected making it safe to call even for non-directory file
|
164 |
|
|
* types. */
|
165 |
|
|
static inline void
|
166 |
|
|
isofs_normalize_block_and_offset(struct iso_directory_record* de,
|
167 |
|
|
unsigned long *block,
|
168 |
|
|
unsigned long *offset)
|
169 |
|
|
{
|
170 |
|
|
/* Only directories are normalized. */
|
171 |
|
|
if (de->flags[0] & 2) {
|
172 |
|
|
*offset = 0;
|
173 |
|
|
*block = (unsigned long)isonum_733(de->extent)
|
174 |
|
|
+ (unsigned long)isonum_711(de->ext_attr_length);
|
175 |
|
|
}
|
176 |
|
|
}
|
177 |
|
|
|
178 |
|
|
extern const struct inode_operations isofs_dir_inode_operations;
|
179 |
|
|
extern const struct file_operations isofs_dir_operations;
|
180 |
|
|
extern const struct address_space_operations isofs_symlink_aops;
|
181 |
|
|
extern const struct export_operations isofs_export_ops;
|