archive_pack_dev.c revision 299425
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 60299425Smm#ifdef HAVE_UNISTD_H 61299425Smm#include <unistd.h> 62299425Smm#endif 63299425Smm 64299425Smm#include "archive_pack_dev.h" 65299425Smm 66299425Smmstatic pack_t pack_netbsd; 67299425Smmstatic pack_t pack_freebsd; 68299425Smmstatic pack_t pack_8_8; 69299425Smmstatic pack_t pack_12_20; 70299425Smmstatic pack_t pack_14_18; 71299425Smmstatic pack_t pack_8_24; 72299425Smmstatic pack_t pack_bsdos; 73299425Smmstatic int compare_format(const void *, const void *); 74299425Smm 75299425Smmstatic const char iMajorError[] = "invalid major number"; 76299425Smmstatic const char iMinorError[] = "invalid minor number"; 77299425Smmstatic const char tooManyFields[] = "too many fields for format"; 78299425Smm 79299425Smm/* This is blatantly stolen from libarchive/archive_entry.c, 80299425Smm * in an attempt to get this to play nice on MinGW... */ 81299425Smm#if !defined(HAVE_MAJOR) && !defined(major) 82299425Smm/* Replacement for major/minor/makedev. */ 83299425Smm#define major(x) ((int)(0x00ff & ((x) >> 8))) 84299425Smm#define minor(x) ((int)(0xffff00ff & (x))) 85299425Smm#define makedev(maj,min) ((0xff00 & ((maj)<<8)) | (0xffff00ff & (min))) 86299425Smm#endif 87299425Smm 88299425Smm/* Play games to come up with a suitable makedev() definition. */ 89299425Smm#ifdef __QNXNTO__ 90299425Smm/* QNX. <sigh> */ 91299425Smm#include <sys/netmgr.h> 92299425Smm#define apd_makedev(maj, min) makedev(ND_LOCAL_NODE, (maj), (min)) 93299425Smm#elif defined makedev 94299425Smm/* There's a "makedev" macro. */ 95299425Smm#define apd_makedev(maj, min) makedev((maj), (min)) 96299425Smm#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__)) 97299425Smm/* Windows. <sigh> */ 98299425Smm#define apd_makedev(maj, min) mkdev((maj), (min)) 99299425Smm#else 100299425Smm/* There's a "makedev" function. */ 101299425Smm#define apd_makedev(maj, min) makedev((maj), (min)) 102299425Smm#endif 103299425Smm 104299425Smm/* exported */ 105299425Smmdev_t 106299425Smmpack_native(int n, unsigned long numbers[], const char **error) 107299425Smm{ 108299425Smm dev_t dev = 0; 109299425Smm 110299425Smm if (n == 2) { 111299425Smm dev = apd_makedev(numbers[0], numbers[1]); 112299425Smm if ((unsigned long)major(dev) != numbers[0]) 113299425Smm *error = iMajorError; 114299425Smm else if ((unsigned long)minor(dev) != numbers[1]) 115299425Smm *error = iMinorError; 116299425Smm } else 117299425Smm *error = tooManyFields; 118299425Smm return (dev); 119299425Smm} 120299425Smm 121299425Smm 122299425Smmstatic dev_t 123299425Smmpack_netbsd(int n, unsigned long numbers[], const char **error) 124299425Smm{ 125299425Smm dev_t dev = 0; 126299425Smm 127299425Smm if (n == 2) { 128299425Smm dev = makedev_netbsd(numbers[0], numbers[1]); 129299425Smm if ((unsigned long)major_netbsd(dev) != numbers[0]) 130299425Smm *error = iMajorError; 131299425Smm else if ((unsigned long)minor_netbsd(dev) != numbers[1]) 132299425Smm *error = iMinorError; 133299425Smm } else 134299425Smm *error = tooManyFields; 135299425Smm return (dev); 136299425Smm} 137299425Smm 138299425Smm 139299425Smm#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 140299425Smm#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) 141299425Smm#define makedev_freebsd(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 142299425Smm (((y) << 0) & 0xffff00ff))) 143299425Smm 144299425Smmstatic dev_t 145299425Smmpack_freebsd(int n, unsigned long numbers[], const char **error) 146299425Smm{ 147299425Smm dev_t dev = 0; 148299425Smm 149299425Smm if (n == 2) { 150299425Smm dev = makedev_freebsd(numbers[0], numbers[1]); 151299425Smm if ((unsigned long)major_freebsd(dev) != numbers[0]) 152299425Smm *error = iMajorError; 153299425Smm if ((unsigned long)minor_freebsd(dev) != numbers[1]) 154299425Smm *error = iMinorError; 155299425Smm } else 156299425Smm *error = tooManyFields; 157299425Smm return (dev); 158299425Smm} 159299425Smm 160299425Smm 161299425Smm#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) 162299425Smm#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 163299425Smm#define makedev_8_8(x,y) ((dev_t)((((x) << 8) & 0x0000ff00) | \ 164299425Smm (((y) << 0) & 0x000000ff))) 165299425Smm 166299425Smmstatic dev_t 167299425Smmpack_8_8(int n, unsigned long numbers[], const char **error) 168299425Smm{ 169299425Smm dev_t dev = 0; 170299425Smm 171299425Smm if (n == 2) { 172299425Smm dev = makedev_8_8(numbers[0], numbers[1]); 173299425Smm if ((unsigned long)major_8_8(dev) != numbers[0]) 174299425Smm *error = iMajorError; 175299425Smm if ((unsigned long)minor_8_8(dev) != numbers[1]) 176299425Smm *error = iMinorError; 177299425Smm } else 178299425Smm *error = tooManyFields; 179299425Smm return (dev); 180299425Smm} 181299425Smm 182299425Smm 183299425Smm#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 184299425Smm#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) 185299425Smm#define makedev_12_20(x,y) ((dev_t)((((x) << 20) & 0xfff00000) | \ 186299425Smm (((y) << 0) & 0x000fffff))) 187299425Smm 188299425Smmstatic dev_t 189299425Smmpack_12_20(int n, unsigned long numbers[], const char **error) 190299425Smm{ 191299425Smm dev_t dev = 0; 192299425Smm 193299425Smm if (n == 2) { 194299425Smm dev = makedev_12_20(numbers[0], numbers[1]); 195299425Smm if ((unsigned long)major_12_20(dev) != numbers[0]) 196299425Smm *error = iMajorError; 197299425Smm if ((unsigned long)minor_12_20(dev) != numbers[1]) 198299425Smm *error = iMinorError; 199299425Smm } else 200299425Smm *error = tooManyFields; 201299425Smm return (dev); 202299425Smm} 203299425Smm 204299425Smm 205299425Smm#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) 206299425Smm#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) 207299425Smm#define makedev_14_18(x,y) ((dev_t)((((x) << 18) & 0xfffc0000) | \ 208299425Smm (((y) << 0) & 0x0003ffff))) 209299425Smm 210299425Smmstatic dev_t 211299425Smmpack_14_18(int n, unsigned long numbers[], const char **error) 212299425Smm{ 213299425Smm dev_t dev = 0; 214299425Smm 215299425Smm if (n == 2) { 216299425Smm dev = makedev_14_18(numbers[0], numbers[1]); 217299425Smm if ((unsigned long)major_14_18(dev) != numbers[0]) 218299425Smm *error = iMajorError; 219299425Smm if ((unsigned long)minor_14_18(dev) != numbers[1]) 220299425Smm *error = iMinorError; 221299425Smm } else 222299425Smm *error = tooManyFields; 223299425Smm return (dev); 224299425Smm} 225299425Smm 226299425Smm 227299425Smm#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) 228299425Smm#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) 229299425Smm#define makedev_8_24(x,y) ((dev_t)((((x) << 24) & 0xff000000) | \ 230299425Smm (((y) << 0) & 0x00ffffff))) 231299425Smm 232299425Smmstatic dev_t 233299425Smmpack_8_24(int n, unsigned long numbers[], const char **error) 234299425Smm{ 235299425Smm dev_t dev = 0; 236299425Smm 237299425Smm if (n == 2) { 238299425Smm dev = makedev_8_24(numbers[0], numbers[1]); 239299425Smm if ((unsigned long)major_8_24(dev) != numbers[0]) 240299425Smm *error = iMajorError; 241299425Smm if ((unsigned long)minor_8_24(dev) != numbers[1]) 242299425Smm *error = iMinorError; 243299425Smm } else 244299425Smm *error = tooManyFields; 245299425Smm return (dev); 246299425Smm} 247299425Smm 248299425Smm 249299425Smm#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) 250299425Smm#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) 251299425Smm#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) 252299425Smm#define makedev_12_12_8(x,y,z) ((dev_t)((((x) << 20) & 0xfff00000) | \ 253299425Smm (((y) << 8) & 0x000fff00) | \ 254299425Smm (((z) << 0) & 0x000000ff))) 255299425Smm 256299425Smmstatic dev_t 257299425Smmpack_bsdos(int n, unsigned long numbers[], const char **error) 258299425Smm{ 259299425Smm dev_t dev = 0; 260299425Smm 261299425Smm if (n == 2) { 262299425Smm dev = makedev_12_20(numbers[0], numbers[1]); 263299425Smm if ((unsigned long)major_12_20(dev) != numbers[0]) 264299425Smm *error = iMajorError; 265299425Smm if ((unsigned long)minor_12_20(dev) != numbers[1]) 266299425Smm *error = iMinorError; 267299425Smm } else if (n == 3) { 268299425Smm dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); 269299425Smm if ((unsigned long)major_12_12_8(dev) != numbers[0]) 270299425Smm *error = iMajorError; 271299425Smm if ((unsigned long)unit_12_12_8(dev) != numbers[1]) 272299425Smm *error = "invalid unit number"; 273299425Smm if ((unsigned long)subunit_12_12_8(dev) != numbers[2]) 274299425Smm *error = "invalid subunit number"; 275299425Smm } else 276299425Smm *error = tooManyFields; 277299425Smm return (dev); 278299425Smm} 279299425Smm 280299425Smm 281299425Smm /* list of formats and pack functions */ 282299425Smm /* this list must be sorted lexically */ 283299425Smmstatic struct format { 284299425Smm const char *name; 285299425Smm pack_t *pack; 286299425Smm} formats[] = { 287299425Smm {"386bsd", pack_8_8}, 288299425Smm {"4bsd", pack_8_8}, 289299425Smm {"bsdos", pack_bsdos}, 290299425Smm {"freebsd", pack_freebsd}, 291299425Smm {"hpux", pack_8_24}, 292299425Smm {"isc", pack_8_8}, 293299425Smm {"linux", pack_8_8}, 294299425Smm {"native", pack_native}, 295299425Smm {"netbsd", pack_netbsd}, 296299425Smm {"osf1", pack_12_20}, 297299425Smm {"sco", pack_8_8}, 298299425Smm {"solaris", pack_14_18}, 299299425Smm {"sunos", pack_8_8}, 300299425Smm {"svr3", pack_8_8}, 301299425Smm {"svr4", pack_14_18}, 302299425Smm {"ultrix", pack_8_8}, 303299425Smm}; 304299425Smm 305299425Smmstatic int 306299425Smmcompare_format(const void *key, const void *element) 307299425Smm{ 308299425Smm const char *name; 309299425Smm const struct format *format; 310299425Smm 311299425Smm name = key; 312299425Smm format = element; 313299425Smm 314299425Smm return (strcmp(name, format->name)); 315299425Smm} 316299425Smm 317299425Smm 318299425Smmpack_t * 319299425Smmpack_find(const char *name) 320299425Smm{ 321299425Smm struct format *format; 322299425Smm 323299425Smm format = bsearch(name, formats, 324299425Smm sizeof(formats)/sizeof(formats[0]), 325299425Smm sizeof(formats[0]), compare_format); 326299425Smm if (format == 0) 327299425Smm return (NULL); 328299425Smm return (format->pack); 329299425Smm} 330