1 /* $NetBSD: ffs_appleufs.c,v 1.12 2011/11/19 22:51:31 tls 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.12 2011/11/19 22:51:31 tls 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 #include <sys/cprng.h> 37 #endif 38 39 #include <ufs/ufs/dinode.h> 40 #include <ufs/ufs/ufs_bswap.h> 41 #include <ufs/ffs/fs.h> 42 #include <ufs/ffs/ffs_extern.h> 43 44 #if !defined(_KERNEL) && !defined(STANDALONE) 45 #include <stddef.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <errno.h> 50 #include <assert.h> 51 #define KASSERT(x) assert(x) 52 #endif 53 54 /* 55 * this is the same calculation as in_cksum 56 */ 57 u_int16_t 58 ffs_appleufs_cksum(const struct appleufslabel *appleufs) 59 { 60 const u_int16_t *p = (const u_int16_t *)appleufs; 61 int len = APPLEUFS_LABEL_SIZE; /* sizeof(struct appleufslabel) */ 62 long res = 0; 63 while (len > 1) { 64 res += *p++; 65 len -= 2; 66 } 67 #if 0 /* APPLEUFS_LABEL_SIZE is guaranteed to be even */ 68 if (len == 1) 69 res += htobe16(*(u_char *)p<<8); 70 #endif 71 res = (res >> 16) + (res & 0xffff); 72 res += (res >> 16); 73 return (~res); 74 } 75 76 /* copies o to n, validating and byteswapping along the way 77 * returns 0 if ok, EINVAL if not valid 78 */ 79 int 80 ffs_appleufs_validate(const char *name, const struct appleufslabel *o, 81 struct appleufslabel *n) 82 { 83 struct appleufslabel tmp; 84 if (!n) n = &tmp; 85 86 if (o->ul_magic != be32toh(APPLEUFS_LABEL_MAGIC)) { 87 return EINVAL; 88 } 89 *n = *o; 90 n->ul_checksum = 0; 91 n->ul_checksum = ffs_appleufs_cksum(n); 92 if (n->ul_checksum != o->ul_checksum) { 93 #if defined(DIAGNOSTIC) || !defined(_KERNEL) 94 printf("%s: invalid APPLE UFS checksum. found 0x%x, expecting 0x%x", 95 name,o->ul_checksum,n->ul_checksum); 96 #endif 97 return EINVAL; 98 } 99 n->ul_magic = be32toh(o->ul_magic); 100 n->ul_version = be32toh(o->ul_version); 101 n->ul_time = be32toh(o->ul_time); 102 n->ul_namelen = be16toh(o->ul_namelen); 103 104 if (n->ul_namelen > APPLEUFS_MAX_LABEL_NAME) { 105 #if defined(DIAGNOSTIC) || !defined(_KERNEL) 106 printf("%s: APPLE UFS label name too long, truncated.\n", 107 name); 108 #endif 109 n->ul_namelen = APPLEUFS_MAX_LABEL_NAME; 110 } 111 /* if len is max, will set ul_unused1 */ 112 n->ul_name[n->ul_namelen - 1] = '\0'; 113 114 #ifdef DEBUG 115 printf("%s: found APPLE UFS label v%d: \"%s\"\n", 116 name,n->ul_version,n->ul_name); 117 #endif 118 n->ul_uuid = be64toh(o->ul_uuid); 119 120 return 0; 121 } 122 123 void 124 ffs_appleufs_set(struct appleufslabel *appleufs, const char *name, time_t t, 125 uint64_t uuid) 126 { 127 size_t namelen; 128 if (!name) name = "untitled"; 129 if (t == ((time_t)-1)) { 130 #if defined(_KERNEL) 131 t = time_second; 132 #elif defined(STANDALONE) 133 t = 0; 134 #else 135 (void)time(&t); 136 #endif 137 } 138 if (uuid == 0) { 139 #if defined(_KERNEL) && !defined(STANDALONE) 140 uuid = cprng_fast64(); 141 #endif 142 } 143 namelen = strlen(name); 144 if (namelen > APPLEUFS_MAX_LABEL_NAME) 145 namelen = APPLEUFS_MAX_LABEL_NAME; 146 memset(appleufs, 0, APPLEUFS_LABEL_SIZE); 147 appleufs->ul_magic = htobe32(APPLEUFS_LABEL_MAGIC); 148 appleufs->ul_version = htobe32(APPLEUFS_LABEL_VERSION); 149 appleufs->ul_time = htobe32((u_int32_t)t); 150 appleufs->ul_namelen = htobe16(namelen); 151 strncpy(appleufs->ul_name,name,namelen); 152 appleufs->ul_uuid = htobe64(uuid); 153 appleufs->ul_checksum = ffs_appleufs_cksum(appleufs); 154 } 155