2004-01-20 21:32:43 +03:00
/*
* Guillaume Cottenceau ( gc @ mandrakesoft . com )
*
* Copyright 2000 MandrakeSoft
*
* This software may be freely redistributed under the terms of the GNU
* public license .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
*/
/*
* Portions from Erik Troan ( ewt @ redhat . com )
*
* Copyright 1996 Red Hat Software
*
*/
# include <stdlib.h>
2008-11-03 21:03:30 +03:00
# include <limits.h>
2004-01-20 21:32:43 +03:00
# include <unistd.h>
# include <string.h>
# include <sys/mount.h>
# include <sys/stat.h>
# include <sys/types.h>
2008-03-13 19:12:12 +03:00
# include <sys/wait.h>
# ifndef DISABLE_NETWORK
# include <sys/socket.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# endif
2004-01-20 21:32:43 +03:00
# include "log.h"
# include "modules.h"
# include "mount.h"
2008-03-13 19:12:12 +03:00
# include "dns.h"
2004-01-20 21:32:43 +03:00
# ifndef DISABLE_MEDIAS
/* WARNING: this won't work if the argument is not /dev/ based */
int ensure_dev_exists ( char * dev )
{
int major , minor ;
int type = S_IFBLK ; /* my default type is block. don't forget to change for chars */
char * name ;
struct stat buf ;
char * ptr ;
name = & dev [ 5 ] ; /* we really need that dev be passed as /dev/something.. */
if ( ! stat ( dev , & buf ) )
return 0 ; /* if the file already exists, we assume it's correct */
if ( name [ 0 ] = = ' s ' & & name [ 1 ] = = ' d ' ) {
/* SCSI disks */
major = 8 ;
minor = ( name [ 2 ] - ' a ' ) < < 4 ;
if ( name [ 3 ] & & name [ 4 ] )
minor + = 10 + ( name [ 4 ] - ' 0 ' ) ;
else if ( name [ 3 ] )
minor + = ( name [ 3 ] - ' 0 ' ) ;
} else if ( name [ 0 ] = = ' h ' & & name [ 1 ] = = ' d ' ) {
/* IDE disks/cd's */
if ( name [ 2 ] = = ' a ' )
major = 3 , minor = 0 ;
else if ( name [ 2 ] = = ' b ' )
major = 3 , minor = 64 ;
else if ( name [ 2 ] = = ' c ' )
major = 22 , minor = 0 ;
else if ( name [ 2 ] = = ' d ' )
major = 22 , minor = 64 ;
else if ( name [ 2 ] = = ' e ' )
major = 33 , minor = 0 ;
else if ( name [ 2 ] = = ' f ' )
major = 33 , minor = 64 ;
else if ( name [ 2 ] = = ' g ' )
major = 34 , minor = 0 ;
else if ( name [ 2 ] = = ' h ' )
major = 34 , minor = 64 ;
else
return - 1 ;
if ( name [ 3 ] & & name [ 4 ] )
minor + = 10 + ( name [ 4 ] - ' 0 ' ) ;
else if ( name [ 3 ] )
minor + = ( name [ 3 ] - ' 0 ' ) ;
} else if ( name [ 0 ] = = ' s ' & & name [ 1 ] = = ' r ' ) {
/* SCSI cd's */
major = 11 ;
minor = name [ 2 ] - ' 0 ' ;
} else if ( ptr_begins_static_str ( name , " ida/ " ) | |
ptr_begins_static_str ( name , " cciss/ " ) ) {
/* Compaq Smart Array "ida/c0d0{p1}" */
ptr = strchr ( name , ' / ' ) ;
mkdir ( " /dev/ida " , 0755 ) ;
mkdir ( " /dev/cciss " , 0755 ) ;
major = ptr_begins_static_str ( name , " ida/ " ) ? 72 : 104 + charstar_to_int ( ptr + 2 ) ;
ptr = strchr ( ptr , ' d ' ) ;
minor = 16 * charstar_to_int ( ptr + 1 ) ;
ptr = strchr ( ptr , ' p ' ) ;
minor + = charstar_to_int ( ptr + 1 ) ;
} else if ( ptr_begins_static_str ( name , " rd/ " ) ) {
/* DAC960 "rd/cXdXXpX" */
mkdir ( " /dev/rd " , 0755 ) ;
major = 48 + charstar_to_int ( name + 4 ) ;
ptr = strchr ( name + 4 , ' d ' ) ;
minor = 8 * charstar_to_int ( ptr + 1 ) ;
ptr = strchr ( ptr , ' p ' ) ;
minor + = charstar_to_int ( ptr + 1 ) ;
} else {
log_message ( " I don't know how to create device %s, please post bugreport to me! " , dev ) ;
return - 1 ;
}
if ( mknod ( dev , type | 0600 , makedev ( major , minor ) ) ) {
log_perror ( dev ) ;
return - 1 ;
}
return 0 ;
}
# endif /* DISABLE_MEDIAS */
2008-03-13 19:12:12 +03:00
# ifndef DISABLE_NETWORK
static int nfsmount ( char * dev , char * location )
{
char spec [ PATH_MAX + 17 ] , * sep ;
struct sockaddr_in saddr ;
int n , pid , status ;
if ( ( sep = strchr ( dev , ' : ' ) ) ) {
* sep = ' \0 ' ;
} else {
log_message ( " nfsmount: directory to mount not in host:dir format " ) ;
return - 1 ;
}
saddr . sin_family = AF_INET ;
if ( ! inet_aton ( dev , & saddr . sin_addr ) & &
mygethostbyname ( dev , & saddr . sin_addr ) ) {
log_message ( " nfsmount: can't get address for %s " , dev ) ;
* sep = ' : ' ;
return - 1 ;
}
* sep = ' : ' ;
strcpy ( spec , inet_ntoa ( saddr . sin_addr ) ) ;
n = strlen ( spec ) ;
strncpy ( spec + n , sep , sizeof ( spec ) - n ) ;
log_message ( " nfsmount %s %s " , spec , location ) ;
if ( ! ( pid = fork ( ) ) ) {
char * argv [ ] = { " /bin/nfsmount " , spec , location , NULL } ;
close ( 0 ) ;
close ( 1 ) ;
close ( 2 ) ;
execve ( argv [ 0 ] , argv , NULL ) ;
exit ( 1 ) ;
}
waitpid ( pid , & status , 0 ) ;
return ( WIFEXITED ( status ) & & ! WEXITSTATUS ( status ) ) ? 0 : - 1 ;
}
# endif
2004-01-20 21:32:43 +03:00
/* mounts, creating the device if needed+possible */
int my_mount ( char * dev , char * location , char * fs , int force_rw )
{
unsigned long flags = MS_MGC_VAL | ( force_rw ? 0 : MS_RDONLY ) ;
char * opts = NULL ;
struct stat buf ;
int rc ;
# ifndef DISABLE_MEDIAS
if ( strcmp ( fs , " nfs " ) ) {
rc = ensure_dev_exists ( dev ) ;
if ( rc ! = 0 ) {
log_message ( " could not create required device file " ) ;
return - 1 ;
}
}
# endif
log_message ( " mounting %s on %s as type %s " , dev , location , fs ) ;
if ( stat ( location , & buf ) ) {
if ( mkdir ( location , 0755 ) ) {
log_perror ( " could not create location dir " ) ;
return - 1 ;
}
} else if ( ! S_ISDIR ( buf . st_mode ) ) {
log_message ( " not a dir %s, will unlink and mkdir " , location ) ;
if ( unlink ( location ) ) {
log_perror ( " could not unlink " ) ;
return - 1 ;
}
if ( mkdir ( location , 0755 ) ) {
log_perror ( " could not create location dir " ) ;
return - 1 ;
}
}
2008-03-13 19:12:12 +03:00
# ifndef DISABLE_NETWORK
if ( ! strcmp ( fs , " nfs " ) ) {
return nfsmount ( dev , location ) ;
}
# endif
2004-01-20 21:32:43 +03:00
# ifndef DISABLE_MEDIAS
2005-04-12 23:32:01 +04:00
if ( ! strcmp ( fs , " squashfs " ) )
2008-03-01 22:02:06 +03:00
my_insmod ( " squashfs " , NULL ) ;
2005-04-12 23:32:01 +04:00
2005-02-16 20:51:48 +03:00
if ( ! strcmp ( fs , " ext2 " ) )
2008-03-01 22:02:06 +03:00
my_insmod ( " ext2 " , NULL ) ;
2005-02-16 20:51:48 +03:00
2004-01-20 21:32:43 +03:00
if ( ! strcmp ( fs , " vfat " ) ) {
2008-03-01 22:02:06 +03:00
my_insmod ( " vfat " , NULL ) ;
2004-01-20 21:32:43 +03:00
opts = " check=relaxed " ;
}
2005-03-02 20:48:28 +03:00
if ( ! strcmp ( fs , " ntfs " ) )
2008-03-01 22:02:06 +03:00
my_insmod ( " ntfs " , NULL ) ;
2005-03-02 20:48:28 +03:00
2004-01-20 21:32:43 +03:00
if ( ! strcmp ( fs , " reiserfs " ) )
2008-03-01 22:02:06 +03:00
my_insmod ( " reiserfs " , NULL ) ;
2004-01-20 21:32:43 +03:00
if ( ! strcmp ( fs , " iso9660 " ) )
2008-03-01 22:02:06 +03:00
my_insmod ( " isofs " , NULL ) ;
2004-01-20 21:32:43 +03:00
# endif
rc = mount ( dev , location , fs , flags , opts ) ;
if ( rc ! = 0 ) {
log_perror ( " mount failed " ) ;
rmdir ( location ) ;
}
return rc ;
}