ReactOS  0.4.14-dev-49-gfb4591c
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
4 static 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 
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));
50 
51 /*
52  * Inode/hard link related stuff for non-directory type files.
53  */
54 EXPORT void
55 do_inode(dpnt)
56  struct directory *dpnt;
57 {
59 
60  if (correct_inodes)
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 
73  compute_linkcount(dpnt);
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  */
84 EXPORT 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  */
112 LOCAL 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  */
197 LOCAL 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) {
272  compute_linkcount(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  */
283 LOCAL 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) {
318  assign_linkcount(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  */
328 LOCAL 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  */
368 LOCAL 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  */
404 LOCAL 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)
456  update_dir_nlink(dpnt->subdir);
457  dpnt = dpnt->next;
458  }
459  return (i+2);
460 }
unsigned int de_flags
Definition: mkisofs.h:122
unsigned int starting_block
Definition: mkisofs.h:161
BOOL rrip112
Definition: mkisofs.c:325
Definition: mkisofs.h:107
long Llong
Definition: stdint.h:152
#define RELOCATED_DIRECTORY
Definition: mkisofs.h:801
EXPORT void do_dir_nlink(struct directory *dpnt)
Definition: inode.c:85
unsigned int starting_block
Definition: mkisofs.h:111
#define PREV_SESS_DEV
Definition: mkisofs.h:762
LOCAL void assign_linkcount(struct directory *dpnt)
Definition: inode.c:284
#define UConst
Definition: ccomdefs.h:72
LOCAL void compute_linkcount(struct directory *dpnt)
Definition: inode.c:198
int cache_inodes
Definition: mkisofs.c:141
LOCAL int update_dir_nlink(struct directory *dpnt)
Definition: inode.c:405
#define RESOURCE_FORK
Definition: mkisofs.h:806
LOCAL UInt32_t null_ino_high
Definition: inode.c:40
#define TABLE_INODE
Definition: mkisofs.h:763
char * name
Definition: mkisofs.h:116
struct directory * subdir
Definition: mkisofs.h:268
#define UNCACHED_DEVICE
Definition: mkisofs.h:765
EXPORT struct file_hash * find_hash(struct directory_entry *spnt)
Definition: hash.c:192
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:36
#define e
Definition: ke_i.h:82
struct iso_directory_record isorec
Definition: mkisofs.h:110
nlink_t nlink
Definition: mkisofs.h:160
#define IS_SYMLINK
Definition: mkisofs.h:807
UInt32_t last_extent
Definition: mkisofs.c:76
dev_t dev
Definition: mkisofs.h:133
EXPORT UInt32_t get_733(void *vp)
Definition: isonum.c:219
smooth NULL
Definition: ftsmooth.c:416
char * whole_name
Definition: mkisofs.h:118
#define INHIBIT_ISO9660_ENTRY
Definition: mkisofs.h:802
struct directory_entry * contents
Definition: mkisofs.h:270
#define LOCAL(type)
Definition: jmorecfg.h:289
unsigned int total_rr_attr_size
Definition: mkisofs.h:136
UInt32_t null_inodes
Definition: mkisofs.c:323
struct directory * reloc_dir
Definition: tree.c:111
int use_RockRidge
Definition: mkisofs.c:110
int create_udfsymlinks
unsigned char * parse_xa(unsigned char *pnt, int *lenp, struct directory_entry *dpnt)
Definition: multi.c:169
static UConst char sccsid[]
Definition: inode.c:4
LOCAL void update_nlink(struct directory_entry *s_entry, int value)
Definition: inode.c:369
#define ISO_DIRECTORY
Definition: iso9660.h:265
GLenum GLsizei len
Definition: glext.h:6722
ino_t inode
Definition: mkisofs.h:132
struct directory_entry * next
Definition: mkisofs.h:108
#define UNCACHED_INODE
Definition: mkisofs.h:764
struct directory_entry * self
Definition: mkisofs.h:272
off_t size
Definition: mkisofs.h:112
GLsizei const GLfloat * value
Definition: glext.h:6069
LOCAL void assign_inodes(struct directory *dpnt)
Definition: inode.c:113
void add_hash(struct hash_table *table, unsigned char *name, int len, unsigned char *pointer)
Definition: hash.c:82
EXPORT void do_inode(struct directory *dpnt)
Definition: inode.c:55
EXPORT void comerrno(int err, char *msg, va_alist)
Definition: comerr.c:137
unsigned char * rr_attributes
Definition: mkisofs.h:134
EXPORT void do_inode __PR((struct directory *dpnt))
LOCAL void update_inode(struct directory_entry *s_entry, int value)
Definition: inode.c:329
unsigned short dir_flags
Definition: mkisofs.h:285
BOOL correct_inodes
Definition: mkisofs.c:324
EXPORT void set_733(void *vp, UInt32_t i)
Definition: isonum.c:125
struct directory * next
Definition: mkisofs.h:267
EXPORT int errmsgno(int err, char *msg, va_alist)
Definition: comerr.c:219
#define EX_BAD
Definition: standard.h:62