1299425Smm/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */ 2299425Smm 3299425Smm/*- 4299425Smm * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5299425Smm * All rights reserved. 6299425Smm * 7299425Smm * This code is derived from software contributed to The NetBSD Foundation 8299425Smm * by Charles M. Hannum. 9299425Smm * 10299425Smm * Redistribution and use in source and binary forms, with or without 11299425Smm * modification, are permitted provided that the following conditions 12299425Smm * are met: 13299425Smm * 1. Redistributions of source code must retain the above copyright 14299425Smm * notice, this list of conditions and the following disclaimer. 15299425Smm * 2. Redistributions in binary form must reproduce the above copyright 16299425Smm * notice, this list of conditions and the following disclaimer in the 17299425Smm * documentation and/or other materials provided with the distribution. 18299425Smm * 19299425Smm * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20299425Smm * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21299425Smm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22299425Smm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23299425Smm * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24299425Smm * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25299425Smm * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26299425Smm * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27299425Smm * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28299425Smm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29299425Smm * POSSIBILITY OF SUCH DAMAGE. 30299425Smm */ 31299425Smm 32299425Smm/* Originally from NetBSD's mknod(8) source. */ 33299425Smm 34299425Smm#include "archive_platform.h" 35299425Smm 36299425Smm#if HAVE_SYS_CDEFS_H 37299425Smm#include <sys/cdefs.h> 38299425Smm#endif 39299425Smm#if !defined(lint) 40299425Smm__RCSID("$NetBSD$"); 41299425Smm#endif /* not lint */ 42299425Smm 43299425Smm#ifdef HAVE_LIMITS_H 44299425Smm#include <limits.h> 45299425Smm#endif 46299425Smm 47299425Smm#include <stdio.h> 48299425Smm#ifdef HAVE_STDLIB_H 49299425Smm#include <stdlib.h> 50299425Smm#endif 51299425Smm#ifdef HAVE_STRING_H 52299425Smm#include <string.h> 53299425Smm#endif 54299425Smm#ifdef HAVE_SYS_TYPES_H 55299425Smm#include <sys/types.h> 56299425Smm#endif 57299425Smm#ifdef HAVE_SYS_STAT_H 58299425Smm#include <sys/stat.h> 59299425Smm#endif 60358088Smm#if MAJOR_IN_MKDEV 61358088Smm#include <sys/mkdev.h> 62358088Smm#define HAVE_MAJOR 63358088Smm#elif MAJOR_IN_SYSMACROS 64338795Smm#include <sys/sysmacros.h> 65358088Smm#define HAVE_MAJOR 66338795Smm#endif 67299425Smm#ifdef HAVE_UNISTD_H 68299425Smm#include <unistd.h> 69299425Smm#endif 70299425Smm 71299425Smm#include "archive_pack_dev.h" 72299425Smm 73299425Smmstatic pack_t pack_netbsd; 74299425Smmstatic pack_t pack_freebsd; 75299425Smmstatic pack_t pack_8_8; 76299425Smmstatic pack_t pack_12_20; 77299425Smmstatic pack_t pack_14_18; 78299425Smmstatic pack_t pack_8_24; 79299425Smmstatic pack_t pack_bsdos; 80299425Smmstatic int compare_format(const void *, const void *); 81299425Smm 82299425Smmstatic const char iMajorError[] = "invalid major number"; 83299425Smmstatic const char iMinorError[] = "invalid minor number"; 84299425Smmstatic const char tooManyFields[] = "too many fields for format"; 85299425Smm 86299425Smm/* This is blatantly stolen from libarchive/archive_entry.c, 87299425Smm * in an attempt to get this to play nice on MinGW... */ 88299425Smm#if !defined(HAVE_MAJOR) && !defined(major) 89299425Smm/* Replacement for major/minor/makedev. */ 90299425Smm#define major(x) ((int)(0x00ff & ((x) >> 8))) 91299425Smm#define minor(x) ((int)(0xffff00ff & (x))) 92299425Smm#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) 93299425Smm#endif 94299425Smm 95299425Smm/* Play games to come up with a suitable makedev() definition. */ 96299425Smm#ifdef __QNXNTO__ 97299425Smm/* QNX. <sigh> */ 98299425Smm#include <sys/netmgr.h> 99299425Smm#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) 100299425Smm#elif defined makedev 101299425Smm/* There's a "makedev" macro. */ 102299425Smm#define apd_makedev(maj, min) makedev((maj), (min)) 103299425Smm#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) 104299425Smm/* Windows. <sigh> */ 105299425Smm#define apd_makedev(maj, min) mkdev((maj), (min)) 106299425Smm#else 107299425Smm/* There's a "makedev" function. */ 108299425Smm#define apd_makedev(maj, min) makedev((maj), (min)) 109299425Smm#endif 110299425Smm 111299425Smm/* exported */ 112299425Smmdev_t 113299425Smmpack_native(int n, unsigned long numbers[], const char **error) 114299425Smm{ 115299425Smm dev_t dev = 0; 116299425Smm 117299425Smm if (n == 2) { 118299425Smm dev = apd_makedev(numbers[0], numbers[1]); 119299425Smm if ((unsigned long)major(dev) != numbers[0]) 120299425Smm *error = iMajorError; 121299425Smm else if ((unsigned long)minor(dev) != numbers[1]) 122299425Smm *error = iMinorError; 123299425Smm } else 124299425Smm *error = tooManyFields; 125299425Smm return (dev); 126299425Smm} 127299425Smm 128299425Smm 129299425Smmstatic dev_t 130299425Smmpack_netbsd(int n, unsigned long numbers[], const char **error) 131299425Smm{ 132299425Smm dev_t dev = 0; 133299425Smm 134299425Smm if (n == 2) { 135299425Smm dev = makedev_netbsd(numbers[0], numbers[1]); 136299425Smm if ((unsigned long)major_netbsd(dev) != numbers[0]) 137299425Smm *error = iMajorError; 138299425Smm else if ((unsigned long)minor_netbsd(dev) != numbers[1]) 139299425Smm *error = iMinorError; 140299425Smm } else 141299425Smm *error = tooManyFields; 142299425Smm return (dev); 143299425Smm} 144299425Smm 145299425Smm 146299425Smm#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 147299425Smm#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 148299425Smm#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 149299425Smm (((y) << 0) & 0xffff00ff))) 150299425Smm 151299425Smmstatic dev_t 152299425Smmpack_freebsd(int n, unsigned long numbers[], const char **error) 153299425Smm{ 154299425Smm dev_t dev = 0; 155299425Smm 156299425Smm if (n == 2) { 157299425Smm dev = makedev_freebsd(numbers[0], numbers[1]); 158299425Smm if ((unsigned long)major_freebsd(dev) != numbers[0]) 159299425Smm *error = iMajorError; 160299425Smm if ((unsigned long)minor_freebsd(dev) != numbers[1]) 161299425Smm *error = iMinorError; 162299425Smm } else 163299425Smm *error = tooManyFields; 164299425Smm return (dev); 165299425Smm} 166299425Smm 167299425Smm 168299425Smm#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 169299425Smm#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 170299425Smm#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 171299425Smm (((y) << 0) & 0x000000ff))) 172299425Smm 173299425Smmstatic dev_t 174299425Smmpack_8_8(int n, unsigned long numbers[], const char **error) 175299425Smm{ 176299425Smm dev_t dev = 0; 177299425Smm 178299425Smm if (n == 2) { 179299425Smm dev = makedev_8_8(numbers[0], numbers[1]); 180299425Smm if ((unsigned long)major_8_8(dev) != numbers[0]) 181299425Smm *error = iMajorError; 182299425Smm if ((unsigned long)minor_8_8(dev) != numbers[1]) 183299425Smm *error = iMinorError; 184299425Smm } else 185299425Smm *error = tooManyFields; 186299425Smm return (dev); 187299425Smm} 188299425Smm 189299425Smm 190299425Smm#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 191299425Smm#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 192299425Smm#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ 193299425Smm (((y) << 0) & 0x000fffff))) 194299425Smm 195299425Smmstatic dev_t 196299425Smmpack_12_20(int n, unsigned long numbers[], const char **error) 197299425Smm{ 198299425Smm dev_t dev = 0; 199299425Smm 200299425Smm if (n == 2) { 201299425Smm dev = makedev_12_20(numbers[0], numbers[1]); 202299425Smm if ((unsigned long)major_12_20(dev) != numbers[0]) 203299425Smm *error = iMajorError; 204299425Smm if ((unsigned long)minor_12_20(dev) != numbers[1]) 205299425Smm *error = iMinorError; 206299425Smm } else 207299425Smm *error = tooManyFields; 208299425Smm return (dev); 209299425Smm} 210299425Smm 211299425Smm 212299425Smm#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 213299425Smm#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 214299425Smm#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ 215299425Smm (((y) << 0) & 0x0003ffff))) 216299425Smm 217299425Smmstatic dev_t 218299425Smmpack_14_18(int n, unsigned long numbers[], const char **error) 219299425Smm{ 220299425Smm dev_t dev = 0; 221299425Smm 222299425Smm if (n == 2) { 223299425Smm dev = makedev_14_18(numbers[0], numbers[1]); 224299425Smm if ((unsigned long)major_14_18(dev) != numbers[0]) 225299425Smm *error = iMajorError; 226299425Smm if ((unsigned long)minor_14_18(dev) != numbers[1]) 227299425Smm *error = iMinorError; 228299425Smm } else 229299425Smm *error = tooManyFields; 230299425Smm return (dev); 231299425Smm} 232299425Smm 233299425Smm 234299425Smm#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 235299425Smm#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 236299425Smm#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ 237299425Smm (((y) << 0) & 0x00ffffff))) 238299425Smm 239299425Smmstatic dev_t 240299425Smmpack_8_24(int n, unsigned long numbers[], const char **error) 241299425Smm{ 242299425Smm dev_t dev = 0; 243299425Smm 244299425Smm if (n == 2) { 245299425Smm dev = makedev_8_24(numbers[0], numbers[1]); 246299425Smm if ((unsigned long)major_8_24(dev) != numbers[0]) 247299425Smm *error = iMajorError; 248299425Smm if ((unsigned long)minor_8_24(dev) != numbers[1]) 249299425Smm *error = iMinorError; 250299425Smm } else 251299425Smm *error = tooManyFields; 252299425Smm return (dev); 253299425Smm} 254299425Smm 255299425Smm 256299425Smm#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 257299425Smm#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 258299425Smm#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 259299425Smm#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ 260299425Smm (((y) << 8) & 0x000fff00) | \ 261299425Smm (((z) << 0) & 0x000000ff))) 262299425Smm 263299425Smmstatic dev_t 264299425Smmpack_bsdos(int n, unsigned long numbers[], const char **error) 265299425Smm{ 266299425Smm dev_t dev = 0; 267299425Smm 268299425Smm if (n == 2) { 269299425Smm dev = makedev_12_20(numbers[0], numbers[1]); 270299425Smm if ((unsigned long)major_12_20(dev) != numbers[0]) 271299425Smm *error = iMajorError; 272299425Smm if ((unsigned long)minor_12_20(dev) != numbers[1]) 273299425Smm *error = iMinorError; 274299425Smm } else if (n == 3) { 275299425Smm dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 276299425Smm if ((unsigned long)major_12_12_8(dev) != numbers[0]) 277299425Smm *error = iMajorError; 278299425Smm if ((unsigned long)unit_12_12_8(dev) != numbers[1]) 279299425Smm *error = "invalid unit number"; 280299425Smm if ((unsigned long)subunit_12_12_8(dev) != numbers[2]) 281299425Smm *error = "invalid subunit number"; 282299425Smm } else 283299425Smm *error = tooManyFields; 284299425Smm return (dev); 285299425Smm} 286299425Smm 287299425Smm 288299425Smm /* list of formats and pack functions */ 289299425Smm /* this list must be sorted lexically */ 290316337Smmstatic const struct format { 291299425Smm const char *name; 292299425Smm pack_t *pack; 293299425Smm} formats[] = { 294299425Smm {"386bsd", pack_8_8}, 295299425Smm {"4bsd", pack_8_8}, 296299425Smm {"bsdos", pack_bsdos}, 297299425Smm {"freebsd", pack_freebsd}, 298299425Smm {"hpux", pack_8_24}, 299299425Smm {"isc", pack_8_8}, 300299425Smm {"linux", pack_8_8}, 301299425Smm {"native", pack_native}, 302299425Smm {"netbsd", pack_netbsd}, 303299425Smm {"osf1", pack_12_20}, 304299425Smm {"sco", pack_8_8}, 305299425Smm {"solaris", pack_14_18}, 306299425Smm {"sunos", pack_8_8}, 307299425Smm {"svr3", pack_8_8}, 308299425Smm {"svr4", pack_14_18}, 309299425Smm {"ultrix", pack_8_8}, 310299425Smm}; 311299425Smm 312299425Smmstatic int 313299425Smmcompare_format(const void *key, const void *element) 314299425Smm{ 315299425Smm const char *name; 316299425Smm const struct format *format; 317299425Smm 318299425Smm name = key; 319299425Smm format = element; 320299425Smm 321299425Smm return (strcmp(name, format->name)); 322299425Smm} 323299425Smm 324299425Smm 325299425Smmpack_t * 326299425Smmpack_find(const char *name) 327299425Smm{ 328299425Smm struct format *format; 329299425Smm 330299425Smm format = bsearch(name, formats, 331299425Smm sizeof(formats)/sizeof(formats[0]), 332299425Smm sizeof(formats[0]), compare_format); 333299425Smm if (format == 0) 334299425Smm return (NULL); 335299425Smm return (format->pack); 336299425Smm} 337