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