$NetBSD: patch-libexfat__nbpartutil.c,v 1.1 2022/10/06 00:51:49 perseant Exp $ Supply the partition utility code from NetBSD newfs. Only compiled if __NetBSD__ is defined. --- libexfat/nbpartutil.c 2022-09-27 10:20:12.769075968 -0700 +++ libexfat/nbpartutil.c 2022-09-27 10:09:39.285740643 -0700 @@ -0,0 +1,197 @@ +#ifdef __NetBSD__ +/* NetBSD: partutil.c,v 1.15.18.2 2021/01/09 19:30:14 martin Exp */ + +/*- + * Copyright (c) 2006 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "nbpartutil.h" + +/* + * Convert disklabel geometry info to disk_geom. + */ +static void +label2geom(struct disk_geom *geo, const struct disklabel *lp) +{ + geo->dg_secperunit = lp->d_secperunit; + geo->dg_secsize = lp->d_secsize; + geo->dg_nsectors = lp->d_nsectors; + geo->dg_ntracks = lp->d_ntracks; + geo->dg_ncylinders = lp->d_ncylinders; + geo->dg_secpercyl = lp->d_secpercyl; + geo->dg_pcylinders = lp->d_ncylinders; + geo->dg_sparespertrack = lp->d_sparespertrack; + geo->dg_sparespercyl = lp->d_sparespercyl; + geo->dg_acylinders = lp->d_acylinders; +} + +/* + * Set what we need to know about disk geometry. + */ +static void +dict2geom(struct disk_geom *geo, prop_dictionary_t dict) +{ + (void)memset(geo, 0, sizeof(struct disk_geom)); + prop_dictionary_get_int64(dict, "sectors-per-unit", + &geo->dg_secperunit); + prop_dictionary_get_uint32(dict, "sector-size", &geo->dg_secsize); + prop_dictionary_get_uint32(dict, "sectors-per-track", + &geo->dg_nsectors); + prop_dictionary_get_uint32(dict, "tracks-per-cylinder", + &geo->dg_ntracks); + prop_dictionary_get_uint32(dict, "cylinders-per-unit", + &geo->dg_ncylinders); +} + + +int +getdiskinfo(const char *s, int fd, const char *dt, struct disk_geom *geo, + struct dkwedge_info *dkw) +{ + struct disklabel lab; + struct disklabel *lp = &lab; + prop_dictionary_t disk_dict, geom_dict; + struct stat sb; + const struct partition *pp; + int ptn, error; + + if (dt) { + lp = getdiskbyname(dt); + if (lp == NULL) + errx(1, "unknown disk type `%s'", dt); + } + + /* Get disk description dictionary */ + disk_dict = NULL; + error = prop_dictionary_recv_ioctl(fd, DIOCGDISKINFO, &disk_dict); + + /* fail quickly if the device does not exist at all */ + if (error == ENXIO) + return -1; + + if (error) { + /* + * Ask for disklabel if DIOCGDISKINFO failed. This is + * compatibility call and can be removed when all devices + * will support DIOCGDISKINFO. + * cgd, ccd pseudo disk drives doesn't support DIOCGDDISKINFO + */ + if (ioctl(fd, DIOCGDINFO, lp) == -1) { + if (errno != ENXIO) + warn("DIOCGDINFO on %s failed", s); + return -1; + } + label2geom(geo, lp); + } else { + geom_dict = prop_dictionary_get(disk_dict, "geometry"); + dict2geom(geo, geom_dict); + } + if (disk_dict != NULL) + prop_object_release(disk_dict); + + if (dkw == NULL) + return 0; + + /* Get info about partition/wedge */ + if (ioctl(fd, DIOCGWEDGEINFO, dkw) != -1) { + /* DIOCGWEDGEINFO didn't fail, we're done */ + return 0; + } + + if (ioctl(fd, DIOCGDINFO, lp) == -1) { + err(1, "Please implement DIOCGWEDGEINFO or " + "DIOCGDINFO for disk device %s", s); + } + + /* DIOCGDINFO didn't fail */ + (void)memset(dkw, 0, sizeof(*dkw)); + + if (stat(s, &sb) == -1) + return 0; + + ptn = strchr(s, '\0')[-1] - 'a'; + if ((unsigned)ptn >= lp->d_npartitions || + (devminor_t)ptn != DISKPART(sb.st_rdev)) + return 0; + + pp = &lp->d_partitions[ptn]; + if (ptn != getrawpartition()) { + dkw->dkw_offset = pp->p_offset; + dkw->dkw_size = pp->p_size; + } else { + dkw->dkw_offset = 0; + dkw->dkw_size = geo->dg_secperunit; + } + dkw->dkw_parent[0] = '*'; + strlcpy(dkw->dkw_ptype, getfstypename(pp->p_fstype), + sizeof(dkw->dkw_ptype)); + + return 0; +} + +int +getdisksize(const char *name, u_int *secsize, off_t *mediasize) +{ + char buf[MAXPATHLEN]; + struct disk_geom geo; + int fd, error; + + if ((fd = opendisk(name, O_RDONLY, buf, sizeof(buf), 0)) == -1) + return -1; + + error = getdiskinfo(name, fd, NULL, &geo, NULL); + close(fd); + if (error) + return error; + + *secsize = geo.dg_secsize; + *mediasize = geo.dg_secsize * geo.dg_secperunit; + return 0; +} +#endif /* __NetBSD__ */