1/* $NetBSD$ */ 2 3/*- 4 * Copyright (c) 1998, 2009 Ben Harris 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * cd9660_archimedes.c - support for RISC OS "ARCHIMEDES" extension 31 * 32 * RISC OS CDFS looks for a special block at the end of the System Use 33 * Field for each file. If present, this contains the RISC OS load 34 * and exec address (used to hold the file timestamp and type), the 35 * file attributes, and a flag indicating whether the first character 36 * of the filename should be replaced with '!' (since many special 37 * RISC OS filenames do). 38 */ 39 40#if HAVE_NBTOOL_CONFIG_H 41#include "nbtool_config.h" 42#endif 43 44#include <sys/cdefs.h> 45#if defined(__RCSID) && !defined(__lint) 46__RCSID("$NetBSD: iso9660_rrip.c,v 1.6 2009/01/09 00:24:07 bjh21 Exp $"); 47#endif /* !__lint */ 48 49#include <assert.h> 50#include <stdint.h> 51#include <stdio.h> 52#include <string.h> 53 54#include "makefs.h" 55#include "cd9660.h" 56#include "cd9660_archimedes.h" 57 58/* 59 * Convert a Unix time_t (non-leap seconds since 1970-01-01) to a RISC 60 * OS time (non-leap(?) centiseconds since 1900-01-01(?)). 61 */ 62 63static u_int64_t 64riscos_date(time_t unixtime) 65{ 66 u_int64_t base; 67 68 base = 31536000ULL * 70 + 86400 * 17; 69 return (((u_int64_t)unixtime) + base)*100; 70} 71 72/* 73 * Add "ARCHIMEDES" metadata to a node if that seems appropriate. 74 * 75 * We touch regular files with names matching /,[0-9a-f]{3}$/ and 76 * directories matching /^!/. 77 */ 78static void 79archimedes_convert_node(cd9660node *node) 80{ 81 struct ISO_ARCHIMEDES *arc; 82 size_t len; 83 int type = -1; 84 uint64_t stamp; 85 86 if (node->su_tail_data != NULL) 87 /* Something else already has the tail. */ 88 return; 89 90 len = strlen(node->node->name); 91 if (len < 1) return; 92 93 if (len >= 4 && node->node->name[len-4] == ',') 94 /* XXX should support ,xxx and ,lxa */ 95 type = strtoul(node->node->name + len - 3, NULL, 16); 96 if (type == -1 && node->node->name[0] != '!') 97 return; 98 if (type == -1) type = 0; 99 100 assert(sizeof(struct ISO_ARCHIMEDES) == 32); 101 if ((arc = calloc(1, sizeof(struct ISO_ARCHIMEDES))) == NULL) { 102 CD9660_MEM_ALLOC_ERROR("archimedes_convert_node"); 103 exit(1); 104 } 105 106 stamp = riscos_date(node->node->inode->st.st_mtime); 107 108 memcpy(arc->magic, "ARCHIMEDES", 10); 109 cd9660_731(0xfff00000 | (type << 8) | (stamp >> 32), arc->loadaddr); 110 cd9660_731(stamp & 0x00ffffffffULL, arc->execaddr); 111 arc->ro_attr = RO_ACCESS_UR | RO_ACCESS_OR; 112 arc->cdfs_attr = node->node->name[0] == '!' ? CDFS_PLING : 0; 113 node->su_tail_data = (void *)arc; 114 node->su_tail_size = sizeof(*arc); 115} 116 117/* 118 * Add "ARCHIMEDES" metadata to an entire tree recursively. 119 */ 120void 121archimedes_convert_tree(cd9660node *node) 122{ 123 cd9660node *cn; 124 125 assert(node != NULL); 126 127 archimedes_convert_node(node); 128 129 /* Recurse on children. */ 130 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) 131 archimedes_convert_tree(cn); 132} 133