1331722Seadler/* 299193Sjmallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 399193Sjmallett * 499193Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 599193Sjmallett * FreeBSD project. Redistribution and use in source and binary forms, with 699193Sjmallett * or without modification, are permitted provided that the following 799193Sjmallett * conditions are met: 899193Sjmallett * 999193Sjmallett * 1. Redistribution of source code must retain the above copyright notice, 1099193Sjmallett * this list of conditions and the following disclaimer. 1199193Sjmallett * 2. Redistribution in binary form must reproduce the above copyright 1299193Sjmallett * notice, this list of conditions and the following disclaimer in the 1399193Sjmallett * documentation and/or other materials provided with the distribution. 1499193Sjmallett * 1599193Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699193Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1799193Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1899193Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1999193Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2099193Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2199193Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2299193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2399193Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2499193Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2599193Sjmallett * POSSIBILITY OF SUCH DAMAGE. 2699193Sjmallett */ 2799193Sjmallett 2899193Sjmallett#include <sys/cdefs.h> 2999193Sjmallett__FBSDID("$FreeBSD: stable/11/lib/libufs/type.c 332638 2018-04-17 00:03:32Z mckusick $"); 3099193Sjmallett 3199193Sjmallett#include <sys/param.h> 3299193Sjmallett#include <sys/mount.h> 3399193Sjmallett#include <sys/disklabel.h> 3499193Sjmallett#include <sys/stat.h> 3599193Sjmallett 3699193Sjmallett#include <ufs/ufs/ufsmount.h> 3799193Sjmallett#include <ufs/ufs/dinode.h> 3899193Sjmallett#include <ufs/ffs/fs.h> 3999193Sjmallett 4099193Sjmallett#include <errno.h> 4199193Sjmallett#include <fcntl.h> 42109506Sjmallett#include <fstab.h> 43109506Sjmallett#include <paths.h> 4499193Sjmallett#include <stdio.h> 4599193Sjmallett#include <stdlib.h> 4699193Sjmallett#include <string.h> 4799193Sjmallett#include <unistd.h> 4899193Sjmallett 4999193Sjmallett#include <libufs.h> 5099193Sjmallett 51109506Sjmallett/* Internally, track the 'name' value, it's ours. */ 52109506Sjmallett#define MINE_NAME 0x01 53110066Sjmallett/* Track if its fd points to a writable device. */ 54110066Sjmallett#define MINE_WRITE 0x02 55109506Sjmallett 5699193Sjmallettint 5799193Sjmallettufs_disk_close(struct uufsd *disk) 5899193Sjmallett{ 59109462Sjmallett ERROR(disk, NULL); 6099193Sjmallett close(disk->d_fd); 61332638Smckusick disk->d_fd = -1; 6299193Sjmallett if (disk->d_inoblock != NULL) { 6399193Sjmallett free(disk->d_inoblock); 6499193Sjmallett disk->d_inoblock = NULL; 6599193Sjmallett } 66109506Sjmallett if (disk->d_mine & MINE_NAME) { 67109506Sjmallett free((char *)(uintptr_t)disk->d_name); 68109506Sjmallett disk->d_name = NULL; 69109506Sjmallett } 70207141Sjeff if (disk->d_sbcsum != NULL) { 71207141Sjeff free(disk->d_sbcsum); 72207141Sjeff disk->d_sbcsum = NULL; 73207141Sjeff } 74116084Sjmallett return (0); 7599193Sjmallett} 7699193Sjmallett 7799193Sjmallettint 7899193Sjmallettufs_disk_fillout(struct uufsd *disk, const char *name) 7999193Sjmallett{ 80109755Sjmallett if (ufs_disk_fillout_blank(disk, name) == -1) { 81116084Sjmallett return (-1); 82109755Sjmallett } 83109755Sjmallett if (sbread(disk) == -1) { 84109755Sjmallett ERROR(disk, "could not read superblock to fill out disk"); 85116084Sjmallett return (-1); 86109755Sjmallett } 87116084Sjmallett return (0); 88109755Sjmallett} 89109755Sjmallett 90109755Sjmallettint 91109755Sjmallettufs_disk_fillout_blank(struct uufsd *disk, const char *name) 92109755Sjmallett{ 93109506Sjmallett struct stat st; 94109506Sjmallett struct fstab *fs; 95167625Spjd struct statfs sfs; 96109506Sjmallett const char *oname; 97109506Sjmallett char dev[MAXPATHLEN]; 98167625Spjd int fd, ret; 9999193Sjmallett 100109462Sjmallett ERROR(disk, NULL); 10199222Sjmallett 102109506Sjmallett oname = name; 103167625Spjdagain: if ((ret = stat(name, &st)) < 0) { 104109506Sjmallett if (*name != '/') { 105109506Sjmallett snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name); 106109506Sjmallett name = dev; 107109506Sjmallett goto again; 108109506Sjmallett } 109167625Spjd /* 110167625Spjd * The given object doesn't exist, but don't panic just yet - 111167625Spjd * it may be still mount point listed in /etc/fstab, but without 112167625Spjd * existing corresponding directory. 113167625Spjd */ 114167625Spjd name = oname; 115167625Spjd } 116194030Sjmallett if (ret >= 0 && S_ISREG(st.st_mode)) { 117194030Sjmallett /* Possibly a disk image, give it a try. */ 118194030Sjmallett ; 119194030Sjmallett } else if (ret >= 0 && S_ISCHR(st.st_mode)) { 120167625Spjd /* This is what we need, do nothing. */ 121167625Spjd ; 122167625Spjd } else if ((fs = getfsfile(name)) != NULL) { 123167625Spjd /* 124167625Spjd * The given mount point is listed in /etc/fstab. 125167625Spjd * It is possible that someone unmounted file system by hand 126167625Spjd * and different file system is mounted on this mount point, 127167625Spjd * but we still prefer /etc/fstab entry, because on the other 128167625Spjd * hand, there could be /etc/fstab entry for this mount 129167625Spjd * point, but file system is not mounted yet (eg. noauto) and 130167625Spjd * statfs(2) will point us at different file system. 131167625Spjd */ 132167625Spjd name = fs->fs_spec; 133167625Spjd } else if (ret >= 0 && S_ISDIR(st.st_mode)) { 134167625Spjd /* 135167625Spjd * The mount point is not listed in /etc/fstab, so it may be 136167625Spjd * file system mounted by hand. 137167625Spjd */ 138167625Spjd if (statfs(name, &sfs) < 0) { 139167625Spjd ERROR(disk, "could not find special device"); 140167625Spjd return (-1); 141167625Spjd } 142167625Spjd strlcpy(dev, sfs.f_mntfromname, sizeof(dev)); 143167625Spjd name = dev; 144167625Spjd } else { 145109506Sjmallett ERROR(disk, "could not find special device"); 146116084Sjmallett return (-1); 147109506Sjmallett } 14899193Sjmallett fd = open(name, O_RDONLY); 14999193Sjmallett if (fd == -1) { 150109506Sjmallett ERROR(disk, "could not open special device"); 151116084Sjmallett return (-1); 15299193Sjmallett } 15399193Sjmallett 15499193Sjmallett disk->d_bsize = 1; 155109509Sjmallett disk->d_ccg = 0; 15699193Sjmallett disk->d_fd = fd; 15799193Sjmallett disk->d_inoblock = NULL; 15899823Sjmallett disk->d_inomin = 0; 15999823Sjmallett disk->d_inomax = 0; 160109518Sjmallett disk->d_lcg = 0; 161109506Sjmallett disk->d_mine = 0; 162101687Sjmallett disk->d_ufs = 0; 163105737Sjmallett disk->d_error = NULL; 164207141Sjeff disk->d_sbcsum = NULL; 16599193Sjmallett 166109506Sjmallett if (oname != name) { 167109506Sjmallett name = strdup(name); 168109506Sjmallett if (name == NULL) { 169109506Sjmallett ERROR(disk, "could not allocate memory for disk name"); 170116084Sjmallett return (-1); 171109506Sjmallett } 172109506Sjmallett disk->d_mine |= MINE_NAME; 173109506Sjmallett } 174109506Sjmallett disk->d_name = name; 175109506Sjmallett 176116084Sjmallett return (0); 17799193Sjmallett} 178110066Sjmallett 179110066Sjmallettint 180110066Sjmallettufs_disk_write(struct uufsd *disk) 181110066Sjmallett{ 182332638Smckusick int fd; 183332638Smckusick 184110066Sjmallett ERROR(disk, NULL); 185110066Sjmallett 186110066Sjmallett if (disk->d_mine & MINE_WRITE) 187116084Sjmallett return (0); 188110066Sjmallett 189332638Smckusick fd = open(disk->d_name, O_RDWR); 190332638Smckusick if (fd < 0) { 191110066Sjmallett ERROR(disk, "failed to open disk for writing"); 192116084Sjmallett return (-1); 193110066Sjmallett } 194110066Sjmallett 195332638Smckusick close(disk->d_fd); 196332638Smckusick disk->d_fd = fd; 197110066Sjmallett disk->d_mine |= MINE_WRITE; 198110066Sjmallett 199116084Sjmallett return (0); 200110066Sjmallett} 201