1209139Srpaulo/* 2209139Srpaulo * Copyright (c) 2002 Juli Mallett. All rights reserved. 3209139Srpaulo * 4209139Srpaulo * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 5252726Srpaulo * FreeBSD project. Redistribution and use in source and binary forms, with 6252726Srpaulo * or without modification, are permitted provided that the following 7209139Srpaulo * conditions are met: 8209139Srpaulo * 9209139Srpaulo * 1. Redistribution of source code must retain the above copyright notice, 10209139Srpaulo * this list of conditions and the following disclaimer. 11209139Srpaulo * 2. Redistribution in binary form must reproduce the above copyright 12209139Srpaulo * notice, this list of conditions and the following disclaimer in the 13209139Srpaulo * documentation and/or other materials provided with the distribution. 14209139Srpaulo * 15209139Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16209139Srpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17209139Srpaulo * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18209139Srpaulo * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19209139Srpaulo * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20209139Srpaulo * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21209139Srpaulo * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22209139Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23209139Srpaulo * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24209139Srpaulo * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25209139Srpaulo * POSSIBILITY OF SUCH DAMAGE. 26209139Srpaulo */ 27209139Srpaulo 28209139Srpaulo#include <sys/cdefs.h> 29209139Srpaulo__FBSDID("$FreeBSD$"); 30209139Srpaulo 31209139Srpaulo#include <sys/param.h> 32209139Srpaulo#include <sys/mount.h> 33209139Srpaulo#include <sys/disklabel.h> 34209139Srpaulo#include <sys/stat.h> 35209139Srpaulo 36209139Srpaulo#include <ufs/ufs/ufsmount.h> 37209139Srpaulo#include <ufs/ufs/dinode.h> 38209139Srpaulo#include <ufs/ffs/fs.h> 39209139Srpaulo 40209139Srpaulo#include <errno.h> 41209139Srpaulo#include <fcntl.h> 42209139Srpaulo#include <fstab.h> 43209139Srpaulo#include <paths.h> 44209139Srpaulo#include <stdio.h> 45209139Srpaulo#include <stdlib.h> 46209139Srpaulo#include <string.h> 47209139Srpaulo#include <unistd.h> 48209139Srpaulo 49209139Srpaulo#include <libufs.h> 50209139Srpaulo 51209139Srpaulo/* Internally, track the 'name' value, it's ours. */ 52209139Srpaulo#define MINE_NAME 0x01 53209139Srpaulo/* Track if its fd points to a writable device. */ 54209139Srpaulo#define MINE_WRITE 0x02 55209139Srpaulo 56209139Srpauloint 57209139Srpauloufs_disk_close(struct uufsd *disk) 58209139Srpaulo{ 59209139Srpaulo ERROR(disk, NULL); 60209139Srpaulo close(disk->d_fd); 61209139Srpaulo if (disk->d_inoblock != NULL) { 62209139Srpaulo free(disk->d_inoblock); 63209139Srpaulo disk->d_inoblock = NULL; 64209139Srpaulo } 65209139Srpaulo if (disk->d_mine & MINE_NAME) { 66209139Srpaulo free((char *)(uintptr_t)disk->d_name); 67209139Srpaulo disk->d_name = NULL; 68209139Srpaulo } 69209139Srpaulo if (disk->d_sbcsum != NULL) { 70209139Srpaulo free(disk->d_sbcsum); 71209139Srpaulo disk->d_sbcsum = NULL; 72209139Srpaulo } 73209139Srpaulo return (0); 74214734Srpaulo} 75209139Srpaulo 76209139Srpauloint 77209139Srpauloufs_disk_fillout(struct uufsd *disk, const char *name) 78209139Srpaulo{ 79209139Srpaulo if (ufs_disk_fillout_blank(disk, name) == -1) { 80209139Srpaulo return (-1); 81209139Srpaulo } 82209139Srpaulo if (sbread(disk) == -1) { 83209139Srpaulo ERROR(disk, "could not read superblock to fill out disk"); 84209139Srpaulo return (-1); 85209139Srpaulo } 86209139Srpaulo return (0); 87209139Srpaulo} 88209139Srpaulo 89209139Srpauloint 90209139Srpauloufs_disk_fillout_blank(struct uufsd *disk, const char *name) 91209139Srpaulo{ 92209139Srpaulo struct stat st; 93209139Srpaulo struct fstab *fs; 94209139Srpaulo struct statfs sfs; 95209139Srpaulo const char *oname; 96209139Srpaulo char dev[MAXPATHLEN]; 97209139Srpaulo int fd, ret; 98209139Srpaulo 99209139Srpaulo ERROR(disk, NULL); 100209139Srpaulo 101252726Srpaulo oname = name; 102252726Srpauloagain: if ((ret = stat(name, &st)) < 0) { 103209139Srpaulo if (*name != '/') { 104209139Srpaulo snprintf(dev, sizeof(dev), "%s%s", _PATH_DEV, name); 105209139Srpaulo name = dev; 106209139Srpaulo goto again; 107209139Srpaulo } 108209139Srpaulo /* 109209139Srpaulo * The given object doesn't exist, but don't panic just yet - 110209139Srpaulo * it may be still mount point listed in /etc/fstab, but without 111209139Srpaulo * existing corresponding directory. 112209139Srpaulo */ 113209139Srpaulo name = oname; 114209139Srpaulo } 115209139Srpaulo if (ret >= 0 && S_ISREG(st.st_mode)) { 116209139Srpaulo /* Possibly a disk image, give it a try. */ 117209139Srpaulo ; 118209139Srpaulo } else if (ret >= 0 && S_ISCHR(st.st_mode)) { 119209139Srpaulo /* This is what we need, do nothing. */ 120209139Srpaulo ; 121209139Srpaulo } else if ((fs = getfsfile(name)) != NULL) { 122209139Srpaulo /* 123209139Srpaulo * The given mount point is listed in /etc/fstab. 124209139Srpaulo * It is possible that someone unmounted file system by hand 125209139Srpaulo * and different file system is mounted on this mount point, 126209139Srpaulo * but we still prefer /etc/fstab entry, because on the other 127209139Srpaulo * hand, there could be /etc/fstab entry for this mount 128209139Srpaulo * point, but file system is not mounted yet (eg. noauto) and 129209139Srpaulo * statfs(2) will point us at different file system. 130209139Srpaulo */ 131252726Srpaulo name = fs->fs_spec; 132252726Srpaulo } else if (ret >= 0 && S_ISDIR(st.st_mode)) { 133209139Srpaulo /* 134209139Srpaulo * The mount point is not listed in /etc/fstab, so it may be 135209139Srpaulo * file system mounted by hand. 136209139Srpaulo */ 137209139Srpaulo if (statfs(name, &sfs) < 0) { 138209139Srpaulo ERROR(disk, "could not find special device"); 139209139Srpaulo return (-1); 140209139Srpaulo } 141209139Srpaulo strlcpy(dev, sfs.f_mntfromname, sizeof(dev)); 142209139Srpaulo name = dev; 143209139Srpaulo } else { 144209139Srpaulo ERROR(disk, "could not find special device"); 145209139Srpaulo return (-1); 146209139Srpaulo } 147209139Srpaulo fd = open(name, O_RDONLY); 148209139Srpaulo if (fd == -1) { 149209139Srpaulo ERROR(disk, "could not open special device"); 150209139Srpaulo return (-1); 151209139Srpaulo } 152209139Srpaulo 153209139Srpaulo disk->d_bsize = 1; 154209139Srpaulo disk->d_ccg = 0; 155209139Srpaulo disk->d_fd = fd; 156209139Srpaulo disk->d_inoblock = NULL; 157209139Srpaulo disk->d_inomin = 0; 158209139Srpaulo disk->d_inomax = 0; 159209139Srpaulo disk->d_lcg = 0; 160209139Srpaulo disk->d_mine = 0; 161209139Srpaulo disk->d_ufs = 0; 162209139Srpaulo disk->d_error = NULL; 163209139Srpaulo disk->d_sbcsum = NULL; 164209139Srpaulo 165209139Srpaulo if (oname != name) { 166209139Srpaulo name = strdup(name); 167209139Srpaulo if (name == NULL) { 168209139Srpaulo ERROR(disk, "could not allocate memory for disk name"); 169209139Srpaulo return (-1); 170209139Srpaulo } 171209139Srpaulo disk->d_mine |= MINE_NAME; 172209139Srpaulo } 173209139Srpaulo disk->d_name = name; 174209139Srpaulo 175209139Srpaulo return (0); 176209139Srpaulo} 177209139Srpaulo 178209139Srpauloint 179209139Srpauloufs_disk_write(struct uufsd *disk) 180209139Srpaulo{ 181209139Srpaulo ERROR(disk, NULL); 182209139Srpaulo 183209139Srpaulo if (disk->d_mine & MINE_WRITE) 184209139Srpaulo return (0); 185209139Srpaulo 186209139Srpaulo close(disk->d_fd); 187209139Srpaulo 188209139Srpaulo disk->d_fd = open(disk->d_name, O_RDWR); 189209139Srpaulo if (disk->d_fd < 0) { 190209139Srpaulo ERROR(disk, "failed to open disk for writing"); 191209139Srpaulo return (-1); 192209139Srpaulo } 193209139Srpaulo 194252726Srpaulo disk->d_mine |= MINE_WRITE; 195252726Srpaulo 196209139Srpaulo return (0); 197209139Srpaulo} 198209139Srpaulo