1289899Sngie/* $NetBSD: iso9660_rrip.c,v 1.14 2014/05/30 13:14:47 martin Exp $ */ 2214921Scognet 3330449Seadler/*- 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5330449Seadler * 6214921Scognet * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan 7214921Scognet * Perez-Rathke and Ram Vedam. All rights reserved. 8214921Scognet * 9214921Scognet * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys, 10214921Scognet * Alan Perez-Rathke and Ram Vedam. 11214921Scognet * 12214921Scognet * Redistribution and use in source and binary forms, with or 13214921Scognet * without modification, are permitted provided that the following 14214921Scognet * conditions are met: 15214921Scognet * 1. Redistributions of source code must retain the above copyright 16214921Scognet * notice, this list of conditions and the following disclaimer. 17214921Scognet * 2. Redistributions in binary form must reproduce the above 18214921Scognet * copyright notice, this list of conditions and the following 19214921Scognet * disclaimer in the documentation and/or other materials provided 20214921Scognet * with the distribution. 21214921Scognet * 22214921Scognet * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN 23214921Scognet * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR 24214921Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25214921Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26214921Scognet * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN 27214921Scognet * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT, 28214921Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29214921Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 30214921Scognet * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31214921Scognet * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32214921Scognet * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33214921Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 34214921Scognet * OF SUCH DAMAGE. 35214921Scognet */ 36214921Scognet/* This will hold all the function definitions 37214921Scognet * defined in iso9660_rrip.h 38214921Scognet */ 39214921Scognet 40332980Sbenno#include <sys/cdefs.h> 41332980Sbenno__FBSDID("$FreeBSD: stable/11/usr.sbin/makefs/cd9660/iso9660_rrip.c 332981 2018-04-25 01:48:15Z benno $"); 42332980Sbenno 43332980Sbenno#include <sys/queue.h> 44332980Sbenno#include <sys/types.h> 45332980Sbenno#include <stdio.h> 46332980Sbenno 47214921Scognet#include "makefs.h" 48214921Scognet#include "cd9660.h" 49214921Scognet#include "iso9660_rrip.h" 50332981Sbenno#include <util.h> 51214921Scognet 52214921Scognetstatic void cd9660_rrip_initialize_inode(cd9660node *); 53332977Sbennostatic int cd9660_susp_handle_continuation(iso9660_disk *, cd9660node *); 54332977Sbennostatic int cd9660_susp_handle_continuation_common(iso9660_disk *, cd9660node *, 55332977Sbenno int); 56214921Scognet 57214921Scognetint 58332977Sbennocd9660_susp_initialize(iso9660_disk *diskStructure, cd9660node *node, 59332977Sbenno cd9660node *parent, cd9660node *grandparent) 60214921Scognet{ 61214921Scognet cd9660node *cn; 62214921Scognet int r; 63214921Scognet 64214921Scognet /* Make sure the node is not NULL. If it is, there are major problems */ 65214921Scognet assert(node != NULL); 66214921Scognet 67214921Scognet if (!(node->type & CD9660_TYPE_DOT) && 68214921Scognet !(node->type & CD9660_TYPE_DOTDOT)) 69214921Scognet TAILQ_INIT(&(node->head)); 70214921Scognet if (node->dot_record != 0) 71214921Scognet TAILQ_INIT(&(node->dot_record->head)); 72214921Scognet if (node->dot_dot_record != 0) 73214921Scognet TAILQ_INIT(&(node->dot_dot_record->head)); 74214921Scognet 75214921Scognet /* SUSP specific entries here */ 76332977Sbenno if ((r = cd9660_susp_initialize_node(diskStructure, node)) < 0) 77214921Scognet return r; 78214921Scognet 79214921Scognet /* currently called cd9660node_rrip_init_links */ 80332977Sbenno r = cd9660_rrip_initialize_node(diskStructure, node, parent, grandparent); 81214921Scognet if (r < 0) 82214921Scognet return r; 83214921Scognet 84214921Scognet /* 85214921Scognet * See if we need a CE record, and set all of the 86214921Scognet * associated counters. 87214921Scognet * 88214921Scognet * This should be called after all extensions. After 89214921Scognet * this is called, no new records should be added. 90214921Scognet */ 91332977Sbenno if ((r = cd9660_susp_handle_continuation(diskStructure, node)) < 0) 92214921Scognet return r; 93214921Scognet 94214921Scognet /* Recurse on children. */ 95214921Scognet TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) { 96332977Sbenno if ((r = cd9660_susp_initialize(diskStructure, cn, node, parent)) < 0) 97214921Scognet return 0; 98214921Scognet } 99214921Scognet return 1; 100214921Scognet} 101214921Scognet 102214921Scognetint 103332977Sbennocd9660_susp_finalize(iso9660_disk *diskStructure, cd9660node *node) 104214921Scognet{ 105214921Scognet cd9660node *temp; 106214921Scognet int r; 107214921Scognet 108214921Scognet assert(node != NULL); 109214921Scognet 110332977Sbenno if (node == diskStructure->rootNode) 111332977Sbenno diskStructure->susp_continuation_area_current_free = 0; 112214921Scognet 113332977Sbenno if ((r = cd9660_susp_finalize_node(diskStructure, node)) < 0) 114214921Scognet return r; 115214921Scognet if ((r = cd9660_rrip_finalize_node(node)) < 0) 116214921Scognet return r; 117214921Scognet 118214921Scognet TAILQ_FOREACH(temp, &node->cn_children, cn_next_child) { 119332977Sbenno if ((r = cd9660_susp_finalize(diskStructure, temp)) < 0) 120214921Scognet return r; 121214921Scognet } 122214921Scognet return 1; 123214921Scognet} 124214921Scognet 125214921Scognet/* 126214921Scognet * If we really wanted to speed things up, we could have some sort of 127214921Scognet * lookup table on the SUSP entry type that calls a functor. Or, we could 128214921Scognet * combine the functions. These functions are kept separate to allow 129214921Scognet * easier addition of other extensions. 130214921Scognet 131214921Scognet * For the sake of simplicity and clarity, we won't be doing that for now. 132214921Scognet */ 133214921Scognet 134214921Scognet/* 135214921Scognet * SUSP needs to update the following types: 136214921Scognet * CE (continuation area) 137214921Scognet */ 138214921Scognetint 139332977Sbennocd9660_susp_finalize_node(iso9660_disk *diskStructure, cd9660node *node) 140214921Scognet{ 141214921Scognet struct ISO_SUSP_ATTRIBUTES *t; 142214921Scognet 143214921Scognet /* Handle CE counters */ 144214921Scognet if (node->susp_entry_ce_length > 0) { 145214921Scognet node->susp_entry_ce_start = 146332977Sbenno diskStructure->susp_continuation_area_current_free; 147332977Sbenno diskStructure->susp_continuation_area_current_free += 148214921Scognet node->susp_entry_ce_length; 149214921Scognet } 150214921Scognet 151214921Scognet TAILQ_FOREACH(t, &node->head, rr_ll) { 152214921Scognet if (t->susp_type != SUSP_TYPE_SUSP || 153214921Scognet t->entry_type != SUSP_ENTRY_SUSP_CE) 154214921Scognet continue; 155214921Scognet cd9660_bothendian_dword( 156332977Sbenno diskStructure-> 157214921Scognet susp_continuation_area_start_sector, 158214921Scognet t->attr.su_entry.CE.ca_sector); 159214921Scognet 160214921Scognet cd9660_bothendian_dword( 161332977Sbenno diskStructure-> 162214921Scognet susp_continuation_area_start_sector, 163214921Scognet t->attr.su_entry.CE.ca_sector); 164214921Scognet cd9660_bothendian_dword(node->susp_entry_ce_start, 165214921Scognet t->attr.su_entry.CE.offset); 166214921Scognet cd9660_bothendian_dword(node->susp_entry_ce_length, 167214921Scognet t->attr.su_entry.CE.length); 168214921Scognet } 169214921Scognet return 0; 170214921Scognet} 171214921Scognet 172214921Scognetint 173214921Scognetcd9660_rrip_finalize_node(cd9660node *node) 174214921Scognet{ 175214921Scognet struct ISO_SUSP_ATTRIBUTES *t; 176214921Scognet 177214921Scognet TAILQ_FOREACH(t, &node->head, rr_ll) { 178214921Scognet if (t->susp_type != SUSP_TYPE_RRIP) 179214921Scognet continue; 180214921Scognet switch (t->entry_type) { 181214921Scognet case SUSP_ENTRY_RRIP_CL: 182214921Scognet /* Look at rr_relocated*/ 183214921Scognet if (node->rr_relocated == NULL) 184214921Scognet return -1; 185214921Scognet cd9660_bothendian_dword( 186214921Scognet node->rr_relocated->fileDataSector, 187214921Scognet (unsigned char *) 188214921Scognet t->attr.rr_entry.CL.dir_loc); 189214921Scognet break; 190214921Scognet case SUSP_ENTRY_RRIP_PL: 191214921Scognet /* Look at rr_real_parent */ 192224762Smarius if (node->parent == NULL || 193224762Smarius node->parent->rr_real_parent == NULL) 194214921Scognet return -1; 195214921Scognet cd9660_bothendian_dword( 196224762Smarius node->parent->rr_real_parent->fileDataSector, 197214921Scognet (unsigned char *) 198214921Scognet t->attr.rr_entry.PL.dir_loc); 199214921Scognet break; 200214921Scognet } 201214921Scognet } 202214921Scognet return 0; 203214921Scognet} 204214921Scognet 205214921Scognetstatic int 206332977Sbennocd9660_susp_handle_continuation_common(iso9660_disk *diskStructure, 207332977Sbenno cd9660node *node, int space) 208214921Scognet{ 209214921Scognet int ca_used, susp_used, susp_used_pre_ce, working; 210214921Scognet struct ISO_SUSP_ATTRIBUTES *temp, *pre_ce, *last, *CE, *ST; 211214921Scognet 212214921Scognet pre_ce = last = NULL; 213214921Scognet working = 254 - space; 214214921Scognet if (node->su_tail_size > 0) 215214921Scognet /* Allow 4 bytes for "ST" record. */ 216214921Scognet working -= node->su_tail_size + 4; 217214921Scognet /* printf("There are %i bytes to work with\n",working); */ 218214921Scognet 219214921Scognet susp_used_pre_ce = susp_used = 0; 220214921Scognet ca_used = 0; 221214921Scognet TAILQ_FOREACH(temp, &node->head, rr_ll) { 222214921Scognet if (working < 0) 223214921Scognet break; 224214921Scognet /* 225214921Scognet * printf("SUSP Entry found, length is %i\n", 226214921Scognet * CD9660_SUSP_ENTRY_SIZE(temp)); 227214921Scognet */ 228214921Scognet working -= CD9660_SUSP_ENTRY_SIZE(temp); 229214921Scognet if (working >= 0) { 230214921Scognet last = temp; 231214921Scognet susp_used += CD9660_SUSP_ENTRY_SIZE(temp); 232214921Scognet } 233214921Scognet if (working >= 28) { 234214921Scognet /* 235214921Scognet * Remember the last entry after which we 236214921Scognet * could insert a "CE" entry. 237214921Scognet */ 238214921Scognet pre_ce = last; 239214921Scognet susp_used_pre_ce = susp_used; 240214921Scognet } 241214921Scognet } 242214921Scognet 243214921Scognet /* A CE entry is needed */ 244214921Scognet if (working <= 0) { 245214921Scognet CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 246214921Scognet SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY); 247214921Scognet cd9660_susp_ce(CE, node); 248214921Scognet /* This will automatically insert at the appropriate location */ 249214921Scognet if (pre_ce != NULL) 250214921Scognet TAILQ_INSERT_AFTER(&node->head, pre_ce, CE, rr_ll); 251214921Scognet else 252214921Scognet TAILQ_INSERT_HEAD(&node->head, CE, rr_ll); 253214921Scognet last = CE; 254214921Scognet susp_used = susp_used_pre_ce + 28; 255214921Scognet /* Count how much CA data is necessary */ 256214921Scognet for (temp = TAILQ_NEXT(last, rr_ll); temp != NULL; 257214921Scognet temp = TAILQ_NEXT(temp, rr_ll)) { 258214921Scognet ca_used += CD9660_SUSP_ENTRY_SIZE(temp); 259214921Scognet } 260214921Scognet } 261214921Scognet 262214921Scognet /* An ST entry is needed */ 263214921Scognet if (node->su_tail_size > 0) { 264214921Scognet ST = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 265214921Scognet SUSP_ENTRY_SUSP_ST, "ST", SUSP_LOC_ENTRY); 266214921Scognet cd9660_susp_st(ST, node); 267214921Scognet if (last != NULL) 268214921Scognet TAILQ_INSERT_AFTER(&node->head, last, ST, rr_ll); 269214921Scognet else 270214921Scognet TAILQ_INSERT_HEAD(&node->head, ST, rr_ll); 271214921Scognet last = ST; 272214921Scognet susp_used += 4; 273214921Scognet } 274214921Scognet if (last != NULL) 275214921Scognet last->last_in_suf = 1; 276214921Scognet 277214921Scognet node->susp_entry_size = susp_used; 278214921Scognet node->susp_entry_ce_length = ca_used; 279214921Scognet 280332977Sbenno diskStructure->susp_continuation_area_size += ca_used; 281214921Scognet return 1; 282214921Scognet} 283214921Scognet 284214921Scognet/* See if a continuation entry is needed for each of the different types */ 285214921Scognetstatic int 286332977Sbennocd9660_susp_handle_continuation(iso9660_disk *diskStructure, cd9660node *node) 287214921Scognet{ 288214921Scognet assert (node != NULL); 289214921Scognet 290214921Scognet /* Entry */ 291332977Sbenno if (cd9660_susp_handle_continuation_common(diskStructure, 292214921Scognet node,(int)(node->isoDirRecord->length[0])) < 0) 293214921Scognet return 0; 294214921Scognet 295214921Scognet return 1; 296214921Scognet} 297214921Scognet 298214921Scognetint 299332977Sbennocd9660_susp_initialize_node(iso9660_disk *diskStructure, cd9660node *node) 300214921Scognet{ 301214921Scognet struct ISO_SUSP_ATTRIBUTES *temp; 302214921Scognet 303214921Scognet /* 304214921Scognet * Requirements/notes: 305214921Scognet * CE: is added for us where needed 306214921Scognet * ST: not sure if it is even required, but if so, should be 307214921Scognet * handled by the CE code 308228990Suqs * PD: isn't needed (though might be added for testing) 309214921Scognet * SP: is stored ONLY on the . record of the root directory 310214921Scognet * ES: not sure 311214921Scognet */ 312214921Scognet 313214921Scognet /* Check for root directory, add SP and ER if needed. */ 314214921Scognet if (node->type & CD9660_TYPE_DOT) { 315332977Sbenno if (node->parent == diskStructure->rootNode) { 316214921Scognet temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 317214921Scognet SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT); 318214921Scognet cd9660_susp_sp(temp, node); 319214921Scognet 320214921Scognet /* Should be first entry. */ 321214921Scognet TAILQ_INSERT_HEAD(&node->head, temp, rr_ll); 322214921Scognet } 323214921Scognet } 324214921Scognet return 1; 325214921Scognet} 326214921Scognet 327214921Scognetstatic void 328214921Scognetcd9660_rrip_initialize_inode(cd9660node *node) 329214921Scognet{ 330214921Scognet struct ISO_SUSP_ATTRIBUTES *attr; 331214921Scognet 332214921Scognet /* 333214921Scognet * Inode dependent values - this may change, 334214921Scognet * but for now virtual files and directories do 335214921Scognet * not have an inode structure 336214921Scognet */ 337214921Scognet 338214921Scognet if ((node->node != NULL) && (node->node->inode != NULL)) { 339214921Scognet /* PX - POSIX attributes */ 340214921Scognet attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 341214921Scognet SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 342214921Scognet cd9660node_rrip_px(attr, node->node); 343214921Scognet 344214921Scognet TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 345214921Scognet 346214921Scognet /* TF - timestamp */ 347214921Scognet attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 348214921Scognet SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY); 349214921Scognet cd9660node_rrip_tf(attr, node->node); 350214921Scognet TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 351214921Scognet 352214921Scognet /* SL - Symbolic link */ 353214921Scognet /* ?????????? Dan - why is this here? */ 354214921Scognet if (TAILQ_EMPTY(&node->cn_children) && 355214921Scognet node->node->inode != NULL && 356214921Scognet S_ISLNK(node->node->inode->st.st_mode)) 357214921Scognet cd9660_createSL(node); 358214921Scognet 359214921Scognet /* PN - device number */ 360214921Scognet if (node->node->inode != NULL && 361214921Scognet ((S_ISCHR(node->node->inode->st.st_mode) || 362214921Scognet S_ISBLK(node->node->inode->st.st_mode)))) { 363214921Scognet attr = 364214921Scognet cd9660node_susp_create_node(SUSP_TYPE_RRIP, 365214921Scognet SUSP_ENTRY_RRIP_PN, "PN", 366214921Scognet SUSP_LOC_ENTRY); 367214921Scognet cd9660node_rrip_pn(attr, node->node); 368214921Scognet TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 369214921Scognet } 370214921Scognet } 371214921Scognet} 372214921Scognet 373214921Scognetint 374332977Sbennocd9660_rrip_initialize_node(iso9660_disk *diskStructure, cd9660node *node, 375332977Sbenno cd9660node *parent, cd9660node *grandparent) 376214921Scognet{ 377214921Scognet struct ISO_SUSP_ATTRIBUTES *current = NULL; 378214921Scognet 379214921Scognet assert(node != NULL); 380214921Scognet 381214921Scognet if (node->type & CD9660_TYPE_DOT) { 382214921Scognet /* 383214921Scognet * Handle ER - should be the only entry to appear on 384214921Scognet * a "." record 385214921Scognet */ 386332977Sbenno if (node->parent == diskStructure->rootNode) { 387214921Scognet cd9660_susp_ER(node, 1, SUSP_RRIP_ER_EXT_ID, 388214921Scognet SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC); 389214921Scognet } 390214921Scognet if (parent != NULL && parent->node != NULL && 391214921Scognet parent->node->inode != NULL) { 392214921Scognet /* PX - POSIX attributes */ 393214921Scognet current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 394214921Scognet SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 395214921Scognet cd9660node_rrip_px(current, parent->node); 396214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 397214921Scognet } 398214921Scognet } else if (node->type & CD9660_TYPE_DOTDOT) { 399214921Scognet if (grandparent != NULL && grandparent->node != NULL && 400214921Scognet grandparent->node->inode != NULL) { 401214921Scognet /* PX - POSIX attributes */ 402214921Scognet current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 403214921Scognet SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 404214921Scognet cd9660node_rrip_px(current, grandparent->node); 405214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 406214921Scognet } 407224762Smarius /* Handle PL */ 408224762Smarius if (parent != NULL && parent->rr_real_parent != NULL) { 409224762Smarius current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 410224762Smarius SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT); 411224762Smarius cd9660_rrip_PL(current,node); 412224762Smarius TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 413224762Smarius } 414214921Scognet } else { 415214921Scognet cd9660_rrip_initialize_inode(node); 416214921Scognet 417214921Scognet /* 418214921Scognet * Not every node needs a NM set - only if the name is 419214921Scognet * actually different. IE: If a file is TEST -> TEST, 420214921Scognet * no NM. test -> TEST, need a NM 421214921Scognet * 422214921Scognet * The rr_moved_dir needs to be assigned a NM record as well. 423214921Scognet */ 424332977Sbenno if (node == diskStructure->rr_moved_dir) { 425214921Scognet cd9660_rrip_add_NM(node, RRIP_DEFAULT_MOVE_DIR_NAME); 426214921Scognet } 427214921Scognet else if ((node->node != NULL) && 428214921Scognet ((strlen(node->node->name) != 429253707Smarius (uint8_t)node->isoDirRecord->name_len[0]) || 430214921Scognet (memcmp(node->node->name,node->isoDirRecord->name, 431253707Smarius (uint8_t)node->isoDirRecord->name_len[0]) != 0))) { 432214921Scognet cd9660_rrip_NM(node); 433214921Scognet } 434214921Scognet 435214921Scognet 436214921Scognet 437214921Scognet /* Rock ridge directory relocation code here. */ 438214921Scognet 439214921Scognet /* First handle the CL for the placeholder file. */ 440214921Scognet if (node->rr_relocated != NULL) { 441214921Scognet current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 442214921Scognet SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY); 443214921Scognet cd9660_rrip_CL(current, node); 444214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 445214921Scognet } 446214921Scognet 447214921Scognet /* Handle RE*/ 448214921Scognet if (node->rr_real_parent != NULL) { 449214921Scognet current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 450214921Scognet SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY); 451214921Scognet cd9660_rrip_RE(current,node); 452214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 453214921Scognet } 454214921Scognet } 455214921Scognet return 1; 456214921Scognet} 457214921Scognet 458214921Scognetstruct ISO_SUSP_ATTRIBUTES* 459214921Scognetcd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id, 460214921Scognet int write_loc) 461214921Scognet{ 462214921Scognet struct ISO_SUSP_ATTRIBUTES* temp; 463214921Scognet 464332981Sbenno temp = emalloc(sizeof(*temp)); 465214921Scognet temp->susp_type = susp_type; 466214921Scognet temp->entry_type = entry_type; 467214921Scognet temp->last_in_suf = 0; 468214921Scognet /* Phase this out */ 469214921Scognet temp->type_of[0] = type_id[0]; 470214921Scognet temp->type_of[1] = type_id[1]; 471214921Scognet temp->write_location = write_loc; 472214921Scognet 473214921Scognet /* 474214921Scognet * Since the first four bytes is common, lets go ahead and 475214921Scognet * set the type identifier, since we are passing that to this 476214921Scognet * function anyhow. 477214921Scognet */ 478214921Scognet temp->attr.su_entry.SP.h.type[0] = type_id[0]; 479214921Scognet temp->attr.su_entry.SP.h.type[1] = type_id[1]; 480214921Scognet return temp; 481214921Scognet} 482214921Scognet 483214921Scognetint 484214921Scognetcd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES* p, cd9660node *node __unused) 485214921Scognet{ 486214921Scognet p->attr.rr_entry.PL.h.length[0] = 12; 487214921Scognet p->attr.rr_entry.PL.h.version[0] = 1; 488214921Scognet return 1; 489214921Scognet} 490214921Scognet 491214921Scognetint 492214921Scognetcd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) 493214921Scognet{ 494214921Scognet p->attr.rr_entry.CL.h.length[0] = 12; 495214921Scognet p->attr.rr_entry.CL.h.version[0] = 1; 496214921Scognet return 1; 497214921Scognet} 498214921Scognet 499214921Scognetint 500214921Scognetcd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) 501214921Scognet{ 502224762Smarius p->attr.rr_entry.RE.h.length[0] = 4; 503214921Scognet p->attr.rr_entry.RE.h.version[0] = 1; 504214921Scognet return 1; 505214921Scognet} 506214921Scognet 507214921Scognetvoid 508214921Scognetcd9660_createSL(cd9660node *node) 509214921Scognet{ 510214921Scognet struct ISO_SUSP_ATTRIBUTES* current; 511214921Scognet int path_count, dir_count, done, i, j, dir_copied; 512214921Scognet char temp_cr[255]; 513214921Scognet char temp_sl[255]; /* used in copying continuation entry*/ 514214921Scognet char* sl_ptr; 515214921Scognet 516214921Scognet sl_ptr = node->node->symlink; 517214921Scognet 518214921Scognet done = 0; 519214921Scognet path_count = 0; 520214921Scognet dir_count = 0; 521214921Scognet dir_copied = 0; 522214921Scognet current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 523214921Scognet SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); 524214921Scognet 525214921Scognet current->attr.rr_entry.SL.h.version[0] = 1; 526214921Scognet current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; 527214921Scognet 528214921Scognet if (*sl_ptr == '/') { 529214921Scognet temp_cr[0] = SL_FLAGS_ROOT; 530214921Scognet temp_cr[1] = 0; 531214921Scognet memcpy(current->attr.rr_entry.SL.component + path_count, 532214921Scognet temp_cr, 2); 533214921Scognet path_count += 2; 534214921Scognet sl_ptr++; 535214921Scognet } 536214921Scognet 537214921Scognet for (i = 0; i < (dir_count + 2); i++) 538214921Scognet temp_cr[i] = '\0'; 539214921Scognet 540214921Scognet while (!done) { 541214921Scognet while ((*sl_ptr != '/') && (*sl_ptr != '\0')) { 542214921Scognet dir_copied = 1; 543214921Scognet if (*sl_ptr == '.') { 544214921Scognet if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1) 545214921Scognet == '\0')) { 546214921Scognet temp_cr[0] = SL_FLAGS_CURRENT; 547214921Scognet sl_ptr++; 548214921Scognet } else if(*(sl_ptr + 1) == '.') { 549214921Scognet if ((*(sl_ptr + 2) == '/') || 550214921Scognet (*(sl_ptr + 2) == '\0')) { 551214921Scognet temp_cr[0] = SL_FLAGS_PARENT; 552214921Scognet sl_ptr += 2; 553214921Scognet } 554214921Scognet } else { 555214921Scognet temp_cr[dir_count+2] = *sl_ptr; 556214921Scognet sl_ptr++; 557214921Scognet dir_count++; 558214921Scognet } 559214921Scognet } else { 560214921Scognet temp_cr[dir_count + 2] = *sl_ptr; 561214921Scognet sl_ptr++; 562214921Scognet dir_count++; 563214921Scognet } 564214921Scognet } 565214921Scognet 566214921Scognet if ((path_count + dir_count) >= 249) { 567214921Scognet current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE; 568214921Scognet 569214921Scognet j = 0; 570214921Scognet 571214921Scognet if (path_count <= 249) { 572214921Scognet while(j != (249 - path_count)) { 573214921Scognet temp_sl[j] = temp_cr[j]; 574214921Scognet j++; 575214921Scognet } 576214921Scognet temp_sl[0] = SL_FLAGS_CONTINUE; 577214921Scognet temp_sl[1] = j - 2; 578214921Scognet memcpy( 579214921Scognet current->attr.rr_entry.SL.component + 580214921Scognet path_count, 581214921Scognet temp_sl, j); 582214921Scognet } 583214921Scognet 584214921Scognet path_count += j; 585214921Scognet current->attr.rr_entry.SL.h.length[0] = path_count + 5; 586214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 587214921Scognet current= cd9660node_susp_create_node(SUSP_TYPE_RRIP, 588214921Scognet SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); 589214921Scognet current->attr.rr_entry.SL.h.version[0] = 1; 590214921Scognet current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; 591214921Scognet 592214921Scognet path_count = 0; 593214921Scognet 594214921Scognet if (dir_count > 2) { 595214921Scognet while (j != dir_count + 2) { 596214921Scognet current->attr.rr_entry.SL.component[ 597214921Scognet path_count + 2] = temp_cr[j]; 598214921Scognet j++; 599214921Scognet path_count++; 600214921Scognet } 601214921Scognet current->attr.rr_entry.SL.component[1] 602214921Scognet = path_count; 603214921Scognet path_count+= 2; 604214921Scognet } else { 605214921Scognet while(j != dir_count) { 606214921Scognet current->attr.rr_entry.SL.component[ 607214921Scognet path_count+2] = temp_cr[j]; 608214921Scognet j++; 609214921Scognet path_count++; 610214921Scognet } 611214921Scognet } 612214921Scognet } else { 613214921Scognet if (dir_copied == 1) { 614214921Scognet temp_cr[1] = dir_count; 615214921Scognet memcpy(current->attr.rr_entry.SL.component + 616214921Scognet path_count, 617214921Scognet temp_cr, dir_count + 2); 618214921Scognet path_count += dir_count + 2; 619214921Scognet } 620214921Scognet } 621214921Scognet 622214921Scognet if (*sl_ptr == '\0') { 623214921Scognet done = 1; 624214921Scognet current->attr.rr_entry.SL.h.length[0] = path_count + 5; 625214921Scognet TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 626214921Scognet } else { 627214921Scognet sl_ptr++; 628214921Scognet dir_count = 0; 629214921Scognet dir_copied = 0; 630214921Scognet for(i = 0; i < 255; i++) { 631214921Scognet temp_cr[i] = '\0'; 632214921Scognet } 633214921Scognet } 634214921Scognet } 635214921Scognet} 636214921Scognet 637214921Scognetint 638214921Scognetcd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo) 639214921Scognet{ 640260041Smarius v->attr.rr_entry.PX.h.length[0] = 44; 641214921Scognet v->attr.rr_entry.PX.h.version[0] = 1; 642214921Scognet cd9660_bothendian_dword(pxinfo->inode->st.st_mode, 643214921Scognet v->attr.rr_entry.PX.mode); 644214921Scognet cd9660_bothendian_dword(pxinfo->inode->st.st_nlink, 645214921Scognet v->attr.rr_entry.PX.links); 646214921Scognet cd9660_bothendian_dword(pxinfo->inode->st.st_uid, 647214921Scognet v->attr.rr_entry.PX.uid); 648214921Scognet cd9660_bothendian_dword(pxinfo->inode->st.st_gid, 649214921Scognet v->attr.rr_entry.PX.gid); 650260041Smarius cd9660_bothendian_dword(pxinfo->inode->st.st_ino, 651260041Smarius v->attr.rr_entry.PX.serial); 652214921Scognet 653214921Scognet return 1; 654214921Scognet} 655214921Scognet 656214921Scognetint 657214921Scognetcd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode) 658214921Scognet{ 659214921Scognet pn_field->attr.rr_entry.PN.h.length[0] = 20; 660214921Scognet pn_field->attr.rr_entry.PN.h.version[0] = 1; 661214921Scognet 662289899Sngie if (sizeof (fnode->inode->st.st_rdev) > 4) 663289899Sngie cd9660_bothendian_dword( 664289899Sngie (uint64_t)fnode->inode->st.st_rdev >> 32, 665214921Scognet pn_field->attr.rr_entry.PN.high); 666214921Scognet else 667214921Scognet cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high); 668214921Scognet 669289899Sngie cd9660_bothendian_dword(fnode->inode->st.st_rdev & 0xffffffff, 670214921Scognet pn_field->attr.rr_entry.PN.low); 671214921Scognet return 1; 672214921Scognet} 673214921Scognet 674214921Scognet#if 0 675214921Scognetint 676214921Scognetcd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node) 677214921Scognet{ 678214921Scognet int nm_length = strlen(file_node->isoDirRecord->name) + 5; 679214921Scognet p->attr.rr_entry.NM.h.type[0] = 'N'; 680214921Scognet p->attr.rr_entry.NM.h.type[1] = 'M'; 681214921Scognet sprintf(p->attr.rr_entry.NM.altname, "%s", file_node->isoDirRecord->name); 682214921Scognet p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length; 683214921Scognet p->attr.rr_entry.NM.h.version[0] = (unsigned char)1; 684214921Scognet p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT; 685214921Scognet return 1; 686214921Scognet} 687214921Scognet#endif 688214921Scognet 689214921Scognetint 690214921Scognetcd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node) 691214921Scognet{ 692214921Scognet p->attr.rr_entry.TF.flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES; 693253707Smarius p->attr.rr_entry.TF.h.length[0] = 5; 694214921Scognet p->attr.rr_entry.TF.h.version[0] = 1; 695214921Scognet 696214921Scognet /* 697214921Scognet * Need to add creation time, backup time, 698214921Scognet * expiration time, and effective time. 699214921Scognet */ 700214921Scognet 701214921Scognet cd9660_time_915(p->attr.rr_entry.TF.timestamp, 702214921Scognet _node->inode->st.st_atime); 703214921Scognet p->attr.rr_entry.TF.h.length[0] += 7; 704214921Scognet 705214921Scognet cd9660_time_915(p->attr.rr_entry.TF.timestamp + 7, 706214921Scognet _node->inode->st.st_mtime); 707214921Scognet p->attr.rr_entry.TF.h.length[0] += 7; 708214921Scognet 709214921Scognet cd9660_time_915(p->attr.rr_entry.TF.timestamp + 14, 710214921Scognet _node->inode->st.st_ctime); 711214921Scognet p->attr.rr_entry.TF.h.length[0] += 7; 712214921Scognet return 1; 713214921Scognet} 714214921Scognet 715214921Scognetint 716214921Scognetcd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) 717214921Scognet{ 718214921Scognet p->attr.su_entry.SP.h.length[0] = 7; 719214921Scognet p->attr.su_entry.SP.h.version[0] = 1; 720214921Scognet p->attr.su_entry.SP.check[0] = 0xBE; 721214921Scognet p->attr.su_entry.SP.check[1] = 0xEF; 722214921Scognet p->attr.su_entry.SP.len_skp[0] = 0; 723214921Scognet return 1; 724214921Scognet} 725214921Scognet 726214921Scognetint 727214921Scognetcd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo __unused) 728214921Scognet{ 729214921Scognet p->attr.su_entry.ST.h.type[0] = 'S'; 730214921Scognet p->attr.su_entry.ST.h.type[1] = 'T'; 731214921Scognet p->attr.su_entry.ST.h.length[0] = 4; 732214921Scognet p->attr.su_entry.ST.h.version[0] = 1; 733214921Scognet return 1; 734214921Scognet} 735214921Scognet 736214921Scognetint 737214921Scognetcd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) 738214921Scognet{ 739214921Scognet p->attr.su_entry.CE.h.length[0] = 28; 740214921Scognet p->attr.su_entry.CE.h.version[0] = 1; 741214921Scognet /* Other attributes dont matter right now, will be updated later */ 742214921Scognet return 1; 743214921Scognet} 744214921Scognet 745214921Scognetint 746214921Scognetcd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p __unused, int length __unused) 747214921Scognet{ 748214921Scognet return 1; 749214921Scognet} 750214921Scognet 751214921Scognetvoid 752214921Scognetcd9660_rrip_add_NM(cd9660node *node, const char *name) 753214921Scognet{ 754214921Scognet int working,len; 755214921Scognet const char *p; 756214921Scognet struct ISO_SUSP_ATTRIBUTES *r; 757214921Scognet 758214921Scognet /* 759214921Scognet * Each NM record has 254 byes to work with. This means that 760214921Scognet * the name data itself only has 249 bytes to work with. So, a 761214921Scognet * name with 251 characters would require two nm records. 762214921Scognet */ 763214921Scognet p = name; 764214921Scognet working = 1; 765214921Scognet while (working) { 766214921Scognet r = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 767214921Scognet SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY); 768214921Scognet r->attr.rr_entry.NM.h.version[0] = 1; 769214921Scognet r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE; 770214921Scognet len = strlen(p); 771214921Scognet 772214921Scognet if (len > 249) { 773214921Scognet len = 249; 774214921Scognet r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE; 775214921Scognet } else { 776214921Scognet working = 0; 777214921Scognet } 778214921Scognet memcpy(r->attr.rr_entry.NM.altname, p, len); 779214921Scognet r->attr.rr_entry.NM.h.length[0] = 5 + len; 780214921Scognet 781214921Scognet TAILQ_INSERT_TAIL(&node->head, r, rr_ll); 782214921Scognet 783214921Scognet p += len; 784214921Scognet } 785214921Scognet} 786214921Scognet 787214921Scognetvoid 788214921Scognetcd9660_rrip_NM(cd9660node *node) 789214921Scognet{ 790214921Scognet cd9660_rrip_add_NM(node, node->node->name); 791214921Scognet} 792214921Scognet 793214921Scognetstruct ISO_SUSP_ATTRIBUTES* 794214921Scognetcd9660_susp_ER(cd9660node *node, 795214921Scognet u_char ext_version, const char* ext_id, const char* ext_des, 796214921Scognet const char* ext_src) 797214921Scognet{ 798214921Scognet int l; 799214921Scognet struct ISO_SUSP_ATTRIBUTES *r; 800214921Scognet 801214921Scognet r = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 802214921Scognet SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT); 803214921Scognet 804214921Scognet /* Fixed data is 8 bytes */ 805214921Scognet r->attr.su_entry.ER.h.length[0] = 8; 806214921Scognet r->attr.su_entry.ER.h.version[0] = 1; 807214921Scognet 808214921Scognet r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id); 809214921Scognet r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des); 810214921Scognet r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src); 811214921Scognet 812214921Scognet l = r->attr.su_entry.ER.len_id[0] + 813214921Scognet r->attr.su_entry.ER.len_src[0] + 814214921Scognet r->attr.su_entry.ER.len_des[0]; 815214921Scognet 816214921Scognet /* Everything must fit. */ 817214921Scognet assert(l + r->attr.su_entry.ER.h.length[0] <= 254); 818214921Scognet 819214921Scognet r->attr.su_entry.ER.h.length[0] += (u_char)l; 820214921Scognet 821214921Scognet 822214921Scognet r->attr.su_entry.ER.ext_ver[0] = ext_version; 823214921Scognet memcpy(r->attr.su_entry.ER.ext_data, ext_id, 824214921Scognet (int)r->attr.su_entry.ER.len_id[0]); 825214921Scognet l = (int) r->attr.su_entry.ER.len_id[0]; 826214921Scognet memcpy(r->attr.su_entry.ER.ext_data + l,ext_des, 827214921Scognet (int)r->attr.su_entry.ER.len_des[0]); 828214921Scognet 829214921Scognet l += (int)r->attr.su_entry.ER.len_des[0]; 830214921Scognet memcpy(r->attr.su_entry.ER.ext_data + l,ext_src, 831214921Scognet (int)r->attr.su_entry.ER.len_src[0]); 832214921Scognet 833214921Scognet TAILQ_INSERT_TAIL(&node->head, r, rr_ll); 834214921Scognet return r; 835214921Scognet} 836214921Scognet 837214921Scognetstruct ISO_SUSP_ATTRIBUTES* 838214921Scognetcd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last __unused, cd9660node *node __unused) 839214921Scognet{ 840214921Scognet return NULL; 841214921Scognet} 842