2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <parted/parted.h>
25 #include <parted/endian.h>
26 #include <parted/debug.h>
31 # define _(String) dgettext (PACKAGE, String)
33 # define _(String) (String)
34 #endif /* ENABLE_NLS */
41 /* Open the data fork of a file with its first three extents and its CNID */
43 hfs_file_open (PedFileSystem *fs, uint32_t CNID,
44 HfsExtDataRec ext_desc, PedSector sect_nb)
48 file = (HfsPrivateFile*) ped_malloc (sizeof (HfsPrivateFile));
49 if (!file) return NULL;
52 file->sect_nb = sect_nb;
54 memcpy(file->first, ext_desc, sizeof (HfsExtDataRec));
55 file->start_cache = 0;
60 /* Close an HFS file */
62 hfs_file_close (HfsPrivateFile* file)
67 /* warning : only works on data forks */
69 hfs_get_extent_containing (HfsPrivateFile* file, unsigned int block,
70 HfsExtDataRec cache, uint16_t* ptr_start_cache)
72 uint8_t record[sizeof (HfsExtentKey)
73 + sizeof (HfsExtDataRec)];
75 HfsExtentKey* ret_key = (HfsExtentKey*) record;
76 HfsExtDescriptor* ret_cache = (HfsExtDescriptor*)
77 (record + sizeof (HfsExtentKey));
78 HfsPrivateFSData* priv_data = (HfsPrivateFSData*)
79 file->fs->type_specific;
81 search.key_length = sizeof (HfsExtentKey) - 1;
82 search.type = HFS_DATA_FORK;
83 search.file_ID = file->CNID;
84 search.start = PED_CPU_TO_BE16 (block);
86 if (!hfs_btree_search (priv_data->extent_file,
87 (HfsPrivateGenericKey*) &search,
88 record, sizeof (record), NULL))
91 if (ret_key->file_ID != search.file_ID || ret_key->type != search.type)
94 memcpy (cache, ret_cache, sizeof(HfsExtDataRec));
95 *ptr_start_cache = PED_BE16_TO_CPU (ret_key->start);
100 /* find and return the nth sector of a file */
101 /* return 0 on error */
103 hfs_file_find_sector (HfsPrivateFile* file, PedSector sector)
105 HfsPrivateFSData* priv_data = (HfsPrivateFSData*)
106 file->fs->type_specific;
107 unsigned int sect_by_block = PED_BE32_TO_CPU (
108 priv_data->mdb->block_size)
109 / PED_SECTOR_SIZE_DEFAULT;
110 unsigned int i, s, vol_block;
111 unsigned int block = sector / sect_by_block;
112 unsigned int offset = sector % sect_by_block;
114 /* in the three first extent */
115 for (s = 0, i = 0; i < HFS_EXT_NB; i++) {
116 if ((block >= s) && ( block < s + PED_BE16_TO_CPU (
117 file->first[i].block_count))) {
118 vol_block = (block - s) + PED_BE16_TO_CPU (
119 file->first[i].start_block);
122 s += PED_BE16_TO_CPU (file->first[i].block_count);
125 /* in the three cached extent */
126 if (file->start_cache && block >= file->start_cache)
127 for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) {
128 if ((block >= s) && (block < s + PED_BE16_TO_CPU (
129 file->cache[i].block_count))) {
130 vol_block = (block - s) + PED_BE16_TO_CPU (
131 file->cache[i].start_block);
134 s += PED_BE16_TO_CPU (file->cache[i].block_count);
138 if (!hfs_get_extent_containing (file, block, file->cache,
139 &(file->start_cache))) {
140 ped_exception_throw (
141 PED_EXCEPTION_WARNING,
142 PED_EXCEPTION_CANCEL,
143 _("Could not update the extent cache for HFS file with "
145 PED_BE32_TO_CPU(file->CNID));
149 /* in the three cached extent */
150 PED_ASSERT(file->start_cache && block >= file->start_cache, return 0);
151 for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) {
152 if ((block >= s) && (block < s + PED_BE16_TO_CPU (
153 file->cache[i].block_count))) {
154 vol_block = (block - s) + PED_BE16_TO_CPU (
155 file->cache[i].start_block);
158 s += PED_BE16_TO_CPU (file->cache[i].block_count);
164 return (PedSector) PED_BE16_TO_CPU (priv_data->mdb->start_block)
165 + (PedSector) vol_block * sect_by_block
169 /* Read the nth sector of a file */
170 /* return 0 on error */
172 hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector)
174 PedSector abs_sector;
176 if (sector >= file->sect_nb) {
177 ped_exception_throw (
179 PED_EXCEPTION_CANCEL,
180 _("Trying to read HFS file with CNID %X behind EOF."),
181 PED_BE32_TO_CPU(file->CNID));
185 abs_sector = hfs_file_find_sector (file, sector);
187 ped_exception_throw (
189 PED_EXCEPTION_CANCEL,
190 _("Could not find sector %lli of HFS file with "
192 sector, PED_BE32_TO_CPU(file->CNID));
196 return ped_geometry_read (file->fs->geom, buf, abs_sector, 1);
199 /* Write the nth sector of a file */
200 /* return 0 on error */
202 hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector)
204 PedSector abs_sector;
206 if (sector >= file->sect_nb) {
207 ped_exception_throw (
209 PED_EXCEPTION_CANCEL,
210 _("Trying to write HFS file with CNID %X behind EOF."),
211 PED_BE32_TO_CPU(file->CNID));
215 abs_sector = hfs_file_find_sector (file, sector);
217 ped_exception_throw (
219 PED_EXCEPTION_CANCEL,
220 _("Could not find sector %lli of HFS file with "
222 sector, PED_BE32_TO_CPU(file->CNID));
226 return ped_geometry_write (file->fs->geom, buf, abs_sector, 1);
229 #endif /* !DISCOVER_ONLY */