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