1 /* $NetBSD: ffs_appleufs.c,v 1.5 2004/01/02 06:57:46 dbj Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Darrin B. Jewell 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Darrin B. Jewell 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: ffs_appleufs.c,v 1.5 2004/01/02 06:57:46 dbj Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/time.h> 38 #if defined(_KERNEL) 39 #include <sys/kernel.h> 40 #include <sys/systm.h> 41 #endif 42 43 #include <ufs/ufs/dinode.h> 44 #include <ufs/ufs/ufs_bswap.h> 45 #include <ufs/ffs/fs.h> 46 #include <ufs/ffs/ffs_extern.h> 47 48 #if !defined(_KERNEL) && !defined(STANDALONE) 49 #include <stddef.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <errno.h> 54 #include <assert.h> 55 #define KASSERT(x) assert(x) 56 #endif 57 58 /* 59 * this is the same calculation as in_cksum 60 */ 61 u_int16_t 62 ffs_appleufs_cksum(appleufs) 63 const struct appleufslabel *appleufs; 64 { 65 const u_int16_t *p = (const u_int16_t *)appleufs; 66 int len = APPLEUFS_LABEL_SIZE; /* sizeof(struct appleufslabel) */ 67 long res = 0; 68 while (len > 1) { 69 res += *p++; 70 len -= 2; 71 } 72 #if 0 /* APPLEUFS_LABEL_SIZE is guaranteed to be even */ 73 if (len == 1) 74 res += htobe16(*(u_char *)p<<8); 75 #endif 76 res = (res >> 16) + (res & 0xffff); 77 res += (res >> 16); 78 return (~res); 79 } 80 81 /* copies o to n, validating and byteswapping along the way 82 * returns 0 if ok, EINVAL if not valid 83 */ 84 int 85 ffs_appleufs_validate(name,o,n) 86 const char *name; 87 const struct appleufslabel *o; 88 struct appleufslabel *n; 89 { 90 struct appleufslabel tmp; 91 if (!n) n = &tmp; 92 93 if (o->ul_magic != be32toh(APPLEUFS_LABEL_MAGIC)) { 94 return EINVAL; 95 } 96 *n = *o; 97 n->ul_checksum = 0; 98 n->ul_checksum = ffs_appleufs_cksum(n); 99 if (n->ul_checksum != o->ul_checksum) { 100 #if defined(DIAGNOSTIC) || !defined(_KERNEL) 101 printf("%s: invalid APPLE UFS checksum. found 0x%x, expecting 0x%x", 102 name,o->ul_checksum,n->ul_checksum); 103 #endif 104 return EINVAL; 105 } 106 n->ul_magic = be32toh(o->ul_magic); 107 n->ul_version = be32toh(o->ul_version); 108 n->ul_time = be32toh(o->ul_time); 109 n->ul_namelen = be16toh(o->ul_namelen); 110 111 if (n->ul_namelen > APPLEUFS_MAX_LABEL_NAME) { 112 #if defined(DIAGNOSTIC) || !defined(_KERNEL) 113 printf("%s: APPLE UFS label name too long, truncated.\n", 114 name); 115 #endif 116 n->ul_namelen = APPLEUFS_MAX_LABEL_NAME; 117 } 118 /* if len is max, will set ul_unused1 */ 119 n->ul_name[n->ul_namelen] = '\0'; 120 121 #ifdef DEBUG 122 printf("%s: found APPLE UFS label v%d: \"%s\"\n", 123 name,n->ul_version,n->ul_name); 124 #endif 125 n->ul_uuid = be64toh(o->ul_uuid); 126 127 return 0; 128 } 129 130 void 131 ffs_appleufs_set(appleufs, name, t, uuid) 132 struct appleufslabel *appleufs; 133 const char *name; 134 time_t t; 135 uint64_t uuid; 136 { 137 size_t namelen; 138 if (!name) name = "untitled"; 139 if (t == ((time_t)-1)) { 140 #if defined(_KERNEL) 141 t = time.tv_sec; 142 #elif defined(STANDALONE) 143 t = 0; 144 #else 145 (void)time(&t); 146 #endif 147 } 148 if (uuid == 0) { 149 #if defined(_KERNEL) && !defined(STANDALONE) 150 uuid = arc4random(); 151 uuid <<= 32; 152 uuid |= arc4random(); 153 #endif 154 } 155 namelen = strlen(name); 156 if (namelen > APPLEUFS_MAX_LABEL_NAME) 157 namelen = APPLEUFS_MAX_LABEL_NAME; 158 memset(appleufs, 0, APPLEUFS_LABEL_SIZE); 159 appleufs->ul_magic = htobe32(APPLEUFS_LABEL_MAGIC); 160 appleufs->ul_version = htobe32(APPLEUFS_LABEL_VERSION); 161 appleufs->ul_time = htobe32((u_int32_t)t); 162 appleufs->ul_namelen = htobe16(namelen); 163 strncpy(appleufs->ul_name,name,namelen); 164 appleufs->ul_uuid = htobe64(uuid); 165 appleufs->ul_checksum = ffs_appleufs_cksum(appleufs); 166 } 167