/* $Id$ */ /* Copyright (c) 2008-2014 Pierre Pronchery */ /* This file is part of DeforaOS Unix others */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include /* portability */ #if defined(MNT_RDONLY) /* FreeBSD, NetBSD */ # include # ifndef MOUNT_CD9660 # define MT_ISO9660 "cd9660" # else # define MT_ISO9660 MOUNT_CD9660 # endif # ifndef MOUNT_PROCFS # define MT_PROCFS "procfs" # else # define MT_PROCFS MOUNT_PROCFS # endif # ifndef MNT_NODEV # define MF_NODEV NODEV # else # define MF_NODEV MNT_NODEV # endif # define MF_NOEXEC MNT_NOEXEC # define MF_NOSUID MNT_NOSUID # define MF_RDONLY MNT_RDONLY # if defined(__APPLE__) || defined(__FreeBSD__) || (defined(__NetBSD__) \ && (!defined(__NetBSD_Version__) \ || __NetBSD_Version__ < 499000000)) /* XXX check */ # define mount(type, dir, flags, data, data_len) \ mount(type, dir, flags, data) # endif #elif !defined(MT_ISO9660) # define MF_ASYNC MS_ASYNC # define MF_NODEV MS_NODEV # define MF_NOEXEC MS_NOEXEC # define MF_NOSUID MS_NOSUID # define MF_RDONLY MS_RDONLY # define MT_ISO9660 "iso9660" # define MT_PROCFS "proc" struct iso_args { char const * fspec; }; # define mount(type, dir, flags, data, data_len) \ mount(data ? ((struct iso_args *)data)->fspec : NULL, dir, type, \ flags, NULL) # define unmount(dir, flags) umount(dir) #endif /* constants */ #define PACKAGE "linuxrc" #define CDROM_PATH "/mnt/cdrom" #define DEV_CDROMX "/dev/cdroms/cdromX" #define INIT_PATH CDROM_PATH "/sbin/init" #define PROC_REAL_ROOT_DEV "/proc/sys/kernel/real-root-dev" /* linuxrc_error */ static int _linuxrc_error(char const * message, int ret) { fputs(PACKAGE ": ", stderr); perror(message); return ret; } /* linuxrc_mount_cdrom */ static int _linuxrc_mount_cdrom(char * source, char const * dir) { struct iso_args ia; memset(&ia, 0, sizeof(ia)); ia.fspec = source; #ifdef DEBUG fprintf(stderr, "DEBUG: mount -t %s %s %s\n", MT_ISO9660, ((struct iso_args *)&ia)->fspec, dir); #endif return mount(MT_ISO9660, dir, MF_NOSUID | MF_NODEV | MF_RDONLY, &ia, sizeof(ia)); } /* main */ int main(void) { size_t i; char dev_cdrom[] = DEV_CDROMX; const char dev_root[] = "0x100\n"; struct stat st; int found = 0; FILE * fp; /* mount /proc */ if(mount(MT_PROCFS, "/proc", MF_NOEXEC | MF_NOSUID | MF_NODEV, NULL, 0) != 0) _linuxrc_error("/proc", 0); /* look for the installation CD-ROM */ for(i = 0; i < 4; i++) { dev_cdrom[sizeof(dev_cdrom) - 2] = i + '0'; if(_linuxrc_mount_cdrom(dev_cdrom, CDROM_PATH) != 0) { _linuxrc_error(dev_cdrom, 0); continue; } if(stat(INIT_PATH, &st) != 0) { found = 1; break; } _linuxrc_error(INIT_PATH, 0); unmount(dev_cdrom, 0); /* FIXME check the flags */ } if(!found) { fputs(PACKAGE ": Could not find the bootable CD-ROM\n", stderr); return 2; } if((fp = fopen(PROC_REAL_ROOT_DEV, "w")) == NULL) return _linuxrc_error(PROC_REAL_ROOT_DEV, 0); if(fwrite(dev_root, sizeof(*dev_root), sizeof(dev_root) - 1, fp) != sizeof(dev_root) - 1) _linuxrc_error(PROC_REAL_ROOT_DEV, 0); if(fclose(fp) != 0) _linuxrc_error(PROC_REAL_ROOT_DEV, 0); return 0; }