archive_pack_dev.c revision 302001
1212793Sdim/* $NetBSD: pack_dev.c,v 1.12 2013/06/14 16:28:20 tsutsui Exp $ */ 2212793Sdim 3212793Sdim/*- 4212793Sdim * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5212793Sdim * All rights reserved. 6212793Sdim * 7212793Sdim * This code is derived from software contributed to The NetBSD Foundation 8212793Sdim * by Charles M. Hannum. 9212793Sdim * 10212793Sdim * Redistribution and use in source and binary forms, with or without 11212793Sdim * modification, are permitted provided that the following conditions 12212793Sdim * are met: 13249423Sdim * 1. Redistributions of source code must retain the above copyright 14263508Sdim * notice, this list of conditions and the following disclaimer. 15218893Sdim * 2. Redistributions in binary form must reproduce the above copyright 16218893Sdim * notice, this list of conditions and the following disclaimer in the 17249423Sdim * documentation and/or other materials provided with the distribution. 18212793Sdim * 19212793Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20212793Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21212793Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22212793Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23212793Sdim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24212793Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25263508Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26212793Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27212793Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28212793Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29212793Sdim * POSSIBILITY OF SUCH DAMAGE. 30212793Sdim */ 31212793Sdim 32263508Sdim/* Originally from NetBSD's mknod(8) source. */ 33212793Sdim 34212793Sdim#include "archive_platform.h" 35212793Sdim 36263508Sdim#if HAVE_SYS_CDEFS_H 37263508Sdim#include <sys/cdefs.h> 38263508Sdim#endif 39212793Sdim#if !defined(lint) 40212793Sdim__RCSID("$NetBSD$"); 41263508Sdim#endif /* not lint */ 42263508Sdim 43212793Sdim#ifdef HAVE_LIMITS_H 44212793Sdim#include <limits.h> 45263508Sdim#endif 46263508Sdim 47263508Sdim#include <stdio.h> 48263508Sdim#ifdef HAVE_STDLIB_H 49212793Sdim#include <stdlib.h> 50212793Sdim#endif 51212793Sdim#ifdef HAVE_STRING_H 52263508Sdim#include <string.h> 53212793Sdim#endif 54212793Sdim#ifdef HAVE_SYS_TYPES_H 55212793Sdim#include <sys/types.h> 56212793Sdim#endif 57212793Sdim#ifdef HAVE_SYS_STAT_H 58212793Sdim#include <sys/stat.h> 59212793Sdim#endif 60212793Sdim#ifdef HAVE_UNISTD_H 61212793Sdim#include <unistd.h> 62212793Sdim#endif 63212793Sdim 64212793Sdim#include "archive_pack_dev.h" 65212793Sdim 66263508Sdimstatic pack_t pack_netbsd; 67212793Sdimstatic pack_t pack_freebsd; 68212793Sdimstatic pack_t pack_8_8; 69263508Sdimstatic pack_t pack_12_20; 70221345Sdimstatic pack_t pack_14_18; 71221345Sdimstatic pack_t pack_8_24; 72221345Sdimstatic pack_t pack_bsdos; 73221345Sdimstatic int compare_format(const void *, const void *); 74212793Sdim 75221345Sdimstatic const char iMajorError[] = "invalid major number"; 76221345Sdimstatic const char iMinorError[] = "invalid minor number"; 77263508Sdimstatic const char tooManyFields[] = "too many fields for format"; 78221345Sdim 79221345Sdim/* This is blatantly stolen from libarchive/archive_entry.c, 80221345Sdim * in an attempt to get this to play nice on MinGW... */ 81221345Sdim#if !defined(HAVE_MAJOR) && !defined(major) 82221345Sdim/* Replacement for major/minor/makedev. */ 83221345Sdim#define major(x) ((int)(0x00ff & ((x) >> 8))) 84221345Sdim#define minor(x) ((int)(0xffff00ff & (x))) 85263508Sdim#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) 86221345Sdim#endif 87212793Sdim 88212793Sdim/* Play games to come up with a suitable makedev() definition. */ 89212793Sdim#ifdef __QNXNTO__ 90212793Sdim/* QNX. <sigh> */ 91221345Sdim#include <sys/netmgr.h> 92263508Sdim#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) 93221345Sdim#elif defined makedev 94221345Sdim/* There's a "makedev" macro. */ 95212793Sdim#define apd_makedev(maj, min) makedev((maj), (min)) 96221345Sdim#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) 97221345Sdim/* Windows. <sigh> */ 98221345Sdim#define apd_makedev(maj, min) mkdev((maj), (min)) 99263508Sdim#else 100212793Sdim/* There's a "makedev" function. */ 101212793Sdim#define apd_makedev(maj, min) makedev((maj), (min)) 102212793Sdim#endif 103212793Sdim 104212793Sdim/* exported */ 105212793Sdimdev_t 106221345Sdimpack_native(int n, unsigned long numbers[], const char **error) 107221345Sdim{ 108221345Sdim dev_t dev = 0; 109221345Sdim 110221345Sdim if (n == 2) { 111221345Sdim dev = apd_makedev(numbers[0], numbers[1]); 112221345Sdim if ((unsigned long)major(dev) != numbers[0]) 113221345Sdim *error = iMajorError; 114221345Sdim else if ((unsigned long)minor(dev) != numbers[1]) 115221345Sdim *error = iMinorError; 116221345Sdim } else 117221345Sdim *error = tooManyFields; 118221345Sdim return (dev); 119221345Sdim} 120221345Sdim 121221345Sdim 122221345Sdimstatic dev_t 123221345Sdimpack_netbsd(int n, unsigned long numbers[], const char **error) 124221345Sdim{ 125221345Sdim dev_t dev = 0; 126221345Sdim 127221345Sdim if (n == 2) { 128221345Sdim dev = makedev_netbsd(numbers[0], numbers[1]); 129221345Sdim if ((unsigned long)major_netbsd(dev) != numbers[0]) 130221345Sdim *error = iMajorError; 131221345Sdim else if ((unsigned long)minor_netbsd(dev) != numbers[1]) 132221345Sdim *error = iMinorError; 133212793Sdim } else 134212793Sdim *error = tooManyFields; 135226633Sdim return (dev); 136212793Sdim} 137226633Sdim 138226633Sdim 139226633Sdim#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 140226633Sdim#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 141226633Sdim#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 142226633Sdim (((y) << 0) & 0xffff00ff))) 143226633Sdim 144226633Sdimstatic dev_t 145226633Sdimpack_freebsd(int n, unsigned long numbers[], const char **error) 146226633Sdim{ 147226633Sdim dev_t dev = 0; 148226633Sdim 149226633Sdim if (n == 2) { 150226633Sdim dev = makedev_freebsd(numbers[0], numbers[1]); 151226633Sdim if ((unsigned long)major_freebsd(dev) != numbers[0]) 152226633Sdim *error = iMajorError; 153226633Sdim if ((unsigned long)minor_freebsd(dev) != numbers[1]) 154226633Sdim *error = iMinorError; 155226633Sdim } else 156226633Sdim *error = tooManyFields; 157226633Sdim return (dev); 158263508Sdim} 159226633Sdim 160226633Sdim 161226633Sdim#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 162226633Sdim#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 163226633Sdim#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 164226633Sdim (((y) << 0) & 0x000000ff))) 165226633Sdim 166226633Sdimstatic dev_t 167226633Sdimpack_8_8(int n, unsigned long numbers[], const char **error) 168226633Sdim{ 169226633Sdim dev_t dev = 0; 170226633Sdim 171226633Sdim if (n == 2) { 172226633Sdim dev = makedev_8_8(numbers[0], numbers[1]); 173226633Sdim if ((unsigned long)major_8_8(dev) != numbers[0]) 174226633Sdim *error = iMajorError; 175226633Sdim if ((unsigned long)minor_8_8(dev) != numbers[1]) 176226633Sdim *error = iMinorError; 177226633Sdim } else 178226633Sdim *error = tooManyFields; 179226633Sdim return (dev); 180226633Sdim} 181226633Sdim 182226633Sdim 183226633Sdim#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 184226633Sdim#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 185212793Sdim#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ 186263508Sdim (((y) << 0) & 0x000fffff))) 187212793Sdim 188212793Sdimstatic dev_t 189212793Sdimpack_12_20(int n, unsigned long numbers[], const char **error) 190212793Sdim{ 191212793Sdim dev_t dev = 0; 192226633Sdim 193226633Sdim if (n == 2) { 194226633Sdim dev = makedev_12_20(numbers[0], numbers[1]); 195226633Sdim if ((unsigned long)major_12_20(dev) != numbers[0]) 196226633Sdim *error = iMajorError; 197226633Sdim if ((unsigned long)minor_12_20(dev) != numbers[1]) 198226633Sdim *error = iMinorError; 199212793Sdim } else 200212793Sdim *error = tooManyFields; 201212793Sdim return (dev); 202263508Sdim} 203212793Sdim 204212793Sdim 205212793Sdim#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 206212793Sdim#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 207212793Sdim#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ 208226633Sdim (((y) << 0) & 0x0003ffff))) 209226633Sdim 210226633Sdimstatic dev_t 211226633Sdimpack_14_18(int n, unsigned long numbers[], const char **error) 212226633Sdim{ 213226633Sdim dev_t dev = 0; 214226633Sdim 215226633Sdim if (n == 2) { 216226633Sdim dev = makedev_14_18(numbers[0], numbers[1]); 217212793Sdim if ((unsigned long)major_14_18(dev) != numbers[0]) 218212793Sdim *error = iMajorError; 219212793Sdim if ((unsigned long)minor_14_18(dev) != numbers[1]) 220212793Sdim *error = iMinorError; 221212793Sdim } else 222212793Sdim *error = tooManyFields; 223212793Sdim return (dev); 224212793Sdim} 225212793Sdim 226212793Sdim 227212793Sdim#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 228212793Sdim#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 229212793Sdim#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ 230212793Sdim (((y) << 0) & 0x00ffffff))) 231212793Sdim 232212793Sdimstatic dev_t 233212793Sdimpack_8_24(int n, unsigned long numbers[], const char **error) 234239462Sdim{ 235212793Sdim dev_t dev = 0; 236212793Sdim 237212793Sdim if (n == 2) { 238212793Sdim dev = makedev_8_24(numbers[0], numbers[1]); 239212793Sdim if ((unsigned long)major_8_24(dev) != numbers[0]) 240263508Sdim *error = iMajorError; 241212793Sdim if ((unsigned long)minor_8_24(dev) != numbers[1]) 242212793Sdim *error = iMinorError; 243212793Sdim } else 244212793Sdim *error = tooManyFields; 245212793Sdim return (dev); 246212793Sdim} 247212793Sdim 248212793Sdim 249212793Sdim#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 250212793Sdim#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 251212793Sdim#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 252212793Sdim#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ 253212793Sdim (((y) << 8) & 0x000fff00) | \ 254212793Sdim (((z) << 0) & 0x000000ff))) 255218893Sdim 256218893Sdimstatic dev_t 257218893Sdimpack_bsdos(int n, unsigned long numbers[], const char **error) 258212793Sdim{ 259212793Sdim dev_t dev = 0; 260212793Sdim 261212793Sdim if (n == 2) { 262212793Sdim dev = makedev_12_20(numbers[0], numbers[1]); 263212793Sdim if ((unsigned long)major_12_20(dev) != numbers[0]) 264212793Sdim *error = iMajorError; 265212793Sdim if ((unsigned long)minor_12_20(dev) != numbers[1]) 266212793Sdim *error = iMinorError; 267212793Sdim } else if (n == 3) { 268212793Sdim dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 269212793Sdim if ((unsigned long)major_12_12_8(dev) != numbers[0]) 270212793Sdim *error = iMajorError; 271263508Sdim if ((unsigned long)unit_12_12_8(dev) != numbers[1]) 272212793Sdim *error = "invalid unit number"; 273212793Sdim if ((unsigned long)subunit_12_12_8(dev) != numbers[2]) 274212793Sdim *error = "invalid subunit number"; 275212793Sdim } else 276212793Sdim *error = tooManyFields; 277212793Sdim return (dev); 278212793Sdim} 279212793Sdim 280212793Sdim 281212793Sdim /* list of formats and pack functions */ 282212793Sdim /* this list must be sorted lexically */ 283212793Sdimstatic struct format { 284212793Sdim const char *name; 285212793Sdim pack_t *pack; 286212793Sdim} formats[] = { 287212793Sdim {"386bsd", pack_8_8}, 288212793Sdim {"4bsd", pack_8_8}, 289212793Sdim {"bsdos", pack_bsdos}, 290263508Sdim {"freebsd", pack_freebsd}, 291212793Sdim {"hpux", pack_8_24}, 292212793Sdim {"isc", pack_8_8}, 293212793Sdim {"linux", pack_8_8}, 294212793Sdim {"native", pack_native}, 295212793Sdim {"netbsd", pack_netbsd}, 296212793Sdim {"osf1", pack_12_20}, 297212793Sdim {"sco", pack_8_8}, 298212793Sdim {"solaris", pack_14_18}, 299212793Sdim {"sunos", pack_8_8}, 300212793Sdim {"svr3", pack_8_8}, 301212793Sdim {"svr4", pack_14_18}, 302212793Sdim {"ultrix", pack_8_8}, 303212793Sdim}; 304212793Sdim 305212793Sdimstatic int 306212793Sdimcompare_format(const void *key, const void *element) 307212793Sdim{ 308212793Sdim const char *name; 309212793Sdim const struct format *format; 310212793Sdim 311212793Sdim name = key; 312212793Sdim format = element; 313212793Sdim 314212793Sdim return (strcmp(name, format->name)); 315212793Sdim} 316212793Sdim 317212793Sdim 318212793Sdimpack_t * 319212793Sdimpack_find(const char *name) 320212793Sdim{ 321212793Sdim struct format *format; 322212793Sdim 323212793Sdim format = bsearch(name, formats, 324212793Sdim sizeof(formats)/sizeof(formats[0]), 325212793Sdim sizeof(formats[0]), compare_format); 326212793Sdim if (format == 0) 327212793Sdim return (NULL); 328212793Sdim return (format->pack); 329212793Sdim} 330212793Sdim