1 /* @(#)inode.c 1.19 16/11/14 Copyright 2006-2016 J. Schilling */
2 #include <schily/mconfig.h>
4 static UConst
char sccsid
[] =
5 "@(#)inode.c 1.19 16/11/14 Copyright 2006-2015 J. Schilling";
8 * Inode and link count handling for ISO-9660/RR
10 * This module computes and sets up a RR link count that reflects
11 * the name-count for files/directories in the ISO-9660/RR image.
12 * This module also assigns inode numbers tp all files/directories
13 * using either the RRip-112 protocol or a mkisofs specific method
14 * of asigning the related number to the "extent" field in the ISO
17 * Copyright (c) 2006-2016 J. Schilling
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2
22 * as published by the Free Software Foundation.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License along with
30 * this program; see the file COPYING. If not, write to the Free Software
31 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
35 #include <schily/schily.h>
38 * Highest inode value we assign in this session.
40 LOCAL UInt32_t null_ino_high
;
42 EXPORT
void do_inode
__PR((struct directory
*dpnt
));
43 EXPORT
void do_dir_nlink
__PR((struct directory
*dpnt
));
44 LOCAL
void assign_inodes
__PR((struct directory
*dpnt
));
45 LOCAL
void compute_linkcount
__PR((struct directory
*dpnt
));
46 LOCAL
void assign_linkcount
__PR((struct directory
*dpnt
));
47 LOCAL
void update_inode
__PR((struct directory_entry
*s_entry
, int value
));
48 LOCAL
void update_nlink
__PR((struct directory_entry
*s_entry
, int value
));
49 LOCAL
int update_dir_nlink
__PR((struct directory
*dpnt
));
52 * Inode/hard link related stuff for non-directory type files.
56 struct directory
*dpnt
;
58 null_ino_high
= null_inodes
;
64 if (!use_RockRidge
&& !use_udf
)
70 if (!cache_inodes
) /* Never FALSE if correct_inodes TRUE */
73 compute_linkcount(dpnt
);
74 if (use_RockRidge
) /* If we have Rock Ridge extensions, */
75 assign_linkcount(dpnt
); /* reassign computed linkcount in RR */
77 if (null_inodes
< last_extent
)
78 comerrno(EX_BAD
, _("Inode number overflow, too many files in file system.\n"));
82 * Set the link count for directories to 2 + number of sub-directories.
86 struct directory
*dpnt
;
94 * Update everything except "/..".
96 rootlinks
= update_dir_nlink(dpnt
);
98 rootlinks
--; /* rr_moved is hidden */
102 update_nlink(dpnt
->contents
, rootlinks
);
106 update_nlink(dpnt
->contents
->next
, rootlinks
);
110 * Assign inode numbers to files of zero size and to symlinks.
114 struct directory
*dpnt
;
116 struct directory_entry
*s_entry
;
117 struct file_hash
*s_hash
;
120 s_entry
= dpnt
->contents
;
121 for (s_entry
= dpnt
->contents
; s_entry
; s_entry
= s_entry
->next
) {
122 if (s_entry
->starting_block
== 0) {
123 s_hash
= find_hash(s_entry
);
124 /* find_directory_hash() ? */
126 s_entry
->starting_block
= s_hash
->starting_block
;
128 if (s_entry
->starting_block
== 0 && s_entry
->size
!= 0) {
129 unsigned int e
= get_733((char *)s_entry
->isorec
.extent
);
133 _("Implementation botch, fetching extend %d for %s from dir entry.\n"),
134 e
, s_entry
->whole_name
);
137 if (use_RockRidge
&& s_entry
->starting_block
> 0)
138 update_inode(s_entry
, s_entry
->starting_block
);
141 * Be careful: UDF Symlinks have size != 0, then
142 * s_hash->starting_block is a valid inode number.
144 if (s_entry
->size
!= 0)
147 if ((s_entry
->de_flags
& IS_SYMLINK
) != 0 &&
151 if ((s_entry
->de_flags
& IS_SYMLINK
) != 0)
155 if (s_entry
->isorec
.flags
[0] & ISO_DIRECTORY
)
159 * Assign inodes to symbolic links.
161 if (s_entry
->dev
== UNCACHED_DEVICE
&& s_entry
->inode
== UNCACHED_INODE
) {
162 s_entry
->dev
= PREV_SESS_DEV
;
163 s_entry
->inode
= null_inodes
;
165 s_hash
= find_hash(s_entry
);
168 * Paranoia: Check for hashed files without proper inode #.
170 if (s_hash
->starting_block
<= last_extent
)
172 _("Implementation botch: Hashed file '%s' has illegal inode %u.\n"),
173 s_entry
->whole_name
?
174 s_entry
->whole_name
: s_entry
->name
,
175 s_hash
->starting_block
);
176 set_733((char *)s_entry
->isorec
.extent
, s_hash
->starting_block
);
177 s_entry
->starting_block
= s_hash
->starting_block
;
179 s_entry
->starting_block
= null_inodes
--;
180 set_733((char *)s_entry
->isorec
.extent
, s_entry
->starting_block
);
184 update_inode(s_entry
, s_entry
->starting_block
);
187 assign_inodes(dpnt
->subdir
);
195 * Compute the link count for non-directory type files.
198 compute_linkcount(dpnt
)
199 struct directory
*dpnt
;
201 struct directory_entry
*s_entry
;
202 struct file_hash
*s_hash
;
205 s_entry
= dpnt
->contents
;
206 for (s_entry
= dpnt
->contents
; s_entry
; s_entry
= s_entry
->next
) {
210 if (s_entry
->isorec
.flags
[0] & ISO_DIRECTORY
)
212 if (s_entry
->de_flags
& RELOCATED_DIRECTORY
)
216 * skip resource files or file stream files
217 * XXX should we assign a standard link count == 1 instead?
219 if (s_entry
->de_flags
& RESOURCE_FORK
)
223 * Assign inodes to symbolic links.
224 * We never come here in case that we create correct inodes,
225 * except with UDF symlinks.
227 if (s_entry
->dev
== UNCACHED_DEVICE
&& s_entry
->inode
== UNCACHED_INODE
) {
228 s_entry
->dev
= PREV_SESS_DEV
;
231 * With UDF symlinks, the starting_block is a
232 * valid inode number.
235 if ((s_entry
->de_flags
& IS_SYMLINK
) != 0 &&
236 create_udfsymlinks
) {
238 if ((s_entry
->de_flags
& IS_SYMLINK
) != 0) {
240 s_entry
->inode
= s_entry
->starting_block
;
242 s_entry
->inode
= null_inodes
--; /* Only used for caching */
245 _("Implementation botch: Unhashed file '%s'.\n"),
246 s_entry
->whole_name
?
247 s_entry
->whole_name
: s_entry
->name
);
250 s_hash
= find_hash(s_entry
);
255 s_hash
= find_hash(s_entry
);
256 if (s_hash
== NULL
) {
257 if (s_entry
->dev
== UNCACHED_DEVICE
&&
258 s_entry
->inode
== TABLE_INODE
) {
262 _("Implementation botch: File '%s' not hashed (dev/ino %llX/%llX).\n"),
263 s_entry
->whole_name
?
264 s_entry
->whole_name
: s_entry
->name
,
266 (Llong
)s_entry
->inode
);
272 compute_linkcount(dpnt
->subdir
);
280 * Assig the link count for non-directory type files to the value
281 * computed with compute_linkcount().
284 assign_linkcount(dpnt
)
285 struct directory
*dpnt
;
287 struct directory_entry
*s_entry
;
288 struct file_hash
*s_hash
;
291 s_entry
= dpnt
->contents
;
292 for (s_entry
= dpnt
->contents
; s_entry
; s_entry
= s_entry
->next
) {
293 if (s_entry
->isorec
.flags
[0] & ISO_DIRECTORY
)
295 if (s_entry
->de_flags
& RELOCATED_DIRECTORY
)
298 * skip resource files or file stream files
300 if (s_entry
->de_flags
& RESOURCE_FORK
)
303 s_hash
= find_hash(s_entry
);
305 update_nlink(s_entry
, s_hash
->nlink
);
307 if (s_entry
->dev
== UNCACHED_DEVICE
&&
308 s_entry
->inode
== TABLE_INODE
) {
312 _("Implementation botch: File '%s' not hashed.\n"),
313 s_entry
->whole_name
?
314 s_entry
->whole_name
: s_entry
->name
);
318 assign_linkcount(dpnt
->subdir
);
326 * Rewrite the content of the RR inode field in the PX record.
329 update_inode(s_entry
, value
)
330 struct directory_entry
*s_entry
;
339 pnt
= s_entry
->rr_attributes
;
340 len
= s_entry
->total_rr_attr_size
;
341 pnt
= parse_xa(pnt
, &len
, 0);
343 if (pnt
[3] != 1 && pnt
[3] != 2) {
345 _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
346 pnt
[3], pnt
[0], pnt
[1], pnt
[0], pnt
[1]);
350 _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
351 pnt
[2], pnt
, pnt
[0], pnt
[1]);
354 if (pnt
[0] == 'P' && pnt
[1] == 'X') {
355 if ((pnt
[2] & 0xFF) < 44) /* Paranoia */
357 set_733((char *)pnt
+ 36, value
);
366 * Rewrite the content of the RR nlink field in the PX record.
369 update_nlink(s_entry
, value
)
370 struct directory_entry
*s_entry
;
376 pnt
= s_entry
->rr_attributes
;
377 len
= s_entry
->total_rr_attr_size
;
378 pnt
= parse_xa(pnt
, &len
, 0);
380 if (pnt
[3] != 1 && pnt
[3] != 2) {
382 _("**BAD RRVERSION (%d) in '%c%c' field (%2.2X %2.2X).\n"),
383 pnt
[3], pnt
[0], pnt
[1], pnt
[0], pnt
[1]);
387 _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
388 pnt
[2], pnt
, pnt
[0], pnt
[1]);
391 if (pnt
[0] == 'P' && pnt
[1] == 'X') {
392 set_733((char *)pnt
+ 12, value
);
401 * Set the link count for directories to 2 + number of sub-directories.
402 * This is done here for all diresctories except for "/..".
405 update_dir_nlink(dpnt
)
406 struct directory
*dpnt
;
408 struct directory
*xpnt
;
409 struct directory_entry
*s_entry
;
413 if (dpnt
->dir_flags
& INHIBIT_ISO9660_ENTRY
) {
418 * First, count up the number of subdirectories this dir has.
420 for (i
= 0, xpnt
= dpnt
->subdir
; xpnt
; xpnt
= xpnt
->next
)
421 if ((xpnt
->dir_flags
& INHIBIT_ISO9660_ENTRY
) == 0)
424 * Next check to see if we have any relocated directories in
425 * this directory. The nlink field will include these as
426 * real directories when they are properly relocated.
427 * In the non-rockridge disk, the relocated entries appear as
430 for (s_entry
= dpnt
->contents
; s_entry
;
431 s_entry
= s_entry
->next
) {
432 if ((s_entry
->de_flags
& RELOCATED_DIRECTORY
) != 0 &&
433 (s_entry
->de_flags
& INHIBIT_ISO9660_ENTRY
) ==
439 * Now update the field in the Rock Ridge entry.
441 update_nlink(dpnt
->self
, i
+ 2);
444 * Update the '.' entry for this directory.
446 update_nlink(dpnt
->contents
, i
+ 2);
449 * Update all of the '..' entries that point to this guy.
451 for (xpnt
= dpnt
->subdir
; xpnt
; xpnt
= xpnt
->next
) {
452 update_nlink(xpnt
->contents
->next
, i
+ 2);
456 update_dir_nlink(dpnt
->subdir
);