1/* $NetBSD: ffs_appleufs.c,v 1.14 2015/02/14 08:07:39 maxv 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.14 2015/02/14 08:07:39 maxv 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 */ 57u_int16_t 58ffs_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/* 77 * Copies o to n, validating and byteswapping along the way. Returns 0 if ok, 78 * EINVAL if not valid. 79 */ 80int 81ffs_appleufs_validate(const char *name, const struct appleufslabel *o, 82 struct appleufslabel *n) 83{ 84 struct appleufslabel tmp; 85 86 if (!n) 87 n = &tmp; 88 if (o->ul_magic != be32toh(APPLEUFS_LABEL_MAGIC)) 89 return EINVAL; 90 91 *n = *o; 92 n->ul_checksum = 0; 93 n->ul_checksum = ffs_appleufs_cksum(n); 94 n->ul_magic = be32toh(o->ul_magic); 95 n->ul_version = be32toh(o->ul_version); 96 n->ul_time = be32toh(o->ul_time); 97 n->ul_namelen = be16toh(o->ul_namelen); 98 99 if (n->ul_checksum != o->ul_checksum) 100 return EINVAL; 101 if (n->ul_namelen == 0) 102 return EINVAL; 103 if (n->ul_namelen > APPLEUFS_MAX_LABEL_NAME) 104 n->ul_namelen = APPLEUFS_MAX_LABEL_NAME; 105 106 n->ul_name[n->ul_namelen - 1] = '\0'; 107 108#ifdef DEBUG 109 printf("%s: found APPLE UFS label v%d: \"%s\"\n", name, 110 n->ul_version, n->ul_name); 111#endif 112 n->ul_uuid = be64toh(o->ul_uuid); 113 114 return 0; 115} 116 117void 118ffs_appleufs_set(struct appleufslabel *appleufs, const char *name, time_t t, 119 uint64_t uuid) 120{ 121 size_t namelen; 122 123 if (!name) 124 name = "untitled"; 125 if (t == ((time_t)-1)) { 126#if defined(_KERNEL) 127 t = time_second; 128#elif defined(STANDALONE) 129 t = 0; 130#else 131 (void)time(&t); 132#endif 133 } 134 if (uuid == 0) { 135#if defined(_KERNEL) && !defined(STANDALONE) 136 uuid = cprng_fast64(); 137#endif 138 } 139 namelen = strlen(name); 140 if (namelen > APPLEUFS_MAX_LABEL_NAME) 141 namelen = APPLEUFS_MAX_LABEL_NAME; 142 memset(appleufs, 0, APPLEUFS_LABEL_SIZE); 143 appleufs->ul_magic = htobe32(APPLEUFS_LABEL_MAGIC); 144 appleufs->ul_version = htobe32(APPLEUFS_LABEL_VERSION); 145 appleufs->ul_time = htobe32((u_int32_t)t); 146 appleufs->ul_namelen = htobe16(namelen); 147 strncpy(appleufs->ul_name, name, namelen); 148 appleufs->ul_uuid = htobe64(uuid); 149 appleufs->ul_checksum = ffs_appleufs_cksum(appleufs); 150} 151