1214921Scognet/* $NetBSD: cd9660_archimedes.c,v 1.1 2009/01/10 22:06:29 bjh21 Exp $ */ 2214921Scognet 3214921Scognet/*- 4214921Scognet * Copyright (c) 1998, 2009 Ben Harris 5214921Scognet * All rights reserved. 6214921Scognet * 7214921Scognet * Redistribution and use in source and binary forms, with or without 8214921Scognet * modification, are permitted provided that the following conditions 9214921Scognet * are met: 10214921Scognet * 1. Redistributions of source code must retain the above copyright 11214921Scognet * notice, this list of conditions and the following disclaimer. 12214921Scognet * 2. Redistributions in binary form must reproduce the above copyright 13214921Scognet * notice, this list of conditions and the following disclaimer in the 14214921Scognet * documentation and/or other materials provided with the distribution. 15214921Scognet * 3. The name of the author may not be used to endorse or promote products 16214921Scognet * derived from this software without specific prior written permission. 17214921Scognet * 18214921Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19214921Scognet * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20214921Scognet * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21214921Scognet * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22214921Scognet * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23214921Scognet * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24214921Scognet * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25214921Scognet * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26214921Scognet * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27214921Scognet * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28214921Scognet */ 29214921Scognet/* 30214921Scognet * cd9660_archimedes.c - support for RISC OS "ARCHIMEDES" extension 31214921Scognet * 32214921Scognet * RISC OS CDFS looks for a special block at the end of the System Use 33214921Scognet * Field for each file. If present, this contains the RISC OS load 34214921Scognet * and exec address (used to hold the file timestamp and type), the 35214921Scognet * file attributes, and a flag indicating whether the first character 36214921Scognet * of the filename should be replaced with '!' (since many special 37214921Scognet * RISC OS filenames do). 38214921Scognet */ 39214921Scognet 40214921Scognet#include <sys/cdefs.h> 41214921Scognet__FBSDID("$FreeBSD: releng/10.2/usr.sbin/makefs/cd9660/cd9660_archimedes.c 214921 2010-11-07 16:05:04Z cognet $"); 42214921Scognet 43214921Scognet#include <assert.h> 44214921Scognet#include <stdint.h> 45214921Scognet#include <stdio.h> 46214921Scognet#include <string.h> 47214921Scognet 48214921Scognet#include "makefs.h" 49214921Scognet#include "cd9660.h" 50214921Scognet#include "cd9660_archimedes.h" 51214921Scognet 52214921Scognet/* 53214921Scognet * Convert a Unix time_t (non-leap seconds since 1970-01-01) to a RISC 54214921Scognet * OS time (non-leap(?) centiseconds since 1900-01-01(?)). 55214921Scognet */ 56214921Scognet 57214921Scognetstatic u_int64_t 58214921Scognetriscos_date(time_t unixtime) 59214921Scognet{ 60214921Scognet u_int64_t base; 61214921Scognet 62214921Scognet base = 31536000ULL * 70 + 86400 * 17; 63214921Scognet return (((u_int64_t)unixtime) + base)*100; 64214921Scognet} 65214921Scognet 66214921Scognet/* 67214921Scognet * Add "ARCHIMEDES" metadata to a node if that seems appropriate. 68214921Scognet * 69214921Scognet * We touch regular files with names matching /,[0-9a-f]{3}$/ and 70214921Scognet * directories matching /^!/. 71214921Scognet */ 72214921Scognetstatic void 73214921Scognetarchimedes_convert_node(cd9660node *node) 74214921Scognet{ 75214921Scognet struct ISO_ARCHIMEDES *arc; 76214921Scognet size_t len; 77214921Scognet int type = -1; 78214921Scognet uint64_t stamp; 79214921Scognet 80214921Scognet if (node->su_tail_data != NULL) 81214921Scognet /* Something else already has the tail. */ 82214921Scognet return; 83214921Scognet 84214921Scognet len = strlen(node->node->name); 85214921Scognet if (len < 1) return; 86214921Scognet 87214921Scognet if (len >= 4 && node->node->name[len-4] == ',') 88214921Scognet /* XXX should support ,xxx and ,lxa */ 89214921Scognet type = strtoul(node->node->name + len - 3, NULL, 16); 90214921Scognet if (type == -1 && node->node->name[0] != '!') 91214921Scognet return; 92214921Scognet if (type == -1) type = 0; 93214921Scognet 94214921Scognet assert(sizeof(struct ISO_ARCHIMEDES) == 32); 95214921Scognet if ((arc = calloc(1, sizeof(struct ISO_ARCHIMEDES))) == NULL) { 96214921Scognet CD9660_MEM_ALLOC_ERROR("archimedes_convert_node"); 97214921Scognet exit(1); 98214921Scognet } 99214921Scognet 100214921Scognet stamp = riscos_date(node->node->inode->st.st_mtime); 101214921Scognet 102214921Scognet memcpy(arc->magic, "ARCHIMEDES", 10); 103214921Scognet cd9660_731(0xfff00000 | (type << 8) | (stamp >> 32), arc->loadaddr); 104214921Scognet cd9660_731(stamp & 0x00ffffffffULL, arc->execaddr); 105214921Scognet arc->ro_attr = RO_ACCESS_UR | RO_ACCESS_OR; 106214921Scognet arc->cdfs_attr = node->node->name[0] == '!' ? CDFS_PLING : 0; 107214921Scognet node->su_tail_data = (void *)arc; 108214921Scognet node->su_tail_size = sizeof(*arc); 109214921Scognet} 110214921Scognet 111214921Scognet/* 112214921Scognet * Add "ARCHIMEDES" metadata to an entire tree recursively. 113214921Scognet */ 114214921Scognetvoid 115214921Scognetarchimedes_convert_tree(cd9660node *node) 116214921Scognet{ 117214921Scognet cd9660node *cn; 118214921Scognet 119214921Scognet assert(node != NULL); 120214921Scognet 121214921Scognet archimedes_convert_node(node); 122214921Scognet 123214921Scognet /* Recurse on children. */ 124214921Scognet TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) 125214921Scognet archimedes_convert_tree(cn); 126214921Scognet} 127