1 /*
2  * Copyright (c) 2007 Vreixo Formoso
3  * Copyright (c) 2009 - 2020 Thomas Schmitt
4  *
5  * This file is part of the libisofs project; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License version 2
7  * or later as published by the Free Software Foundation.
8  * See COPYING file for details.
9  */
10 #ifndef LIBISO_NODE_H_
11 #define LIBISO_NODE_H_
12 
13 /*
14  * Definitions for the public iso tree
15  */
16 
17 #include "libisofs.h"
18 #include "stream.h"
19 
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #ifdef HAVE_STDINT_H
25 #include <stdint.h>
26 #else
27 #ifdef HAVE_INTTYPES_H
28 #include <inttypes.h>
29 #endif
30 #endif
31 
32 
33 /* Maximum length of a leaf name in the libisofs node tree. This is currently
34    restricted by the implemented maximum length of a Rock Ridge name.
35    This might later become larger and may then be limited to smaller values.
36 
37    Rock Ridge specs do not impose an explicit limit on name length.
38    But 255 is also specified by
39      http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
40    which says
41      NAME_MAX >= _XOPEN_NAME_MAX = 255
42 */
43 #define LIBISOFS_NODE_NAME_MAX 255
44 
45 
46 /* Maximum length of a path in the libisofs node tree.
47    Rock Ridge specs do not impose an explicit limit on path length.
48 
49      http://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html
50    says
51      PATH_MAX >= _XOPEN_PATH_MAX = 1024
52 */
53 #define LIBISOFS_NODE_PATH_MAX 1024
54 
55 
56 /**
57  * The extended information is a way to attach additional information to each
58  * IsoNode. External applications may want to use this extension system to
59  * store application specific information related to each node. On the other
60  * side, libisofs may make use of this struct to attach information to nodes in
61  * some particular, uncommon, cases, without incrementing the size of the
62  * IsoNode struct.
63  *
64  * It is implemented like a chained list.
65  */
66 typedef struct iso_extended_info IsoExtendedInfo;
67 
68 struct iso_extended_info {
69     /**
70      * Next struct in the chain. NULL if it is the last item
71      */
72     IsoExtendedInfo *next;
73 
74     /**
75      * Function to handle this particular extended information. The function
76      * pointer acts as an identifier for the type of the information. Structs
77      * with same information type must use the same function.
78      *
79      * @param data
80      *     Attached data
81      * @param flag
82      *     What to do with the data. At this time the following values are
83      *     defined:
84      *      -> 1 the data must be freed
85      * @return
86      *     1
87      */
88     iso_node_xinfo_func process;
89 
90     /**
91      * Pointer to information specific data.
92      */
93     void *data;
94 };
95 
96 /**
97  *
98  */
99 struct Iso_Node
100 {
101     /*
102      * Initialized to 1, originally owned by user, until added to another node.
103      * Then it is owned by the parent node, so the user must take his own ref
104      * if needed. With the exception of the creation functions, none of the
105      * other libisofs functions that return an IsoNode increment its
106      * refcount. This is responsablity of the client, if (s)he needs it.
107      */
108     int refcount;
109 
110     /** Type of the IsoNode, do not confuse with mode */
111     enum IsoNodeType type;
112 
113     char *name; /**< Real name, in default charset */
114 
115     mode_t mode; /**< protection */
116     uid_t uid; /**< user ID of owner */
117     gid_t gid; /**< group ID of owner */
118 
119     /* TODO #00001 : consider adding new timestamps */
120     time_t atime; /**< time of last access */
121     time_t mtime; /**< time of last modification */
122     time_t ctime; /**< time of last status change */
123 
124     int hidden; /**< whether the node will be hidden, see IsoHideNodeFlag */
125 
126     IsoDir *parent; /**< parent node, NULL for root */
127 
128     /*
129      * Pointer to the linked list of children in a dir.
130      */
131     IsoNode *next;
132 
133     /**
134      * Extended information for the node.
135      */
136     IsoExtendedInfo *xinfo;
137 };
138 
139 struct Iso_Dir
140 {
141     IsoNode node;
142 
143     size_t nchildren; /**< The number of children of this directory. */
144     IsoNode *children; /**< list of children. ptr to first child */
145 };
146 
147 /* IMPORTANT: Any change must be reflected by iso_tree_clone_file. */
148 struct Iso_File
149 {
150     IsoNode node;
151 
152     /* 1 = The node was loaded from an existing ISO image and still refers
153            to its data content there.
154     */
155     unsigned int from_old_session : 1;
156 
157     /* 1 = The node got attributed a weight by iso_node_set_sort_weight().
158     */
159     unsigned int explicit_weight : 1;
160 
161     /**
162      * It sorts the order in which the file data is written to the CD image.
163      * Higher weighting files are written at the beginning of image
164      */
165     int sort_weight;
166     IsoStream *stream;                    /* Knows fs_id, st_dev, and st_ino */
167 };
168 
169 struct Iso_Symlink
170 {
171     IsoNode node;
172 
173     char *dest;
174 
175     /* If the IsoNode represents an object in an existing filesystem then
176        the following three numbers should unique identify it.
177        (0,0,0) will always be taken as unique.
178      */
179     unsigned int fs_id;
180     dev_t st_dev;
181     ino_t st_ino;
182 };
183 
184 struct Iso_Special
185 {
186     IsoNode node;
187     dev_t dev;
188 
189     /* If the IsoNode represents an object in an existing filesystem then
190        the following three numbers should unique identify it.
191        (0,0,0) will always be taken as unique.
192      */
193     unsigned int fs_id;
194     dev_t st_dev;
195     ino_t st_ino;
196 };
197 
198 struct iso_dir_iter_iface
199 {
200 
201     int (*next)(IsoDirIter *iter, IsoNode **node);
202 
203     int (*has_next)(IsoDirIter *iter);
204 
205     void (*free)(IsoDirIter *iter);
206 
207     int (*take)(IsoDirIter *iter);
208 
209     int (*remove)(IsoDirIter *iter);
210 
211     /**
212      * This is called just before remove a node from a directory. The iterator
213      * may want to update its internal state according to this.
214      */
215     void (*notify_child_taken)(IsoDirIter *iter, IsoNode *node);
216 };
217 
218 /**
219  * An iterator for directory children.
220  */
221 struct Iso_Dir_Iter
222 {
223     struct iso_dir_iter_iface *class;
224 
225     /* the directory this iterator iterates over */
226     IsoDir *dir;
227 
228     void *data;
229 };
230 
231 int iso_node_new_root(IsoDir **root);
232 
233 /**
234  * Create a new IsoDir. Attributes, uid/gid, timestamps, etc are set to
235  * default (0) values. You must set them.
236  *
237  * @param name
238  *      Name for the node. It is not strdup() so you shouldn't use this
239  *      reference when this function returns successfully. NULL is not
240  *      allowed.
241  * @param dir
242  *
243  * @return
244  *      1 on success, < 0 on error.
245  */
246 int iso_node_new_dir(char *name, IsoDir **dir);
247 
248 /**
249  * Create a new file node. Attributes, uid/gid, timestamps, etc are set to
250  * default (0) values. You must set them.
251  *
252  * @param name
253  *      Name for the node. It is not strdup() so you shouldn't use this
254  *      reference when this function returns successfully. NULL is not
255  *      allowed.
256  * @param stream
257  *      Source for file contents. The reference is taken by the node,
258  *      you must call iso_stream_ref() if you need your own ref.
259  * @return
260  *      1 on success, < 0 on error.
261  */
262 int iso_node_new_file(char *name, IsoStream *stream, IsoFile **file);
263 
264 /**
265  * Creates a new IsoSymlink node. Attributes, uid/gid, timestamps, etc are set
266  * to default (0) values. You must set them.
267  *
268  * @param name
269  *      name for the new symlink. It is not strdup() so you shouldn't use this
270  *      reference when this function returns successfully. NULL is not
271  *      allowed.
272  * @param dest
273  *      destination of the link. It is not strdup() so you shouldn't use this
274  *      reference when this function returns successfully. NULL is not
275  *      allowed.
276  * @param link
277  *      place where to store a pointer to the newly created link.
278  * @return
279  *     1 on success, < 0 otherwise
280  */
281 int iso_node_new_symlink(char *name, char *dest, IsoSymlink **link);
282 
283 /**
284  * Create a new special file node. As far as libisofs concerns,
285  * an special file is a block device, a character device, a FIFO (named pipe)
286  * or a socket. You can choose the specific kind of file you want to add
287  * by setting mode properly (see man 2 stat).
288  *
289  * Note that special files are only written to image when Rock Ridge
290  * extensions are enabled. Moreover, a special file is just a directory entry
291  * in the image tree, no data is written beyond that.
292  *
293  * Owner and hidden atts are taken from parent. You can modify any of them
294  * later.
295  *
296  * @param name
297  *      name for the new special file. It is not strdup() so you shouldn't use
298  *      this reference when this function returns successfully. NULL is not
299  *      allowed.
300  * @param mode
301  *      file type and permissions for the new node. Note that you can't
302  *      specify any kind of file here, only special types are allowed. i.e,
303  *      S_IFSOCK, S_IFBLK, S_IFCHR and S_IFIFO are valid types; S_IFLNK,
304  *      S_IFREG and S_IFDIR aren't.
305  * @param dev
306  *      device ID, equivalent to the st_rdev field in man 2 stat.
307  * @param special
308  *      place where to store a pointer to the newly created special file.
309  * @return
310  *     1 on success, < 0 otherwise
311  */
312 int iso_node_new_special(char *name, mode_t mode, dev_t dev,
313                          IsoSpecial **special);
314 
315 /**
316  * Check if a given name is valid for an iso node.
317  *
318  * @return
319  *     1 if yes, <0 if not. The value is a specific ISO_* error code.
320  */
321 int iso_node_is_valid_name(const char *name);
322 
323 /**
324  * Check if a given path is valid for the destination of a link.
325  *
326  * @return
327  *     1 if yes, 0 if not
328  */
329 int iso_node_is_valid_link_dest(const char *dest);
330 
331 /**
332  * Find the position where to insert a node
333  *
334  * @param dir
335  *      A valid dir. It can't be NULL
336  * @param name
337  *      The node name to search for. It can't be NULL
338  * @param pos
339  *      Will be filled with the position where to insert. It can't be NULL
340  */
341 void iso_dir_find(IsoDir *dir, const char *name, IsoNode ***pos);
342 
343 /**
344  * Check if a node with the given name exists in a dir.
345  *
346  * @param dir
347  *      A valid dir. It can't be NULL
348  * @param name
349  *      The node name to search for. It can't be NULL
350  * @param pos
351  *      If not NULL, will be filled with the position where to insert. If the
352  *      node exists, (**pos) will refer to the given node.
353  * @return
354  *      1 if node exists, 0 if not
355  */
356 int iso_dir_exists(IsoDir *dir, const char *name, IsoNode ***pos);
357 
358 /**
359  * Inserts a given node in a dir, at the specified position.
360  *
361  * @param dir
362  *     Dir where to insert. It can't be NULL
363  * @param node
364  *     The node to insert. It can't be NULL
365  * @param pos
366  *     Position where the node will be inserted. It is a pointer previously
367  *     obtained with a call to iso_dir_exists() or iso_dir_find().
368  *     It can't be NULL.
369  * @param replace
370  *     Whether to replace an old node with the same name with the new node.
371  * @return
372  *     If success, number of children in dir. < 0 on error
373  */
374 int iso_dir_insert(IsoDir *dir, IsoNode *node, IsoNode **pos,
375                    enum iso_replace_mode replace);
376 
377 /**
378  * Add a new iterator to the registry. The iterator register keeps track of
379  * all iterators being used, and are notified when directory structure
380  * changes.
381  */
382 int iso_dir_iter_register(IsoDirIter *iter);
383 
384 /**
385  * Unregister a directory iterator.
386  */
387 void iso_dir_iter_unregister(IsoDirIter *iter);
388 
389 void iso_notify_dir_iters(IsoNode *node, int flag);
390 
391 
392 /**
393  * See API function iso_node_set_permissions()
394  *
395  * @param flag  bit0= do not adjust ACL
396  * @return      >0 success , <0 error
397  */
398 int iso_node_set_perms_internal(IsoNode *node, mode_t mode, int flag);
399 
400 
401 /**
402  * Like iso_node_get_acl_text() with param node replaced by aa_string and
403  * st_mode from where to obtain the ACLs. All other parameter specs apply.
404  */
405 int iso_aa_get_acl_text(unsigned char *aa_string, mode_t st_mode,
406                         char **access_text, char **default_text, int flag);
407 
408 /**
409  * Backend of iso_node_get_attrs() with parameter node replaced by the
410  * AAIP string from where to get the attribute list.
411  * All other parameter specs apply.
412  */
413 int iso_aa_get_attrs(unsigned char *aa_string, size_t *num_attrs,
414               char ***names, size_t **value_lengths, char ***values, int flag);
415 
416 /**
417  * Search given name. Eventually calloc() and copy value. Add trailing 0 byte
418  * for caller convenience.
419  *
420  * @return 1= found , 0= not found , <0 error
421  */
422 int iso_aa_lookup_attr(unsigned char *aa_string, char *name,
423                        size_t *value_length, char **value, int flag);
424 
425 
426 /**
427  * Function to identify and manage ZF parameters which do not stem from ZF
428  * fields (those are known to the FileSource) and do not stem from filters
429  * ("ziso" knows them globally, "osiz" knows them individually) but rather
430  * from an inspection of the file content header for zisofs magic number and
431  * plausible parameters.
432  * The parameters get attached in struct zisofs_zf_info as xinfo to an IsoNode.
433  */
434 int zisofs_zf_xinfo_func(void *data, int flag);
435 
436 /**
437  * Parameter structure which is to be managed by zisofs_zf_xinfo_func.
438  */
439 struct zisofs_zf_info {
440     uint64_t uncompressed_size;
441     uint8_t header_size_div4;
442     uint8_t block_size_log2;
443     uint8_t zisofs_algo[2];
444 };
445 
446 /**
447  * Checks whether a file effectively bears a zisofs file header and eventually
448  * marks this by a struct zisofs_zf_info as xinfo of the file node.
449  * @param flag bit0= inquire the most original stream of the file
450  *             bit1= permission to overwrite existing zisofs_zf_info
451  *             bit2= if no zisofs header is found:
452                      create xinfo with parameters which indicate no zisofs
453  * @return 1= zf xinfo added, 0= no zisofs data found ,
454  *         2= found existing zf xinfo and flag bit1 was not set
455  *         <0 means error
456  */
457 int iso_file_zf_by_magic(IsoFile *file, int flag);
458 
459 /*
460  * @param flag
461  *     bit0= do only retrieve id if node is in imported ISO image
462  *           or has an explicit xinfo inode number
463  * @return
464  *     1= reply is valid from stream, 2= reply is valid from xinfo
465  *     0= no id available,           <0= error
466  *     (fs_id, dev_id, ino_id) will be (0,0,0) in case of return <= 0
467  */
468 int iso_node_get_id(IsoNode *node, unsigned int *fs_id, dev_t *dev_id,
469                     ino_t *ino_id, int flag);
470 
471 /* Set a new unique inode ISO image number to the given node.
472  * This number shall eventually persist during image generation.
473  */
474 int iso_node_set_unique_id(IsoNode *node, IsoImage *image, int flag);
475 
476 /* Use this with extreme care. Duplicate inode numbers will indicate hardlink
477  * relationship between the nodes.
478  */
479 int iso_node_set_ino(IsoNode *node, ino_t ino, int flag);
480 
481 /*
482  * @param flag
483  *     bit0= compare stat properties and attributes
484  *     bit1= treat all nodes with image ino == 0 as unique
485  *           (those with 0,0,0 are treated as unique anyway)
486  */
487 int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag);
488 
489 
490 /**
491  * Set the checksum index (typically coming from IsoFileSrc.checksum_index)
492  * of a regular file node. The index is encoded as xattr "isofs.cx" with
493  * four bytes of value.
494  */
495 int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
496                          int flag);
497 
498 
499 /**
500  * Set the checksum area description. node should be the root node.
501  * It is encoded as xattr "isofs.ca".
502  */
503 int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba,
504                          uint32_t count, uint32_t size, char *typetext,
505                          int flag);
506 
507 /**
508  * Get the checksum area description. node should be the root node.
509  * It is encoded as xattr "isofs.ca".
510  */
511 int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
512                          uint32_t *count, uint32_t *size, char typetext[81],
513                          int flag);
514 
515 
516 /**
517  * Record and get truncation parameters as of iso_image_set_truncate_mode() by
518  * "isofs.nt".
519  */
520 int iso_root_set_isofsnt(IsoNode *node, uint32_t truncate_mode,
521                          uint32_t truncate_length, int flag);
522 int iso_root_get_isofsnt(IsoNode *node, uint32_t *truncate_mode,
523                          uint32_t *truncate_length, int flag);
524 
525 
526 /**
527  * Copy the xinfo list from one node to the another.
528  */
529 int iso_node_clone_xinfo(IsoNode *from_node, IsoNode *to_node, int flag);
530 
531 
532 /**
533  * The iso_node_xinfo_func instance which governs the storing of the inode
534  * number from Rock Ridge field PX.
535  */
536 int iso_px_ino_xinfo_func(void *data, int flag);
537 
538 /* The iso_node_xinfo_cloner function which gets associated to
539  * iso_px_ino_xinfo_func by iso_init() resp. iso_init_with_flag() via
540  * iso_node_xinfo_make_clonable()
541  */
542 int iso_px_ino_xinfo_cloner(void *old_data, void **new_data, int flag);
543 
544 
545 /* Function to identify and manage ZF parameters of zisofs compression.
546  * data is supposed to be a pointer to struct zisofs_zf_info
547  */
548 int zisofs_zf_xinfo_func(void *data, int flag);
549 
550 /* The iso_node_xinfo_cloner function which gets associated to
551  * zisofs_zf_xinfo_func by iso_init() resp. iso_init_with_flag() via
552  * iso_node_xinfo_make_clonable()
553  */
554 int zisofs_zf_xinfo_cloner(void *old_data, void **new_data, int flag);
555 
556 
557 /* Performing search for possibly truncated node name.
558  */
559 int iso_dir_get_node_trunc(IsoDir *dir, int truncate_length,
560                            const char *name, IsoNode **node);
561 
562 
563 #endif /*LIBISO_NODE_H_*/
564