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