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 .
*
*/
/* This code comes from util-linux-2.10n (mount/lomount.c)
* ( this is a simplified version of this code )
*/
# include <sys/types.h>
# include <sys/mount.h>
# include <sys/ioctl.h>
# include <sys/mount.h>
# include <errno.h>
# include <fcntl.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include "stage1.h"
# include "frontend.h"
# include "log.h"
# include "mount.h"
# include "modules.h"
2021-08-11 20:15:40 +03:00
# include "udev.h"
2004-01-20 21:32:43 +03:00
# include "lomount.h"
# define LO_NAME_SIZE 64
# define LO_KEY_SIZE 32
struct loop_info
{
int lo_number ; /* ioctl r/o */
dev_t lo_device ; /* ioctl r/o */
unsigned long lo_inode ; /* ioctl r/o */
dev_t lo_rdevice ; /* ioctl r/o */
int lo_offset ;
int lo_encrypt_type ;
int lo_encrypt_key_size ; /* ioctl w/o */
int lo_flags ; /* ioctl r/o */
char lo_name [ LO_NAME_SIZE ] ;
unsigned char lo_encrypt_key [ LO_KEY_SIZE ] ; /* ioctl w/o */
unsigned long lo_init [ 2 ] ;
char reserved [ 4 ] ;
} ;
# define LOOP_SET_FD 0x4C00
# define LOOP_CLR_FD 0x4C01
# define LOOP_SET_STATUS 0x4C02
# define LOOP_GET_STATUS 0x4C03
int
set_loop ( const char * device , const char * file )
{
struct loop_info loopinfo ;
2008-03-01 22:02:06 +03:00
int i , fd , ffd , mode ;
2004-01-20 21:32:43 +03:00
mode = O_RDONLY ;
if ( ( ffd = open ( file , mode ) ) < 0 )
return 1 ;
2018-05-09 15:21:26 +03:00
2008-03-01 22:02:06 +03:00
for ( i = 3 ; i & & ( fd = open ( device , mode ) ) < 0 ; - - i , sleep ( 1 ) ) ;
if ( fd < 0 ) {
2004-01-20 21:32:43 +03:00
close ( ffd ) ;
return 1 ;
}
memset ( & loopinfo , 0 , sizeof ( loopinfo ) ) ;
strncpy ( loopinfo . lo_name , file , LO_NAME_SIZE ) ;
loopinfo . lo_name [ LO_NAME_SIZE - 1 ] = 0 ;
loopinfo . lo_offset = 0 ;
2018-05-09 15:21:26 +03:00
# ifdef MCL_FUTURE
2004-01-20 21:32:43 +03:00
/*
* Oh - oh , sensitive data coming up . Better lock into memory to prevent
* passwd etc being swapped out and left somewhere on disk .
*/
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
if ( mlockall ( MCL_CURRENT | MCL_FUTURE ) ) {
log_message ( " CRITICAL Couldn't lock into memory! %s (memlock) " , strerror ( errno ) ) ;
return 1 ;
}
# endif
if ( ioctl ( fd , LOOP_SET_FD , ffd ) < 0 ) {
close ( fd ) ;
close ( ffd ) ;
return 1 ;
}
2021-08-11 20:15:40 +03:00
/* Note: LOOP_SET_FD triggers change event. While processing it
* udev reads the loop device with builtin blkid . This can race
* with subsequent access by kernel due to LOOP_SET_STATUS ( or
* mounting the loop device ) . Therefore give udev a chance to
* process the event without concurrent access to the loop device
*/
udev_settle ( ) ;
2004-01-20 21:32:43 +03:00
if ( ioctl ( fd , LOOP_SET_STATUS , & loopinfo ) < 0 ) {
( void ) ioctl ( fd , LOOP_CLR_FD , 0 ) ;
close ( fd ) ;
close ( ffd ) ;
return 1 ;
}
2021-08-11 20:15:40 +03:00
/* Same here: LOOP_SET_STATUS triggers change event, give udev
* a chance to process it without concurrent access to the loop
* device . In other words , prevent the caller of this function
* from mounting the device while udev still running blkid on it
*/
udev_settle ( ) ;
2004-01-20 21:32:43 +03:00
close ( fd ) ;
close ( ffd ) ;
2021-08-11 20:15:40 +03:00
/* udev might be monitoring loopback device (with fanotify) and
* will synthesize a change event on close . Give udev some time
* to process without racing with the caller of this function
* ( which is going to mount the newly configured loopback device )
*/
udev_settle ( ) ;
2004-01-20 21:32:43 +03:00
return 0 ;
}
char * loopdev = " /dev/loop3 " ; /* Ugly. But do I care? */
2008-03-12 15:19:18 +03:00
void del_loop ( char * device )
2004-01-20 21:32:43 +03:00
{
int fd ;
2008-03-12 15:19:18 +03:00
if ( ( fd = open ( device , O_RDONLY ) ) < 0 )
2004-01-20 21:32:43 +03:00
return ;
if ( ioctl ( fd , LOOP_CLR_FD , 0 ) < 0 )
return ;
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
close ( fd ) ;
}
static char * where_mounted = NULL ;
int
lomount ( char * loopfile , char * where )
{
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
long int flag ;
flag = MS_MGC_VAL ;
flag | = MS_RDONLY ;
2008-03-01 22:02:06 +03:00
my_insmod ( " loop " , NULL ) ;
2004-01-20 21:32:43 +03:00
if ( set_loop ( loopdev , loopfile ) ) {
log_message ( " set_loop failed on %s (%s) " , loopdev , strerror ( errno ) ) ;
return 1 ;
}
2018-05-09 15:21:26 +03:00
2004-01-20 21:32:43 +03:00
if ( my_mount ( loopdev , where , " iso9660 " , 0 ) ) {
2008-03-12 15:19:18 +03:00
del_loop ( loopdev ) ;
2004-01-20 21:32:43 +03:00
return 1 ;
}
where_mounted = strdup ( where ) ;
log_message ( " lomount succeeded for %s on %s " , loopfile , where ) ;
return 0 ;
}
int
loumount ( )
{
if ( where_mounted ) {
umount ( where_mounted ) ;
where_mounted = NULL ;
}
2008-03-12 15:19:18 +03:00
del_loop ( loopdev ) ;
2004-01-20 21:32:43 +03:00
return 0 ;
}