ReactOS 0.4.15-dev-8061-g57b775e
inode.c
Go to the documentation of this file.
1/* @(#)inode.c 1.19 16/11/14 Copyright 2006-2016 J. Schilling */
2#include <schily/mconfig.h>
3#ifndef lint
4static UConst char sccsid[] =
5 "@(#)inode.c 1.19 16/11/14 Copyright 2006-2015 J. Schilling";
6#endif
7/*
8 * Inode and link count handling for ISO-9660/RR
9 *
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
15 * directory record.
16 *
17 * Copyright (c) 2006-2016 J. Schilling
18 */
19/*
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.
23 *
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.
28 *
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.
32 */
33
34#include "mkisofs.h"
35#include <schily/schily.h>
36
37/*
38 * Highest inode value we assign in this session.
39 */
41
42EXPORT void do_inode __PR((struct directory *dpnt));
43EXPORT void do_dir_nlink __PR((struct directory *dpnt));
44LOCAL void assign_inodes __PR((struct directory *dpnt));
45LOCAL void compute_linkcount __PR((struct directory *dpnt));
46LOCAL void assign_linkcount __PR((struct directory *dpnt));
47LOCAL void update_inode __PR((struct directory_entry *s_entry, int value));
48LOCAL void update_nlink __PR((struct directory_entry *s_entry, int value));
49LOCAL int update_dir_nlink __PR((struct directory *dpnt));
50
51/*
52 * Inode/hard link related stuff for non-directory type files.
53 */
54EXPORT void
56 struct directory *dpnt;
57{
59
62
63#ifdef UDF
64 if (!use_RockRidge && !use_udf)
65 return;
66#else
67 if (!use_RockRidge)
68 return;
69#endif
70 if (!cache_inodes) /* Never FALSE if correct_inodes TRUE */
71 return;
72
74 if (use_RockRidge) /* If we have Rock Ridge extensions, */
75 assign_linkcount(dpnt); /* reassign computed linkcount in RR */
76
78 comerrno(EX_BAD, _("Inode number overflow, too many files in file system.\n"));
79}
80
81/*
82 * Set the link count for directories to 2 + number of sub-directories.
83 */
84EXPORT void
86 struct directory *dpnt;
87{
88 int rootlinks;
89
90 if (!use_RockRidge)
91 return;
92
93 /*
94 * Update everything except "/..".
95 */
96 rootlinks = update_dir_nlink(dpnt);
97 if (reloc_dir)
98 rootlinks--; /* rr_moved is hidden */
99 /*
100 * Update "/." now.
101 */
102 update_nlink(dpnt->contents, rootlinks);
103 /*
104 * Update "/.." now.
105 */
106 update_nlink(dpnt->contents->next, rootlinks);
107}
108
109/*
110 * Assign inode numbers to files of zero size and to symlinks.
111 */
112LOCAL void
114 struct directory *dpnt;
115{
116 struct directory_entry *s_entry;
117 struct file_hash *s_hash;
118
119 while (dpnt) {
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() ? */
125 if (s_hash)
126 s_entry->starting_block = s_hash->starting_block;
127 }
128 if (s_entry->starting_block == 0 && s_entry->size != 0) {
129 unsigned int e = get_733((char *)s_entry->isorec.extent);
130
131 if (e != 0) {
133 _("Implementation botch, fetching extend %d for %s from dir entry.\n"),
134 e, s_entry->whole_name);
135 }
136 }
137 if (use_RockRidge && s_entry->starting_block > 0)
138 update_inode(s_entry, s_entry->starting_block);
139
140 /*
141 * Be careful: UDF Symlinks have size != 0, then
142 * s_hash->starting_block is a valid inode number.
143 */
144 if (s_entry->size != 0)
145 continue;
146#ifdef UDF
147 if ((s_entry->de_flags & IS_SYMLINK) != 0 &&
149 continue;
150#else
151 if ((s_entry->de_flags & IS_SYMLINK) != 0)
152 continue;
153#endif
154
155 if (s_entry->isorec.flags[0] & ISO_DIRECTORY)
156 continue;
157
158 /*
159 * Assign inodes to symbolic links.
160 */
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;
164 }
165 s_hash = find_hash(s_entry);
166 if (s_hash) {
167 /*
168 * Paranoia: Check for hashed files without proper inode #.
169 */
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;
178 } else {
179 s_entry->starting_block = null_inodes--;
180 set_733((char *)s_entry->isorec.extent, s_entry->starting_block);
181 add_hash(s_entry);
182 }
183 if (use_RockRidge)
184 update_inode(s_entry, s_entry->starting_block);
185 }
186 if (dpnt->subdir) {
187 assign_inodes(dpnt->subdir);
188 }
189
190 dpnt = dpnt->next;
191 }
192}
193
194/*
195 * Compute the link count for non-directory type files.
196 */
197LOCAL void
199 struct directory *dpnt;
200{
201 struct directory_entry *s_entry;
202 struct file_hash *s_hash;
203
204 while (dpnt) {
205 s_entry = dpnt->contents;
206 for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {
207 /*
208 * Skip directories.
209 */
210 if (s_entry->isorec.flags[0] & ISO_DIRECTORY)
211 continue;
212 if (s_entry->de_flags & RELOCATED_DIRECTORY)
213 continue;
214
215 /*
216 * skip resource files or file stream files
217 * XXX should we assign a standard link count == 1 instead?
218 */
219 if (s_entry->de_flags & RESOURCE_FORK)
220 continue;
221
222 /*
223 * Assign inodes to symbolic links.
224 * We never come here in case that we create correct inodes,
225 * except with UDF symlinks.
226 */
227 if (s_entry->dev == UNCACHED_DEVICE && s_entry->inode == UNCACHED_INODE) {
228 s_entry->dev = PREV_SESS_DEV;
229
230 /*
231 * With UDF symlinks, the starting_block is a
232 * valid inode number.
233 */
234#ifdef UDF
235 if ((s_entry->de_flags & IS_SYMLINK) != 0 &&
237#else
238 if ((s_entry->de_flags & IS_SYMLINK) != 0) {
239#endif
240 s_entry->inode = s_entry->starting_block;
241 } else {
242 s_entry->inode = null_inodes--; /* Only used for caching */
243 if (correct_inodes)
245 _("Implementation botch: Unhashed file '%s'.\n"),
246 s_entry->whole_name ?
247 s_entry->whole_name : s_entry->name);
248 }
249 }
250 s_hash = find_hash(s_entry);
251 if (s_hash) {
252 s_hash->nlink++;
253 } else {
254 add_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) {
259 continue;
260 }
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,
265 (Llong)s_entry->dev,
266 (Llong)s_entry->inode);
267 }
268 s_hash->nlink++;
269 }
270 }
271 if (dpnt->subdir) {
273 }
274
275 dpnt = dpnt->next;
276 }
277}
278
279/*
280 * Assig the link count for non-directory type files to the value
281 * computed with compute_linkcount().
282 */
283LOCAL void
285 struct directory *dpnt;
286{
287 struct directory_entry *s_entry;
288 struct file_hash *s_hash;
289
290 while (dpnt) {
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)
294 continue;
295 if (s_entry->de_flags & RELOCATED_DIRECTORY)
296 continue;
297 /*
298 * skip resource files or file stream files
299 */
300 if (s_entry->de_flags & RESOURCE_FORK)
301 continue;
302
303 s_hash = find_hash(s_entry);
304 if (s_hash) {
305 update_nlink(s_entry, s_hash->nlink);
306 } else {
307 if (s_entry->dev == UNCACHED_DEVICE &&
308 s_entry->inode == TABLE_INODE) {
309 continue;
310 }
312 _("Implementation botch: File '%s' not hashed.\n"),
313 s_entry->whole_name ?
314 s_entry->whole_name : s_entry->name);
315 }
316 }
317 if (dpnt->subdir) {
319 }
320
321 dpnt = dpnt->next;
322 }
323}
324
325/*
326 * Rewrite the content of the RR inode field in the PX record.
327 */
328LOCAL void
330 struct directory_entry *s_entry;
331 int value;
332{
333 unsigned char *pnt;
334 int len;
335
336 if (!rrip112)
337 return;
338
339 pnt = s_entry->rr_attributes;
340 len = s_entry->total_rr_attr_size;
341 pnt = parse_xa(pnt, &len, 0);
342 while (len >= 4) {
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]);
347 }
348 if (pnt[2] < 4) {
350 _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
351 pnt[2], pnt, pnt[0], pnt[1]);
352 break;
353 }
354 if (pnt[0] == 'P' && pnt[1] == 'X') {
355 if ((pnt[2] & 0xFF) < 44) /* Paranoia */
356 return;
357 set_733((char *)pnt + 36, value);
358 break;
359 }
360 len -= pnt[2];
361 pnt += pnt[2];
362 }
363}
364
365/*
366 * Rewrite the content of the RR nlink field in the PX record.
367 */
368LOCAL void
370 struct directory_entry *s_entry;
371 int value;
372{
373 unsigned char *pnt;
374 int len;
375
376 pnt = s_entry->rr_attributes;
377 len = s_entry->total_rr_attr_size;
378 pnt = parse_xa(pnt, &len, 0);
379 while (len >= 4) {
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]);
384 }
385 if (pnt[2] < 4) {
387 _("**BAD RRLEN (%d) in '%2.2s' field %2.2X %2.2X.\n"),
388 pnt[2], pnt, pnt[0], pnt[1]);
389 break;
390 }
391 if (pnt[0] == 'P' && pnt[1] == 'X') {
392 set_733((char *)pnt + 12, value);
393 break;
394 }
395 len -= pnt[2];
396 pnt += pnt[2];
397 }
398}
399
400/*
401 * Set the link count for directories to 2 + number of sub-directories.
402 * This is done here for all diresctories except for "/..".
403 */
404LOCAL int
406 struct directory *dpnt;
407{
408 struct directory *xpnt;
409 struct directory_entry *s_entry;
410 int i = 0;
411
412 while (dpnt) {
413 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) {
414 dpnt = dpnt->next;
415 continue;
416 }
417 /*
418 * First, count up the number of subdirectories this dir has.
419 */
420 for (i = 0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next)
421 if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0)
422 i++;
423 /*
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
428 * zero length files.
429 */
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) ==
434 0) {
435 i++;
436 }
437 }
438 /*
439 * Now update the field in the Rock Ridge entry.
440 */
441 update_nlink(dpnt->self, i + 2);
442
443 /*
444 * Update the '.' entry for this directory.
445 */
446 update_nlink(dpnt->contents, i + 2);
447
448 /*
449 * Update all of the '..' entries that point to this guy.
450 */
451 for (xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) {
452 update_nlink(xpnt->contents->next, i + 2);
453 }
454
455 if (dpnt->subdir)
457 dpnt = dpnt->next;
458 }
459 return (i+2);
460}
void add_hash(struct hash_table *table, unsigned char *name, int len, unsigned char *pointer)
Definition: hash.c:82
#define UConst
Definition: ccomdefs.h:72
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
#define NULL
Definition: types.h:112
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define _(X)
Definition: i386-dis.c:35
LOCAL void update_nlink(struct directory_entry *s_entry, int value)
Definition: inode.c:369
EXPORT void do_inode(struct directory *dpnt)
Definition: inode.c:55
LOCAL void assign_inodes(struct directory *dpnt)
Definition: inode.c:113
LOCAL UInt32_t null_ino_high
Definition: inode.c:40
LOCAL void assign_linkcount(struct directory *dpnt)
Definition: inode.c:284
static UConst char sccsid[]
Definition: inode.c:4
LOCAL void compute_linkcount(struct directory *dpnt)
Definition: inode.c:198
LOCAL int update_dir_nlink(struct directory *dpnt)
Definition: inode.c:405
EXPORT void do_dir_nlink(struct directory *dpnt)
Definition: inode.c:85
LOCAL void update_inode(struct directory_entry *s_entry, int value)
Definition: inode.c:329
#define ISO_DIRECTORY
Definition: iso9660.h:265
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
#define LOCAL(type)
Definition: jmorecfg.h:289
#define e
Definition: ke_i.h:82
int cache_inodes
Definition: mkisofs.c:141
BOOL correct_inodes
Definition: mkisofs.c:324
UInt32_t null_inodes
Definition: mkisofs.c:323
int use_RockRidge
Definition: mkisofs.c:110
UInt32_t last_extent
Definition: mkisofs.c:76
BOOL rrip112
Definition: mkisofs.c:325
#define TABLE_INODE
Definition: mkisofs.h:763
#define RESOURCE_FORK
Definition: mkisofs.h:806
int create_udfsymlinks
#define PREV_SESS_DEV
Definition: mkisofs.h:762
#define RELOCATED_DIRECTORY
Definition: mkisofs.h:801
struct directory * reloc_dir
Definition: tree.c:111
#define IS_SYMLINK
Definition: mkisofs.h:807
#define UNCACHED_DEVICE
Definition: mkisofs.h:765
#define INHIBIT_ISO9660_ENTRY
Definition: mkisofs.h:802
#define UNCACHED_INODE
Definition: mkisofs.h:764
unsigned char * parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
Definition: multi.c:169
#define __PR(a)
Definition: prototyp.h:106
EXPORT struct file_hash * find_hash(struct directory_entry *spnt)
Definition: hash.c:192
#define EX_BAD
Definition: standard.h:62
Definition: mkisofs.h:107
char * whole_name
Definition: mkisofs.h:118
dev_t dev
Definition: mkisofs.h:133
unsigned int starting_block
Definition: mkisofs.h:111
unsigned char * rr_attributes
Definition: mkisofs.h:134
off_t size
Definition: mkisofs.h:112
struct directory_entry * next
Definition: mkisofs.h:108
char * name
Definition: mkisofs.h:116
unsigned int de_flags
Definition: mkisofs.h:122
struct iso_directory_record isorec
Definition: mkisofs.h:110
ino_t inode
Definition: mkisofs.h:132
unsigned int total_rr_attr_size
Definition: mkisofs.h:136
unsigned short dir_flags
Definition: mkisofs.h:285
struct directory * subdir
Definition: mkisofs.h:268
struct directory * next
Definition: mkisofs.h:267
struct directory_entry * self
Definition: mkisofs.h:272
struct directory_entry * contents
Definition: mkisofs.h:270
unsigned int starting_block
Definition: mkisofs.h:161
nlink_t nlink
Definition: mkisofs.h:160
long Llong
Definition: stdint.h:152
Definition: pdh_main.c:94