199193Sjmallett/* 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: releng/10.2/lib/libufs/type.c 207141 2010-04-24 07:05:35Z jeff $"); 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); 6199193Sjmallett if (disk->d_inoblock != NULL) { 6299193Sjmallett free(disk->d_inoblock); 6399193Sjmallett disk->d_inoblock = NULL; 6499193Sjmallett } 65109506Sjmallett if (disk->d_mine & MINE_NAME) { 66109506Sjmallett free((char *)(uintptr_t)disk->d_name); 67109506Sjmallett disk->d_name = NULL; 68109506Sjmallett } 69207141Sjeff if (disk->d_sbcsum != NULL) { 70207141Sjeff free(disk->d_sbcsum); 71207141Sjeff disk->d_sbcsum = NULL; 72207141Sjeff } 73116084Sjmallett return (0); 7499193Sjmallett} 7599193Sjmallett 7699193Sjmallettint 7799193Sjmallettufs_disk_fillout(struct uufsd *disk, const char *name) 7899193Sjmallett{ 79109755Sjmallett if (ufs_disk_fillout_blank(disk, name) == -1) { 80116084Sjmallett return (-1); 81109755Sjmallett } 82109755Sjmallett if (sbread(disk) == -1) { 83109755Sjmallett ERROR(disk, "could not read superblock to fill out disk"); 84116084Sjmallett return (-1); 85109755Sjmallett } 86116084Sjmallett return (0); 87109755Sjmallett} 88109755Sjmallett 89109755Sjmallettint 90109755Sjmallettufs_disk_fillout_blank(struct uufsd *disk, const char *name) 91109755Sjmallett{ 92109506Sjmallett struct stat st; 93109506Sjmallett struct fstab *fs; 94167625Spjd struct statfs sfs; 95109506Sjmallett const char *oname; 96109506Sjmallett char dev[MAXPATHLEN]; 97167625Spjd int fd, ret; 9899193Sjmallett 99109462Sjmallett ERROR(disk, NULL); 10099222Sjmallett 101109506Sjmallett oname = name; 102167625Spjdagain: if ((ret = stat(name, &st)) < 0) { 103109506Sjmallett if (*name != '/') { 104109506Sjmallett snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name); 105109506Sjmallett name = dev; 106109506Sjmallett goto again; 107109506Sjmallett } 108167625Spjd /* 109167625Spjd * The given object doesn't exist, but don't panic just yet - 110167625Spjd * it may be still mount point listed in /etc/fstab, but without 111167625Spjd * existing corresponding directory. 112167625Spjd */ 113167625Spjd name = oname; 114167625Spjd } 115194030Sjmallett if (ret >= 0 && S_ISREG(st.st_mode)) { 116194030Sjmallett /* Possibly a disk image, give it a try. */ 117194030Sjmallett ; 118194030Sjmallett } else if (ret >= 0 && S_ISCHR(st.st_mode)) { 119167625Spjd /* This is what we need, do nothing. */ 120167625Spjd ; 121167625Spjd } else if ((fs = getfsfile(name)) != NULL) { 122167625Spjd /* 123167625Spjd * The given mount point is listed in /etc/fstab. 124167625Spjd * It is possible that someone unmounted file system by hand 125167625Spjd * and different file system is mounted on this mount point, 126167625Spjd * but we still prefer /etc/fstab entry, because on the other 127167625Spjd * hand, there could be /etc/fstab entry for this mount 128167625Spjd * point, but file system is not mounted yet (eg. noauto) and 129167625Spjd * statfs(2) will point us at different file system. 130167625Spjd */ 131167625Spjd name = fs->fs_spec; 132167625Spjd } else if (ret >= 0 && S_ISDIR(st.st_mode)) { 133167625Spjd /* 134167625Spjd * The mount point is not listed in /etc/fstab, so it may be 135167625Spjd * file system mounted by hand. 136167625Spjd */ 137167625Spjd if (statfs(name, &sfs) < 0) { 138167625Spjd ERROR(disk, "could not find special device"); 139167625Spjd return (-1); 140167625Spjd } 141167625Spjd strlcpy(dev, sfs.f_mntfromname, sizeof(dev)); 142167625Spjd name = dev; 143167625Spjd } else { 144109506Sjmallett ERROR(disk, "could not find special device"); 145116084Sjmallett return (-1); 146109506Sjmallett } 14799193Sjmallett fd = open(name, O_RDONLY); 14899193Sjmallett if (fd == -1) { 149109506Sjmallett ERROR(disk, "could not open special device"); 150116084Sjmallett return (-1); 15199193Sjmallett } 15299193Sjmallett 15399193Sjmallett disk->d_bsize = 1; 154109509Sjmallett disk->d_ccg = 0; 15599193Sjmallett disk->d_fd = fd; 15699193Sjmallett disk->d_inoblock = NULL; 15799823Sjmallett disk->d_inomin = 0; 15899823Sjmallett disk->d_inomax = 0; 159109518Sjmallett disk->d_lcg = 0; 160109506Sjmallett disk->d_mine = 0; 161101687Sjmallett disk->d_ufs = 0; 162105737Sjmallett disk->d_error = NULL; 163207141Sjeff disk->d_sbcsum = NULL; 16499193Sjmallett 165109506Sjmallett if (oname != name) { 166109506Sjmallett name = strdup(name); 167109506Sjmallett if (name == NULL) { 168109506Sjmallett ERROR(disk, "could not allocate memory for disk name"); 169116084Sjmallett return (-1); 170109506Sjmallett } 171109506Sjmallett disk->d_mine |= MINE_NAME; 172109506Sjmallett } 173109506Sjmallett disk->d_name = name; 174109506Sjmallett 175116084Sjmallett return (0); 17699193Sjmallett} 177110066Sjmallett 178110066Sjmallettint 179110066Sjmallettufs_disk_write(struct uufsd *disk) 180110066Sjmallett{ 181110066Sjmallett ERROR(disk, NULL); 182110066Sjmallett 183110066Sjmallett if (disk->d_mine & MINE_WRITE) 184116084Sjmallett return (0); 185110066Sjmallett 186112730Sjmallett close(disk->d_fd); 187110066Sjmallett 188110066Sjmallett disk->d_fd = open(disk->d_name, O_RDWR); 189110066Sjmallett if (disk->d_fd < 0) { 190110066Sjmallett ERROR(disk, "failed to open disk for writing"); 191116084Sjmallett return (-1); 192110066Sjmallett } 193110066Sjmallett 194110066Sjmallett disk->d_mine |= MINE_WRITE; 195110066Sjmallett 196116084Sjmallett return (0); 197110066Sjmallett} 198