mirror of
				https://gitlab.com/sortix/sortix.git
				synced 2023-02-13 20:55:38 -05:00 
			
		
		
		
	Add libmount.
This commit is contained in:
		
							parent
							
								
									aff8f4d89c
								
							
						
					
					
						commit
						e6a1cd6dee
					
				
					 28 changed files with 2783 additions and 0 deletions
				
			
		
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -9,6 +9,7 @@ libc \
 | 
			
		|||
libm \
 | 
			
		||||
libpthread \
 | 
			
		||||
dispd \
 | 
			
		||||
libmount \
 | 
			
		||||
bench \
 | 
			
		||||
carray \
 | 
			
		||||
editor \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								libmount/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								libmount/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
libmount.a
 | 
			
		||||
*.o
 | 
			
		||||
							
								
								
									
										46
									
								
								libmount/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libmount/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
SOFTWARE_MEANT_FOR_SORTIX=1
 | 
			
		||||
include ../build-aux/platform.mak
 | 
			
		||||
include ../build-aux/compiler.mak
 | 
			
		||||
include ../build-aux/version.mak
 | 
			
		||||
include ../build-aux/dirs.mak
 | 
			
		||||
 | 
			
		||||
OPTLEVEL?=$(DEFAULT_OPTLEVEL)
 | 
			
		||||
CFLAGS?=$(OPTLEVEL)
 | 
			
		||||
 | 
			
		||||
CFLAGS:=$(CFLAGS) -Wall -Wextra
 | 
			
		||||
CPPFLAGS:=$(CPPFLAGS) -Iinclude
 | 
			
		||||
 | 
			
		||||
OBJS:=\
 | 
			
		||||
biosboot.o \
 | 
			
		||||
blockdevice.o \
 | 
			
		||||
devices.o \
 | 
			
		||||
crc32.o \
 | 
			
		||||
ext2.o \
 | 
			
		||||
extended.o \
 | 
			
		||||
filesystem.o \
 | 
			
		||||
gpt.o \
 | 
			
		||||
harddisk.o \
 | 
			
		||||
mbr.o \
 | 
			
		||||
partition.o \
 | 
			
		||||
uuid.o \
 | 
			
		||||
 | 
			
		||||
all: libmount.a
 | 
			
		||||
 | 
			
		||||
.PHONY: all clean install
 | 
			
		||||
 | 
			
		||||
%.o: %.c
 | 
			
		||||
	$(CC) $(CFLAGS) $(CPPFLAGS) -std=gnu11 -c $< -o $@
 | 
			
		||||
 | 
			
		||||
libmount.a: $(OBJS)
 | 
			
		||||
	$(AR) rcs $@ $(OBJS)
 | 
			
		||||
 | 
			
		||||
install: libmount.a
 | 
			
		||||
	mkdir -p $(DESTDIR)$(INCLUDEDIR)
 | 
			
		||||
	cp -RTv include $(DESTDIR)$(INCLUDEDIR)
 | 
			
		||||
	mkdir -p $(DESTDIR)$(LIBDIR)
 | 
			
		||||
	cp libmount.a $(DESTDIR)$(LIBDIR)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -f libmount.a
 | 
			
		||||
	rm -f $(OBJS)
 | 
			
		||||
	rm -f *.o
 | 
			
		||||
							
								
								
									
										87
									
								
								libmount/biosboot.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								libmount/biosboot.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,87 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    biosboot.c
 | 
			
		||||
    GPT bios boot partition.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/biosboot.h>
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
#include <mount/uuid.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
static size_t biosboot_probe_amount(struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	(void) bdev;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool biosboot_probe(struct blockdevice* bdev,
 | 
			
		||||
                           const unsigned char* leading,
 | 
			
		||||
                           size_t amount)
 | 
			
		||||
{
 | 
			
		||||
	(void) leading;
 | 
			
		||||
	(void) amount;
 | 
			
		||||
	struct partition* p = bdev->p;
 | 
			
		||||
	if ( !p )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( p->table_type != PARTITION_TABLE_TYPE_GPT )
 | 
			
		||||
		return false;
 | 
			
		||||
	unsigned char uuid[16];
 | 
			
		||||
	uuid_from_string(uuid, BIOSBOOT_GPT_TYPE_UUID);
 | 
			
		||||
	return memcmp(p->gpt_type_guid, uuid, 16) == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void biosboot_release(struct filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return;
 | 
			
		||||
	free(fs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum filesystem_error biosboot_inspect(struct filesystem** fs_ptr,
 | 
			
		||||
                                              struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*fs_ptr = NULL;
 | 
			
		||||
	struct filesystem* fs = CALLOC_TYPE(struct filesystem);
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	fs->bdev = bdev;
 | 
			
		||||
	fs->handler = &biosboot_handler;
 | 
			
		||||
	fs->handler_private = NULL;
 | 
			
		||||
	fs->fstype_name = "biosboot";
 | 
			
		||||
	return *fs_ptr = fs, FILESYSTEM_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct filesystem_handler biosboot_handler =
 | 
			
		||||
{
 | 
			
		||||
	.handler_name = "biosboot",
 | 
			
		||||
	.probe_amount = biosboot_probe_amount,
 | 
			
		||||
	.probe = biosboot_probe,
 | 
			
		||||
	.inspect = biosboot_inspect,
 | 
			
		||||
	.release = biosboot_release,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										84
									
								
								libmount/blockdevice.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								libmount/blockdevice.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,84 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015, 2016.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    blockdevice.c
 | 
			
		||||
    Block device abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <ioleast.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/harddisk.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
 | 
			
		||||
blksize_t blockdevice_logical_block_size(const struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	while ( bdev->p )
 | 
			
		||||
		bdev = bdev->p->parent_bdev;
 | 
			
		||||
	assert(bdev->hd);
 | 
			
		||||
	return bdev->hd->logical_block_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool blockdevice_check_reasonable_block_size(blksize_t size)
 | 
			
		||||
{
 | 
			
		||||
	if ( size < 512 ) // Violates assumptions.
 | 
			
		||||
		return false;
 | 
			
		||||
	for ( blksize_t cmp = 512; cmp <= 65536; cmp *= 2 )
 | 
			
		||||
		if ( cmp == size )
 | 
			
		||||
			return true;
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
off_t blockdevice_size(const struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	if ( bdev->p )
 | 
			
		||||
		return bdev->p->length;
 | 
			
		||||
	assert(bdev->hd);
 | 
			
		||||
	return bdev->hd->st.st_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t blockdevice_preadall(const struct blockdevice* bdev,
 | 
			
		||||
                            void* buffer,
 | 
			
		||||
                            size_t count,
 | 
			
		||||
                            off_t off)
 | 
			
		||||
{
 | 
			
		||||
	if ( off < 0 )
 | 
			
		||||
		return errno = EINVAL, 0;
 | 
			
		||||
	while ( bdev->p )
 | 
			
		||||
	{
 | 
			
		||||
		if ( bdev->p->length < off )
 | 
			
		||||
			return 0;
 | 
			
		||||
		off_t available = bdev->p->length - off;
 | 
			
		||||
		if ( (uintmax_t) available < (uintmax_t) count )
 | 
			
		||||
			count = (size_t) available;
 | 
			
		||||
		if ( __builtin_add_overflow(bdev->p->start, off, &off) )
 | 
			
		||||
			return 0;
 | 
			
		||||
		bdev = bdev->p->parent_bdev;
 | 
			
		||||
	}
 | 
			
		||||
	assert(bdev->hd);
 | 
			
		||||
	return preadall(bdev->hd->fd, buffer, count, off);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								libmount/crc32.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libmount/crc32.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
/* crc32.c -- compute the CRC-32 of a data stream
 | 
			
		||||
 * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
 | 
			
		||||
 * Adapted by Jonas 'Sortie' Termansen for Sortix libmount in 2015.
 | 
			
		||||
 *
 | 
			
		||||
 * This software is provided 'as-is', without any express or implied
 | 
			
		||||
 * warranty.  In no event will the authors be held liable for any damages
 | 
			
		||||
 * arising from the use of this software.
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is granted to anyone to use this software for any purpose,
 | 
			
		||||
 * including commercial applications, and to alter it and redistribute it
 | 
			
		||||
 * freely, subject to the following restrictions:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. The origin of this software must not be misrepresented; you must not
 | 
			
		||||
 *    claim that you wrote the original software. If you use this software
 | 
			
		||||
 *    in a product, an acknowledgment in the product documentation would be
 | 
			
		||||
 *    appreciated but is not required.
 | 
			
		||||
 * 2. Altered source versions must be plainly marked as such, and must not be
 | 
			
		||||
 *    misrepresented as being the original software.
 | 
			
		||||
 * 3. This notice may not be removed or altered from any source distribution.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/gpt.h>
 | 
			
		||||
 | 
			
		||||
uint32_t gpt_crc32(const void* buffer_ptr, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	/* generate a crc for every 8-bit value */
 | 
			
		||||
	uint32_t poly = 0xedb88320UL;
 | 
			
		||||
	uint32_t crc_table[256];
 | 
			
		||||
	for ( unsigned int n = 0; n < 256; n++ )
 | 
			
		||||
	{
 | 
			
		||||
		uint32_t c = n;
 | 
			
		||||
		for ( unsigned int k = 0; k < 8; k++ )
 | 
			
		||||
			c = c & 1 ? poly ^ (c >> 1) : c >> 1;
 | 
			
		||||
		crc_table[n] = c;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* calculate bytewise crc of input buffer */
 | 
			
		||||
	const unsigned char* buffer = (const unsigned char*) buffer_ptr;
 | 
			
		||||
	uint32_t crc = 0xffffffffUL;
 | 
			
		||||
	for ( size_t i = 0; i < size; i++ )
 | 
			
		||||
		crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8);
 | 
			
		||||
	return crc ^ 0xffffffffUL;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										170
									
								
								libmount/devices.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								libmount/devices.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,170 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    devices.c
 | 
			
		||||
    Locate block devices.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <dirent.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/devices.h>
 | 
			
		||||
#include <mount/harddisk.h>
 | 
			
		||||
 | 
			
		||||
static bool is_partition_name(const char* path)
 | 
			
		||||
{
 | 
			
		||||
	const char* name = path;
 | 
			
		||||
	for ( size_t i = 0; path[i]; i++ )
 | 
			
		||||
		if ( path[i] == '/' )
 | 
			
		||||
			name = path + i + 1;
 | 
			
		||||
	if ( !isalpha((unsigned char) *name) )
 | 
			
		||||
		return false;
 | 
			
		||||
	name++;
 | 
			
		||||
	while ( isalpha((unsigned char) *name) )
 | 
			
		||||
		name++;
 | 
			
		||||
	if ( !isdigit((unsigned char) *name) )
 | 
			
		||||
		return false;
 | 
			
		||||
	name++;
 | 
			
		||||
	while ( isdigit((unsigned char) *name) )
 | 
			
		||||
		name++;
 | 
			
		||||
	if ( *name != 'p' )
 | 
			
		||||
		return false;
 | 
			
		||||
	name++;
 | 
			
		||||
	if ( !isdigit((unsigned char) *name) )
 | 
			
		||||
		return false;
 | 
			
		||||
	name++;
 | 
			
		||||
	while ( isdigit((unsigned char) *name) )
 | 
			
		||||
		name++;
 | 
			
		||||
	return *name == '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool devices_iterate_path(bool (*callback)(void*, const char*), void* ctx)
 | 
			
		||||
{
 | 
			
		||||
	const char* dev_path = "/dev";
 | 
			
		||||
	DIR* dir = opendir(dev_path);
 | 
			
		||||
	if ( !dir )
 | 
			
		||||
		return errno == ENOENT;
 | 
			
		||||
	// TODO: This readdir loop can be derailed if the callback creates devices.
 | 
			
		||||
	struct dirent* entry;
 | 
			
		||||
	while ( (errno = 0, entry = readdir(dir)) )
 | 
			
		||||
	{
 | 
			
		||||
		if ( entry->d_name[0] == '.' )
 | 
			
		||||
			continue;
 | 
			
		||||
		if ( entry->d_type != DT_UNKNOWN && entry->d_type != DT_BLK )
 | 
			
		||||
			continue;
 | 
			
		||||
		// TODO: Remove this once partitions identify themselves as such and
 | 
			
		||||
		//       libmount doesn't allow using them as a real full block device.
 | 
			
		||||
		if ( is_partition_name(entry->d_name) )
 | 
			
		||||
			continue;
 | 
			
		||||
		char* path;
 | 
			
		||||
		if ( asprintf(&path, "%s/%s", dev_path, entry->d_name) < 0 )
 | 
			
		||||
			return closedir(dir), false;
 | 
			
		||||
		bool success = callback(ctx, path);
 | 
			
		||||
		free(path);
 | 
			
		||||
		if ( !success )
 | 
			
		||||
			return closedir(dir), false;
 | 
			
		||||
	}
 | 
			
		||||
	bool success = errno == 0;
 | 
			
		||||
	closedir(dir);
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct devices_iterate_open
 | 
			
		||||
{
 | 
			
		||||
	void* ctx;
 | 
			
		||||
	bool (*callback)(void*, struct harddisk*);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool devices_iterate_open_callback(void* ctx_ptr, const char* path)
 | 
			
		||||
{
 | 
			
		||||
	struct devices_iterate_open* ctx = (struct devices_iterate_open*) ctx_ptr;
 | 
			
		||||
	struct harddisk* hd = harddisk_openat(AT_FDCWD, path, O_RDWR);
 | 
			
		||||
	if ( !hd )
 | 
			
		||||
	{
 | 
			
		||||
		int true_errno = errno;
 | 
			
		||||
		struct stat st;
 | 
			
		||||
		if ( lstat(path, 0) == 0 && !S_ISBLK(st.st_mode) )
 | 
			
		||||
			return true;
 | 
			
		||||
		errno = true_errno;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	if ( !harddisk_inspect_blockdevice(hd) )
 | 
			
		||||
	{
 | 
			
		||||
		bool success = errno == ENOTBLK;
 | 
			
		||||
		harddisk_close(hd);
 | 
			
		||||
		return success;
 | 
			
		||||
	}
 | 
			
		||||
	return ctx->callback(ctx->ctx, hd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool devices_iterate_open(bool (*callback)(void*, struct harddisk*), void* ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct devices_iterate_open myctx;
 | 
			
		||||
	myctx.ctx = ctx;
 | 
			
		||||
	myctx.callback = callback;
 | 
			
		||||
	return devices_iterate_path(devices_iterate_open_callback, &myctx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct devices_open_all
 | 
			
		||||
{
 | 
			
		||||
	struct harddisk** hds;
 | 
			
		||||
	size_t hds_count;
 | 
			
		||||
	size_t hds_allocated;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool devices_open_all_callback(void* ctx_ptr, struct harddisk* hd)
 | 
			
		||||
{
 | 
			
		||||
	struct devices_open_all* ctx = (struct devices_open_all*) ctx_ptr;
 | 
			
		||||
	if ( ctx->hds_count == ctx->hds_allocated )
 | 
			
		||||
	{
 | 
			
		||||
		size_t new_allocated = ctx->hds_allocated ? 2 * ctx->hds_allocated : 16;
 | 
			
		||||
		struct harddisk** new_hds = (struct harddisk**)
 | 
			
		||||
			reallocarray(ctx->hds, new_allocated, sizeof(struct harddisk*));
 | 
			
		||||
		if ( !new_hds )
 | 
			
		||||
			return harddisk_close(hd), false;
 | 
			
		||||
		ctx->hds = new_hds;
 | 
			
		||||
		ctx->hds_allocated = new_allocated;
 | 
			
		||||
	}
 | 
			
		||||
	ctx->hds[ctx->hds_count++] = hd;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool devices_open_all(struct harddisk*** hds_ptr, size_t* hds_count_ptr)
 | 
			
		||||
{
 | 
			
		||||
	struct devices_open_all myctx;
 | 
			
		||||
	myctx.hds = NULL;
 | 
			
		||||
	myctx.hds_count = 0;
 | 
			
		||||
	myctx.hds_allocated = 0;
 | 
			
		||||
	if ( !devices_iterate_open(devices_open_all_callback, &myctx) )
 | 
			
		||||
	{
 | 
			
		||||
		for ( size_t i = 0; i < myctx.hds_count; i++ )
 | 
			
		||||
			harddisk_close(myctx.hds[i]);
 | 
			
		||||
		free(myctx.hds);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	*hds_ptr = myctx.hds;
 | 
			
		||||
	*hds_count_ptr = myctx.hds_count;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										172
									
								
								libmount/ext2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								libmount/ext2.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,172 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    ext2.c
 | 
			
		||||
    ext2 filesystem.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/ext2.h>
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
void ext2_superblock_decode(struct ext2_superblock* sb)
 | 
			
		||||
{
 | 
			
		||||
	sb->s_inodes_count = le32toh(sb->s_inodes_count);
 | 
			
		||||
	sb->s_blocks_count = le32toh(sb->s_blocks_count);
 | 
			
		||||
	sb->s_r_blocks_count = le32toh(sb->s_r_blocks_count);
 | 
			
		||||
	sb->s_free_blocks_count = le32toh(sb->s_free_blocks_count);
 | 
			
		||||
	sb->s_free_inodes_count = le32toh(sb->s_free_inodes_count);
 | 
			
		||||
	sb->s_first_data_block = le32toh(sb->s_first_data_block);
 | 
			
		||||
	sb->s_log_block_size = le32toh(sb->s_log_block_size);
 | 
			
		||||
	sb->s_log_frag_size = (int32_t) le32toh((uint32_t) sb->s_log_frag_size);
 | 
			
		||||
	sb->s_blocks_per_group = le32toh(sb->s_blocks_per_group);
 | 
			
		||||
	sb->s_frags_per_group = le32toh(sb->s_frags_per_group);
 | 
			
		||||
	sb->s_inodes_per_group = le32toh(sb->s_inodes_per_group);
 | 
			
		||||
	sb->s_mtime = le32toh(sb->s_mtime);
 | 
			
		||||
	sb->s_wtime = le32toh(sb->s_wtime);
 | 
			
		||||
	sb->s_mnt_count = le16toh(sb->s_mnt_count);
 | 
			
		||||
	sb->s_max_mnt_count = le16toh(sb->s_max_mnt_count);
 | 
			
		||||
	sb->s_magic = le16toh(sb->s_magic);
 | 
			
		||||
	sb->s_state = le16toh(sb->s_state);
 | 
			
		||||
	sb->s_errors = le16toh(sb->s_errors);
 | 
			
		||||
	sb->s_minor_rev_level = le16toh(sb->s_minor_rev_level);
 | 
			
		||||
	sb->s_lastcheck = le32toh(sb->s_lastcheck);
 | 
			
		||||
	sb->s_checkinterval = le32toh(sb->s_checkinterval);
 | 
			
		||||
	sb->s_creator_os = le32toh(sb->s_creator_os);
 | 
			
		||||
	sb->s_rev_level = le32toh(sb->s_rev_level);
 | 
			
		||||
	sb->s_def_resuid = le16toh(sb->s_def_resuid);
 | 
			
		||||
	sb->s_def_resgid = le16toh(sb->s_def_resgid);
 | 
			
		||||
	sb->s_first_ino = le32toh(sb->s_first_ino);
 | 
			
		||||
	sb->s_inode_size = le16toh(sb->s_inode_size);
 | 
			
		||||
	sb->s_block_group_nr = le16toh(sb->s_block_group_nr);
 | 
			
		||||
	sb->s_feature_compat = le32toh(sb->s_feature_compat);
 | 
			
		||||
	sb->s_feature_incompat = le32toh(sb->s_feature_incompat);
 | 
			
		||||
	sb->s_feature_ro_compat = le32toh(sb->s_feature_ro_compat);
 | 
			
		||||
	// s_uuid is endian agnostic.
 | 
			
		||||
	// s_volume_name is endian agnostic.
 | 
			
		||||
	// s_last_mounted is endian agnostic.
 | 
			
		||||
	sb->s_algo_bitmap = le32toh(sb->s_algo_bitmap);
 | 
			
		||||
	// s_prealloc_blocks is endian agnostic.
 | 
			
		||||
	// s_prealloc_dir_blocks is endian agnostic.
 | 
			
		||||
	sb->alignment0 = le16toh(sb->alignment0);
 | 
			
		||||
	// s_journal_uuid is endian agnostic.
 | 
			
		||||
	sb->s_journal_inum = le32toh(sb->s_journal_inum);
 | 
			
		||||
	sb->s_journal_dev = le32toh(sb->s_journal_dev);
 | 
			
		||||
	sb->s_last_orphan = le32toh(sb->s_last_orphan);
 | 
			
		||||
	for ( size_t i = 0; i < 4; i++ )
 | 
			
		||||
		sb->s_hash_seed[i] = le32toh(sb->s_hash_seed[i]);
 | 
			
		||||
	// s_def_hash_version is endian agnostic.
 | 
			
		||||
	// alignment1 is endian agnostic.
 | 
			
		||||
	sb->s_default_mount_options = le32toh(sb->s_default_mount_options);
 | 
			
		||||
	sb->s_first_meta_bg = le32toh(sb->s_first_meta_bg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static size_t ext2_probe_amount(struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	(void) bdev;
 | 
			
		||||
	return 1024 + sizeof(struct ext2_superblock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool ext2_probe(struct blockdevice* bdev,
 | 
			
		||||
                       const unsigned char* leading,
 | 
			
		||||
                       size_t amount)
 | 
			
		||||
{
 | 
			
		||||
	(void) bdev;
 | 
			
		||||
	if ( amount < 1024 )
 | 
			
		||||
		return false;
 | 
			
		||||
	leading += 1024;
 | 
			
		||||
	amount -= 1024;
 | 
			
		||||
	if ( amount < sizeof(struct ext2_superblock) )
 | 
			
		||||
		return false;
 | 
			
		||||
	struct ext2_superblock sb;
 | 
			
		||||
	memcpy(&sb, leading, sizeof(sb));
 | 
			
		||||
	ext2_superblock_decode(&sb);
 | 
			
		||||
	if ( sb.s_magic != EXT2_SUPER_MAGIC )
 | 
			
		||||
		return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ext2_private
 | 
			
		||||
{
 | 
			
		||||
	struct ext2_superblock sb;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ext2_release(struct filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return;
 | 
			
		||||
	struct ext2_private* priv = (struct ext2_private*) fs->handler_private;
 | 
			
		||||
	free(priv);
 | 
			
		||||
	free(fs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum filesystem_error ext2_inspect(struct filesystem** fs_ptr,
 | 
			
		||||
                                          struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*fs_ptr = NULL;
 | 
			
		||||
	struct filesystem* fs = CALLOC_TYPE(struct filesystem);
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	struct ext2_private* priv = CALLOC_TYPE(struct ext2_private);
 | 
			
		||||
	if ( !priv )
 | 
			
		||||
		return free(fs), FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	fs->bdev = bdev;
 | 
			
		||||
	fs->handler = &ext2_handler;
 | 
			
		||||
	fs->handler_private = priv;
 | 
			
		||||
	struct ext2_superblock* sb = &priv->sb;
 | 
			
		||||
	if ( blockdevice_preadall(bdev, sb, sizeof(*sb), 1024) != sizeof(*sb) )
 | 
			
		||||
		return ext2_release(fs), FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	ext2_superblock_decode(sb);
 | 
			
		||||
	fs->fstype_name = "ext2";
 | 
			
		||||
	fs->fsck = "fsck.ext2";
 | 
			
		||||
	fs->driver = "extfs";
 | 
			
		||||
	fs->flags |= FILESYSTEM_FLAG_UUID;
 | 
			
		||||
	memcpy(&fs->uuid, sb->s_uuid, 16);
 | 
			
		||||
	struct timespec now;
 | 
			
		||||
	clock_gettime(CLOCK_REALTIME, &now);
 | 
			
		||||
	time_t next_check = (time_t)
 | 
			
		||||
		((uintmax_t) sb->s_lastcheck + (uintmax_t) sb->s_checkinterval);
 | 
			
		||||
	if ( sb->s_state != EXT2_VALID_FS )
 | 
			
		||||
		fs->flags |= FILESYSTEM_FLAG_FSCK_SHOULD |
 | 
			
		||||
		             FILESYSTEM_FLAG_FSCK_MUST;
 | 
			
		||||
	else if ( sb->s_max_mnt_count && sb->s_max_mnt_count <= sb->s_mnt_count )
 | 
			
		||||
		fs->flags |= FILESYSTEM_FLAG_FSCK_SHOULD;
 | 
			
		||||
	else if ( sb->s_checkinterval && next_check <= now.tv_sec )
 | 
			
		||||
		fs->flags |= FILESYSTEM_FLAG_FSCK_SHOULD;
 | 
			
		||||
	return *fs_ptr = fs, FILESYSTEM_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct filesystem_handler ext2_handler =
 | 
			
		||||
{
 | 
			
		||||
	.handler_name = "ext2",
 | 
			
		||||
	.probe_amount = ext2_probe_amount,
 | 
			
		||||
	.probe = ext2_probe,
 | 
			
		||||
	.inspect = ext2_inspect,
 | 
			
		||||
	.release = ext2_release,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										85
									
								
								libmount/extended.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								libmount/extended.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    extended.c
 | 
			
		||||
    MBR extended partition.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/extended.h>
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
#include <mount/uuid.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
static size_t extended_probe_amount(struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	(void) bdev;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool extended_probe(struct blockdevice* bdev,
 | 
			
		||||
                           const unsigned char* leading,
 | 
			
		||||
                           size_t amount)
 | 
			
		||||
{
 | 
			
		||||
	(void) leading;
 | 
			
		||||
	(void) amount;
 | 
			
		||||
	struct partition* p = bdev->p;
 | 
			
		||||
	if ( !p )
 | 
			
		||||
		return false;
 | 
			
		||||
	return p->table_type == PARTITION_TABLE_TYPE_MBR &&
 | 
			
		||||
		   (p->mbr_system_id == 0x05 ||
 | 
			
		||||
	        p->mbr_system_id == 0x0F);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void extended_release(struct filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return;
 | 
			
		||||
	free(fs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static enum filesystem_error extended_inspect(struct filesystem** fs_ptr,
 | 
			
		||||
                                              struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*fs_ptr = NULL;
 | 
			
		||||
	struct filesystem* fs = CALLOC_TYPE(struct filesystem);
 | 
			
		||||
	if ( !fs )
 | 
			
		||||
		return FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	fs->bdev = bdev;
 | 
			
		||||
	fs->handler = &extended_handler;
 | 
			
		||||
	fs->handler_private = NULL;
 | 
			
		||||
	fs->fstype_name = "extended";
 | 
			
		||||
	return *fs_ptr = fs, FILESYSTEM_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct filesystem_handler extended_handler =
 | 
			
		||||
{
 | 
			
		||||
	.handler_name = "extended",
 | 
			
		||||
	.probe_amount = extended_probe_amount,
 | 
			
		||||
	.probe = extended_probe,
 | 
			
		||||
	.inspect = extended_inspect,
 | 
			
		||||
	.release = extended_release,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										102
									
								
								libmount/filesystem.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								libmount/filesystem.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,102 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    filesystem.c
 | 
			
		||||
    Filesystem abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/biosboot.h>
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/ext2.h>
 | 
			
		||||
#include <mount/extended.h>
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
 | 
			
		||||
const char* filesystem_error_string(enum filesystem_error error)
 | 
			
		||||
{
 | 
			
		||||
	switch ( error )
 | 
			
		||||
	{
 | 
			
		||||
	case FILESYSTEM_ERROR_NONE:
 | 
			
		||||
		break;
 | 
			
		||||
	case FILESYSTEM_ERROR_ABSENT:
 | 
			
		||||
		return "No filesystem found";
 | 
			
		||||
	case FILESYSTEM_ERROR_UNRECOGNIZED:
 | 
			
		||||
		return "Unrecognized filesystem type";
 | 
			
		||||
	case FILESYSTEM_ERROR_ERRNO:
 | 
			
		||||
		return (const char*) strerror(errno);
 | 
			
		||||
	}
 | 
			
		||||
	return "Unknown error condition";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct filesystem_handler* filesystem_handlers[] =
 | 
			
		||||
{
 | 
			
		||||
	&biosboot_handler,
 | 
			
		||||
	&extended_handler,
 | 
			
		||||
	&ext2_handler,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void filesystem_release(struct filesystem* fs)
 | 
			
		||||
{
 | 
			
		||||
	if ( !fs || !fs->handler )
 | 
			
		||||
		return;
 | 
			
		||||
	fs->handler->release(fs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum filesystem_error
 | 
			
		||||
blockdevice_inspect_filesystem(struct filesystem** fs_ptr,
 | 
			
		||||
                               struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*fs_ptr = NULL;
 | 
			
		||||
	size_t leading_size = 65536;
 | 
			
		||||
	for ( size_t i = 0; filesystem_handlers[i]; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		size_t amount = filesystem_handlers[i]->probe_amount(bdev);
 | 
			
		||||
		if ( leading_size < amount )
 | 
			
		||||
			leading_size = amount;
 | 
			
		||||
	}
 | 
			
		||||
	unsigned char* leading = (unsigned char*) malloc(leading_size);
 | 
			
		||||
	if ( !leading )
 | 
			
		||||
		return *fs_ptr = NULL, FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	size_t amount = blockdevice_preadall(bdev, leading, leading_size, 0);
 | 
			
		||||
	if ( amount < leading_size && errno != EEOF )
 | 
			
		||||
		return free(leading), *fs_ptr = NULL, FILESYSTEM_ERROR_ERRNO;
 | 
			
		||||
	for ( size_t i = 0; filesystem_handlers[i]; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		if ( !filesystem_handlers[i]->probe(bdev, leading, amount) )
 | 
			
		||||
			continue;
 | 
			
		||||
		free(leading);
 | 
			
		||||
		return filesystem_handlers[i]->inspect(fs_ptr, bdev);
 | 
			
		||||
	}
 | 
			
		||||
	for ( size_t i = 0; i < amount; i++ )
 | 
			
		||||
		if ( !leading[i] )
 | 
			
		||||
			return free(leading), FILESYSTEM_ERROR_UNRECOGNIZED;
 | 
			
		||||
	return free(leading), FILESYSTEM_ERROR_ABSENT;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										325
									
								
								libmount/gpt.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								libmount/gpt.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,325 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    gpt.c
 | 
			
		||||
    GUID Partition Table.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <wchar.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/gpt.h>
 | 
			
		||||
#include <mount/harddisk.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
void gpt_decode(struct gpt* v)
 | 
			
		||||
{
 | 
			
		||||
	// signature is endian agnostic.
 | 
			
		||||
	v->revision = le32toh(v->revision);
 | 
			
		||||
	v->header_size = le32toh(v->header_size);
 | 
			
		||||
	v->header_crc32 = le32toh(v->header_crc32);
 | 
			
		||||
	v->reserved0 = le32toh(v->reserved0);
 | 
			
		||||
	v->my_lba = le64toh(v->my_lba);
 | 
			
		||||
	v->alternate_lba = le64toh(v->alternate_lba);
 | 
			
		||||
	v->first_usable_lba = le64toh(v->first_usable_lba);
 | 
			
		||||
	v->last_usable_lba = le64toh(v->last_usable_lba);
 | 
			
		||||
	// disk_guid is endian agnostic.
 | 
			
		||||
	v->partition_entry_lba = le64toh(v->partition_entry_lba);
 | 
			
		||||
	v->number_of_partition_entries = le32toh(v->number_of_partition_entries);
 | 
			
		||||
	v->size_of_partition_entry = le32toh(v->size_of_partition_entry);
 | 
			
		||||
	v->partition_entry_array_crc32 = le32toh(v->partition_entry_array_crc32);
 | 
			
		||||
	// reserved bytes are endian agnostic.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gpt_encode(struct gpt* v)
 | 
			
		||||
{
 | 
			
		||||
	// signature is endian agnostic.
 | 
			
		||||
	v->revision = htole32(v->revision);
 | 
			
		||||
	v->header_size = htole32(v->header_size);
 | 
			
		||||
	v->header_crc32 = htole32(v->header_crc32);
 | 
			
		||||
	v->reserved0 = htole32(v->reserved0);
 | 
			
		||||
	v->my_lba = htole64(v->my_lba);
 | 
			
		||||
	v->alternate_lba = htole64(v->alternate_lba);
 | 
			
		||||
	v->first_usable_lba = htole64(v->first_usable_lba);
 | 
			
		||||
	v->last_usable_lba = htole64(v->last_usable_lba);
 | 
			
		||||
	// disk_guid is endian agnostic.
 | 
			
		||||
	v->partition_entry_lba = htole64(v->partition_entry_lba);
 | 
			
		||||
	v->number_of_partition_entries = htole32(v->number_of_partition_entries);
 | 
			
		||||
	v->size_of_partition_entry = htole32(v->size_of_partition_entry);
 | 
			
		||||
	v->partition_entry_array_crc32 = htole32(v->partition_entry_array_crc32);
 | 
			
		||||
	// reserved bytes are endian agnostic.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gpt_partition_decode(struct gpt_partition* v)
 | 
			
		||||
{
 | 
			
		||||
	// partition_type_guid is endian agnostic.
 | 
			
		||||
	// unique_partition_guid is endian agnostic.
 | 
			
		||||
	v->starting_lba = le64toh(v->starting_lba);
 | 
			
		||||
	v->ending_lba = le64toh(v->ending_lba);
 | 
			
		||||
	v->attributes = le64toh(v->attributes);
 | 
			
		||||
	for ( size_t i = 0; i < GPT_PARTITION_NAME_LENGTH; i++ )
 | 
			
		||||
		v->partition_name[i] = le16toh(v->partition_name[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gpt_partition_encode(struct gpt_partition* v)
 | 
			
		||||
{
 | 
			
		||||
	// partition_type_guid is endian agnostic.
 | 
			
		||||
	// unique_partition_guid is endian agnostic.
 | 
			
		||||
	v->starting_lba = htole64(v->starting_lba);
 | 
			
		||||
	v->ending_lba = htole64(v->ending_lba);
 | 
			
		||||
	v->attributes = htole64(v->attributes);
 | 
			
		||||
	for ( size_t i = 0; i < GPT_PARTITION_NAME_LENGTH; i++ )
 | 
			
		||||
		v->partition_name[i] = htole16(v->partition_name[i]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char* gpt_decode_utf16(uint16_t* string, size_t length)
 | 
			
		||||
{
 | 
			
		||||
	mbstate_t ps;
 | 
			
		||||
	memset(&ps, 0, sizeof(ps));
 | 
			
		||||
 | 
			
		||||
	char* result = NULL;
 | 
			
		||||
	size_t result_used = 0;
 | 
			
		||||
	size_t result_length = 0;
 | 
			
		||||
 | 
			
		||||
	for ( size_t i = 0; true; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		wchar_t wc;
 | 
			
		||||
		if ( length <= i )
 | 
			
		||||
			wc = L'\0';
 | 
			
		||||
		else if ( 0xDC00 <= string[i] && string[i] <= 0xDFFF )
 | 
			
		||||
			return free(result), errno = EILSEQ, (char*) NULL;
 | 
			
		||||
		else if ( 0xD800 <= string[i] && string[i] <= 0xDBFF )
 | 
			
		||||
		{
 | 
			
		||||
			uint16_t high = string[i] - 0xD800;
 | 
			
		||||
			if ( i + 1 == length )
 | 
			
		||||
				return free(result), errno = EILSEQ, (char*) NULL;
 | 
			
		||||
			if ( !(0xDC00 <= string[i+1] && string[i] <= 0xDFFF) )
 | 
			
		||||
				return free(result), errno = EILSEQ, (char*) NULL;
 | 
			
		||||
			uint16_t low = string[++i] - 0xDC00;
 | 
			
		||||
			wc = (((wchar_t) high << 10) | ((wchar_t) low << 0)) + 0x10000;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			wc = (wchar_t) string[i++];
 | 
			
		||||
		char mb[MB_CUR_MAX];
 | 
			
		||||
		size_t amount = wcrtomb(mb, wc, &ps);
 | 
			
		||||
		if ( amount == (size_t) -1 )
 | 
			
		||||
			return free(result), (char*) NULL;
 | 
			
		||||
		for ( size_t n = 0; n < amount; n++ )
 | 
			
		||||
		{
 | 
			
		||||
			if ( result_used == result_length )
 | 
			
		||||
			{
 | 
			
		||||
				// TODO: Potential overflow.
 | 
			
		||||
				size_t new_length = result_length ? 2 * result_length : length;
 | 
			
		||||
				char* new_result = (char*) realloc(result, new_length);
 | 
			
		||||
				if ( !new_result )
 | 
			
		||||
					return free(result), (char*) NULL;
 | 
			
		||||
				result = new_result;
 | 
			
		||||
				result_length = new_length;
 | 
			
		||||
			}
 | 
			
		||||
			result[result_used++] = mb[n];
 | 
			
		||||
		}
 | 
			
		||||
		if ( wc == L'\0' )
 | 
			
		||||
		{
 | 
			
		||||
			char* new_result = (char*) realloc(result, result_used);
 | 
			
		||||
			if ( new_result )
 | 
			
		||||
				result = new_result;
 | 
			
		||||
			return result;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gpt_partition_table_release(struct gpt_partition_table* pt)
 | 
			
		||||
{
 | 
			
		||||
	if ( !pt )
 | 
			
		||||
		return;
 | 
			
		||||
	free(pt->rpt);
 | 
			
		||||
	free(pt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool gpt_check_power_of_two(uintmax_t value,
 | 
			
		||||
                                   uintmax_t low,
 | 
			
		||||
                                   uintmax_t high)
 | 
			
		||||
{
 | 
			
		||||
	for ( uintmax_t cmp = low; cmp <= high; cmp *= 2 )
 | 
			
		||||
		if ( value == cmp )
 | 
			
		||||
			return true;
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table_gpt(struct partition_table** pt_ptr,
 | 
			
		||||
                                    struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*pt_ptr = NULL;
 | 
			
		||||
	blksize_t logical_block_size = blockdevice_logical_block_size(bdev);
 | 
			
		||||
	if ( !blockdevice_check_reasonable_block_size(logical_block_size) )
 | 
			
		||||
		return errno = EINVAL, PARTITION_ERROR_ERRNO;
 | 
			
		||||
	off_t device_size = blockdevice_size(bdev);
 | 
			
		||||
	const char* device_path = bdev->p ? bdev->p->path : bdev->hd->path;
 | 
			
		||||
 | 
			
		||||
	unsigned char* gpt_block = (unsigned char*) malloc(logical_block_size);
 | 
			
		||||
	if ( !gpt_block )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	if ( blockdevice_preadall(bdev, gpt_block, logical_block_size,
 | 
			
		||||
	                          1 * logical_block_size) != (size_t) logical_block_size )
 | 
			
		||||
		return free(gpt_block), PARTITION_ERROR_ERRNO;
 | 
			
		||||
 | 
			
		||||
	struct gpt gpt;
 | 
			
		||||
	memcpy(&gpt, gpt_block, sizeof(gpt));
 | 
			
		||||
	gpt_decode(&gpt);
 | 
			
		||||
 | 
			
		||||
	if ( memcmp(gpt.signature, "EFI PART", 8) != 0 )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
	static_assert( 92 == sizeof(gpt) - sizeof(gpt.reserved1),
 | 
			
		||||
	              "92 == sizeof(gpt) - sizeof(gpt.reserved1)");
 | 
			
		||||
	if ( gpt.header_size < 92 )
 | 
			
		||||
		return free(gpt_block), PARTITION_ERROR_INVALID;
 | 
			
		||||
 | 
			
		||||
	struct partition_table* pt = CALLOC_TYPE(struct partition_table);
 | 
			
		||||
	if ( !pt )
 | 
			
		||||
		return free(gpt_block), PARTITION_ERROR_ERRNO;
 | 
			
		||||
	*pt_ptr = pt;
 | 
			
		||||
	pt->type = PARTITION_TABLE_TYPE_GPT;
 | 
			
		||||
	size_t pt__partitions_length = 0;
 | 
			
		||||
 | 
			
		||||
	if ( logical_block_size < gpt.header_size )
 | 
			
		||||
		return free(gpt_block), PARTITION_ERROR_HEADER_TOO_LARGE;
 | 
			
		||||
 | 
			
		||||
	struct gpt_partition_table* gptpt = CALLOC_TYPE(struct gpt_partition_table);
 | 
			
		||||
	if ( !gptpt )
 | 
			
		||||
		return free(gpt_block), PARTITION_ERROR_ERRNO;
 | 
			
		||||
	pt->raw_partition_table = gptpt;
 | 
			
		||||
	memcpy(&gptpt->gpt, gpt_block, sizeof(gptpt->gpt));
 | 
			
		||||
 | 
			
		||||
	struct gpt* check_gpt = (struct gpt*) gpt_block;
 | 
			
		||||
	check_gpt->header_crc32 = 0;
 | 
			
		||||
	uint32_t checksum = gpt_crc32(gpt_block, gpt.header_size);
 | 
			
		||||
	free(gpt_block);
 | 
			
		||||
	if ( checksum != gpt.header_crc32 )
 | 
			
		||||
		return PARTITION_ERROR_CHECKSUM;
 | 
			
		||||
 | 
			
		||||
	memcpy(pt->gpt_disk_guid, gpt.disk_guid, 16);
 | 
			
		||||
 | 
			
		||||
	if ( !gpt_check_power_of_two(gpt.size_of_partition_entry,
 | 
			
		||||
	                             sizeof(struct gpt_partition), 65536) )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
	if ( gpt.my_lba != 1 )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
 | 
			
		||||
	if ( gpt.my_lba >= gpt.first_usable_lba )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
	// TODO: Ensure nothing collides with anything else.
 | 
			
		||||
	if ( gpt.partition_entry_lba <= 1 )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
	if ( gpt.last_usable_lba < gpt.first_usable_lba )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
 | 
			
		||||
	// TODO: Potential overflow.
 | 
			
		||||
	pt->usable_start = (off_t) gpt.first_usable_lba * (off_t) logical_block_size;
 | 
			
		||||
	pt->usable_end = ((off_t) gpt.last_usable_lba + 1) * (off_t) logical_block_size;
 | 
			
		||||
	if ( device_size < pt->usable_end )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
 | 
			
		||||
	// TODO: Potential overflow.
 | 
			
		||||
	size_t rpt_size = (size_t) gpt.size_of_partition_entry *
 | 
			
		||||
	                  (size_t) gpt.number_of_partition_entries;
 | 
			
		||||
	off_t rpt_off = (off_t) gpt.partition_entry_lba * (off_t) logical_block_size;
 | 
			
		||||
	off_t rpt_end = rpt_off + rpt_off;
 | 
			
		||||
	if ( pt->usable_start < rpt_end )
 | 
			
		||||
		return PARTITION_ERROR_INVALID;
 | 
			
		||||
	if ( !(gptpt->rpt = (unsigned char*) malloc(rpt_size)) )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	unsigned char* rpt = gptpt->rpt;
 | 
			
		||||
	if ( blockdevice_preadall(bdev, rpt, rpt_size, rpt_off) != rpt_size )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	if ( gpt.partition_entry_array_crc32 != gpt_crc32(rpt, rpt_size) )
 | 
			
		||||
		return PARTITION_ERROR_CHECKSUM;
 | 
			
		||||
 | 
			
		||||
	for ( uint32_t i = 0; i < gpt.number_of_partition_entries; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		size_t pentry_off = (size_t) i * (size_t) gpt.size_of_partition_entry;
 | 
			
		||||
		struct gpt_partition pentry;
 | 
			
		||||
		memcpy(&pentry, rpt + pentry_off, sizeof(pentry));
 | 
			
		||||
		gpt_partition_decode(&pentry);
 | 
			
		||||
		if ( memiszero(pentry.partition_type_guid, 16) )
 | 
			
		||||
			continue;
 | 
			
		||||
		if ( pentry.ending_lba < pentry.starting_lba )
 | 
			
		||||
			return PARTITION_ERROR_END_BEFORE_START;
 | 
			
		||||
		// TODO: Potential overflow.
 | 
			
		||||
		uint64_t lba_count = (pentry.ending_lba - pentry.starting_lba) + 1;
 | 
			
		||||
		off_t start = (off_t) pentry.starting_lba * (off_t) logical_block_size;
 | 
			
		||||
		if ( start < pt->usable_start )
 | 
			
		||||
			return PARTITION_ERROR_BEFORE_USABLE;
 | 
			
		||||
		off_t length = (off_t) lba_count * (off_t) logical_block_size;
 | 
			
		||||
		if ( pt->usable_end < start || pt->usable_end - start < length )
 | 
			
		||||
			return PARTITION_ERROR_BEYOND_USABLE;
 | 
			
		||||
		struct partition* p = CALLOC_TYPE(struct partition);
 | 
			
		||||
		if ( !p )
 | 
			
		||||
			return PARTITION_ERROR_ERRNO;
 | 
			
		||||
		memset(&p->bdev, 0, sizeof(p->bdev));
 | 
			
		||||
		p->bdev.p = p;
 | 
			
		||||
		p->parent_bdev = bdev;
 | 
			
		||||
		p->index = 1 + i;
 | 
			
		||||
		p->start = start;
 | 
			
		||||
		p->length = length;
 | 
			
		||||
		p->type = PARTITION_TYPE_PRIMARY;
 | 
			
		||||
		p->table_type = PARTITION_TABLE_TYPE_GPT;
 | 
			
		||||
		memcpy(p->gpt_type_guid, pentry.partition_type_guid, 16);
 | 
			
		||||
		memcpy(p->gpt_unique_guid, pentry.unique_partition_guid, 16);
 | 
			
		||||
		p->gpt_attributes = pentry.attributes;
 | 
			
		||||
		if ( !array_add((void***) &pt->partitions,
 | 
			
		||||
				        &pt->partitions_count,
 | 
			
		||||
				        &pt__partitions_length,
 | 
			
		||||
				        p) )
 | 
			
		||||
			return free(p), PARTITION_ERROR_ERRNO;
 | 
			
		||||
		if ( !(p->gpt_name = gpt_decode_utf16(pentry.partition_name,
 | 
			
		||||
		                                      GPT_PARTITION_NAME_LENGTH)) )
 | 
			
		||||
			return PARTITION_ERROR_ERRNO;
 | 
			
		||||
		if ( device_path &&
 | 
			
		||||
		     asprintf(&p->path, "%sp%u", device_path, p->index) < 0 )
 | 
			
		||||
			return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	qsort(pt->partitions, pt->partitions_count, sizeof(pt->partitions[0]),
 | 
			
		||||
	      partition_compare_start_indirect);
 | 
			
		||||
	for ( size_t i = 1; i < pt->partitions_count; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		struct partition* a = pt->partitions[i-1];
 | 
			
		||||
		struct partition* b = pt->partitions[i];
 | 
			
		||||
		if ( partition_check_overlap(a, b->start, b->length) )
 | 
			
		||||
			return PARTITION_ERROR_OVERLAP;
 | 
			
		||||
	}
 | 
			
		||||
	qsort(pt->partitions, pt->partitions_count, sizeof(pt->partitions[0]),
 | 
			
		||||
	      partition_compare_index_indirect);
 | 
			
		||||
 | 
			
		||||
	return PARTITION_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										123
									
								
								libmount/harddisk.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								libmount/harddisk.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,123 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    harddisk.c
 | 
			
		||||
    Harddisk abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <termios.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/harddisk.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
static char* atcgetblob(int fd, const char* name, size_t* size_ptr)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t size = tcgetblob(fd, name, NULL, 0);
 | 
			
		||||
	if ( size < 0 )
 | 
			
		||||
		return NULL;
 | 
			
		||||
	char* result = (char*) malloc((size_t) size + 1);
 | 
			
		||||
	if ( !result )
 | 
			
		||||
		return NULL;
 | 
			
		||||
	ssize_t second_size = tcgetblob(fd, name, result, (size_t) size);
 | 
			
		||||
	if ( second_size != size )
 | 
			
		||||
		return free(result), (char*) NULL;
 | 
			
		||||
	result[(size_t) size] = '\0';
 | 
			
		||||
	if ( size_ptr )
 | 
			
		||||
		*size_ptr = (size_t) size;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct harddisk* harddisk_openat(int dirfd, const char* relpath, int rdwr)
 | 
			
		||||
{
 | 
			
		||||
	struct harddisk* hd = CALLOC_TYPE(struct harddisk);
 | 
			
		||||
	if ( !hd )
 | 
			
		||||
		return (struct harddisk*) NULL;
 | 
			
		||||
	memset(&hd->bdev, 0, sizeof(hd->bdev));
 | 
			
		||||
	hd->bdev.hd = hd;
 | 
			
		||||
	if ( (hd->fd = openat(dirfd, relpath, rdwr)) < 0 )
 | 
			
		||||
		return harddisk_close(hd), (struct harddisk*) NULL;
 | 
			
		||||
	if ( !(hd->path = canonicalize_file_name_at(dirfd, relpath)) )
 | 
			
		||||
		return harddisk_close(hd), (struct harddisk*) NULL;
 | 
			
		||||
	if ( fstat(hd->fd, &hd->st) < 0 )
 | 
			
		||||
		return harddisk_close(hd), (struct harddisk*) NULL;
 | 
			
		||||
	return hd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool harddisk_inspect_blockdevice(struct harddisk* hd)
 | 
			
		||||
{
 | 
			
		||||
	if ( !S_ISBLK(hd->st.st_mode) )
 | 
			
		||||
		return errno = ENOTBLK, false;
 | 
			
		||||
	if ( tcgetblob(hd->fd, "harddisk-driver", NULL, 0) < 0 )
 | 
			
		||||
	{
 | 
			
		||||
		if ( errno == ENOENT )
 | 
			
		||||
			errno = ENOTBLK;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	if ( !(hd->driver = atcgetblob(hd->fd, "harddisk-driver", NULL)) ||
 | 
			
		||||
	     !(hd->model = atcgetblob(hd->fd, "harddisk-model", NULL)) ||
 | 
			
		||||
	     !(hd->serial = atcgetblob(hd->fd, "harddisk-serial", NULL)) )
 | 
			
		||||
		return harddisk_close(hd), false;
 | 
			
		||||
	char* str;
 | 
			
		||||
	if ( !(str = atcgetblob(hd->fd, "harddisk-block-size", NULL)) )
 | 
			
		||||
		return harddisk_close(hd), false;
 | 
			
		||||
	hd->logical_block_size = (blksize_t) strtoumax(str, NULL, 10);
 | 
			
		||||
	free(str);
 | 
			
		||||
	if ( !(str = atcgetblob(hd->fd, "harddisk-cylinders", NULL)) )
 | 
			
		||||
		return harddisk_close(hd), false;
 | 
			
		||||
	hd->cylinders = (uint16_t) strtoul(str, NULL, 10);
 | 
			
		||||
	free(str);
 | 
			
		||||
	if ( !(str = atcgetblob(hd->fd, "harddisk-heads", NULL)) )
 | 
			
		||||
		return harddisk_close(hd), false;
 | 
			
		||||
	hd->heads = (uint16_t) strtoul(str, NULL, 10);
 | 
			
		||||
	free(str);
 | 
			
		||||
	if ( !(str = atcgetblob(hd->fd, "harddisk-sectors", NULL)) )
 | 
			
		||||
		return harddisk_close(hd), false;
 | 
			
		||||
	hd->sectors = (uint16_t) strtoul(str, NULL, 10);
 | 
			
		||||
	free(str);
 | 
			
		||||
	// TODO: To avoid potential overflow bugs (assuming malicious filesystem),
 | 
			
		||||
	//       reject ridiculous block sizes.
 | 
			
		||||
	if ( 65536 < hd->logical_block_size )
 | 
			
		||||
		return harddisk_close(hd), errno = EINVAL, false;
 | 
			
		||||
	if ( hd->logical_block_size < 512 )
 | 
			
		||||
		return harddisk_close(hd), errno = EINVAL, false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void harddisk_close(struct harddisk* hd)
 | 
			
		||||
{
 | 
			
		||||
	if ( 0 <= hd->fd )
 | 
			
		||||
		close(hd->fd);
 | 
			
		||||
	free(hd->path);
 | 
			
		||||
	free(hd->driver);
 | 
			
		||||
	free(hd->model);
 | 
			
		||||
	free(hd->serial);
 | 
			
		||||
	free(hd);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								libmount/include/mount/biosboot.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								libmount/include/mount/biosboot.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/biosboot.h
 | 
			
		||||
    GPT bios boot partition.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_BIOSBOOT_H
 | 
			
		||||
#define INCLUDE_MOUNT_BIOSBOOT_H
 | 
			
		||||
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
 | 
			
		||||
#define BIOSBOOT_GPT_TYPE_UUID "48616821-4964-6f6e-744e-656564454649"
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern const struct filesystem_handler biosboot_handler;
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										66
									
								
								libmount/include/mount/blockdevice.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libmount/include/mount/blockdevice.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/blockdevice.h
 | 
			
		||||
    Block device abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_BLOCKDEVICE_H
 | 
			
		||||
#define INCLUDE_MOUNT_BLOCKDEVICE_H
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/error.h>
 | 
			
		||||
 | 
			
		||||
struct filesystem;
 | 
			
		||||
struct harddisk;
 | 
			
		||||
struct partition;
 | 
			
		||||
struct partition_table;
 | 
			
		||||
 | 
			
		||||
struct blockdevice
 | 
			
		||||
{
 | 
			
		||||
	struct harddisk* hd;
 | 
			
		||||
	struct partition* p;
 | 
			
		||||
	struct partition_table* pt;
 | 
			
		||||
	struct filesystem* fs;
 | 
			
		||||
	enum partition_error pt_error;
 | 
			
		||||
	enum filesystem_error fs_error;
 | 
			
		||||
	void* user_ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
blksize_t blockdevice_logical_block_size(const struct blockdevice*);
 | 
			
		||||
bool blockdevice_check_reasonable_block_size(blksize_t);
 | 
			
		||||
off_t blockdevice_size(const struct blockdevice*);
 | 
			
		||||
size_t blockdevice_preadall(const struct blockdevice*, void*, size_t, off_t);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										46
									
								
								libmount/include/mount/devices.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libmount/include/mount/devices.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/devices.h
 | 
			
		||||
    Locate block devices.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_DEVICES_H
 | 
			
		||||
#define INCLUDE_MOUNT_DEVICES_H
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct harddisk;
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool devices_iterate_path(bool (*)(void*, const char*), void*);
 | 
			
		||||
bool devices_iterate_open(bool (*)(void*, struct harddisk*), void*);
 | 
			
		||||
bool devices_open_all(struct harddisk***, size_t*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										56
									
								
								libmount/include/mount/error.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								libmount/include/mount/error.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/error.h
 | 
			
		||||
    Error enumerations.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_ERROR_H
 | 
			
		||||
#define INCLUDE_MOUNT_ERROR_H
 | 
			
		||||
 | 
			
		||||
enum filesystem_error
 | 
			
		||||
{
 | 
			
		||||
	FILESYSTEM_ERROR_NONE,
 | 
			
		||||
	FILESYSTEM_ERROR_ABSENT,
 | 
			
		||||
	FILESYSTEM_ERROR_UNRECOGNIZED,
 | 
			
		||||
	FILESYSTEM_ERROR_ERRNO,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum partition_error
 | 
			
		||||
{
 | 
			
		||||
	PARTITION_ERROR_NONE,
 | 
			
		||||
	PARTITION_ERROR_ABSENT,
 | 
			
		||||
	PARTITION_ERROR_UNRECOGNIZED,
 | 
			
		||||
	PARTITION_ERROR_ERRNO,
 | 
			
		||||
	PARTITION_ERROR_INVALID,
 | 
			
		||||
	PARTITION_ERROR_HEADER_TOO_LARGE,
 | 
			
		||||
	PARTITION_ERROR_CHECKSUM,
 | 
			
		||||
	PARTITION_ERROR_OVERLAP,
 | 
			
		||||
	PARTITION_ERROR_END_BEFORE_START,
 | 
			
		||||
	PARTITION_ERROR_BEFORE_USABLE,
 | 
			
		||||
	PARTITION_ERROR_BEYOND_DEVICE,
 | 
			
		||||
	PARTITION_ERROR_BEYOND_EXTENDED,
 | 
			
		||||
	PARTITION_ERROR_BEYOND_USABLE,
 | 
			
		||||
	PARTITION_ERROR_TOO_EXTENDED,
 | 
			
		||||
	PARTITION_ERROR_BAD_EXTENDED,
 | 
			
		||||
	PARTITION_ERROR_NONLINEAR_EXTENDED,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										105
									
								
								libmount/include/mount/ext2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								libmount/include/mount/ext2.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/ext2.h
 | 
			
		||||
    ext2 filesystem.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_EXT2_H
 | 
			
		||||
#define INCLUDE_MOUNT_EXT2_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
 | 
			
		||||
static const uint16_t EXT2_SUPER_MAGIC = 0xEF53;
 | 
			
		||||
static const uint16_t EXT2_VALID_FS = 1;
 | 
			
		||||
static const uint16_t EXT2_ERROR_FS = 2;
 | 
			
		||||
 | 
			
		||||
struct ext2_superblock
 | 
			
		||||
{
 | 
			
		||||
	uint32_t s_inodes_count;
 | 
			
		||||
	uint32_t s_blocks_count;
 | 
			
		||||
	uint32_t s_r_blocks_count;
 | 
			
		||||
	uint32_t s_free_blocks_count;
 | 
			
		||||
	uint32_t s_free_inodes_count;
 | 
			
		||||
	uint32_t s_first_data_block;
 | 
			
		||||
	uint32_t s_log_block_size;
 | 
			
		||||
	 int32_t s_log_frag_size;
 | 
			
		||||
	uint32_t s_blocks_per_group;
 | 
			
		||||
	uint32_t s_frags_per_group;
 | 
			
		||||
	uint32_t s_inodes_per_group;
 | 
			
		||||
	uint32_t s_mtime;
 | 
			
		||||
	uint32_t s_wtime;
 | 
			
		||||
	uint16_t s_mnt_count;
 | 
			
		||||
	uint16_t s_max_mnt_count;
 | 
			
		||||
	uint16_t s_magic;
 | 
			
		||||
	uint16_t s_state;
 | 
			
		||||
	uint16_t s_errors;
 | 
			
		||||
	uint16_t s_minor_rev_level;
 | 
			
		||||
	uint32_t s_lastcheck;
 | 
			
		||||
	uint32_t s_checkinterval;
 | 
			
		||||
	uint32_t s_creator_os;
 | 
			
		||||
	uint32_t s_rev_level;
 | 
			
		||||
	uint16_t s_def_resuid;
 | 
			
		||||
	uint16_t s_def_resgid;
 | 
			
		||||
// EXT2_DYNAMIC_REV
 | 
			
		||||
	uint32_t s_first_ino;
 | 
			
		||||
	uint16_t s_inode_size;
 | 
			
		||||
	uint16_t s_block_group_nr;
 | 
			
		||||
	uint32_t s_feature_compat;
 | 
			
		||||
	uint32_t s_feature_incompat;
 | 
			
		||||
	uint32_t s_feature_ro_compat;
 | 
			
		||||
	uint8_t  s_uuid[16];
 | 
			
		||||
	/*uint8_t*/ char s_volume_name[16];
 | 
			
		||||
	/*uint8_t*/ char s_last_mounted[64];
 | 
			
		||||
	uint32_t s_algo_bitmap;
 | 
			
		||||
// Performance Hints
 | 
			
		||||
	uint8_t  s_prealloc_blocks;
 | 
			
		||||
	uint8_t  s_prealloc_dir_blocks;
 | 
			
		||||
	uint16_t alignment0;
 | 
			
		||||
// Journaling Support
 | 
			
		||||
	uint8_t  s_journal_uuid[16];
 | 
			
		||||
	uint32_t s_journal_inum;
 | 
			
		||||
	uint32_t s_journal_dev;
 | 
			
		||||
	uint32_t s_last_orphan;
 | 
			
		||||
// Directory Indexing Support
 | 
			
		||||
	uint32_t s_hash_seed[4];
 | 
			
		||||
	uint8_t  s_def_hash_version;
 | 
			
		||||
	uint8_t  alignment1[3];
 | 
			
		||||
// Other options
 | 
			
		||||
	uint32_t s_default_mount_options;
 | 
			
		||||
	uint32_t s_first_meta_bg;
 | 
			
		||||
	uint8_t  alignment2[760];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern const struct filesystem_handler ext2_handler;
 | 
			
		||||
 | 
			
		||||
void ext2_superblock_decode(struct ext2_superblock*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										40
									
								
								libmount/include/mount/extended.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								libmount/include/mount/extended.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/extended.h
 | 
			
		||||
    MBR extended partition.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_EXTENDED_H
 | 
			
		||||
#define INCLUDE_MOUNT_EXTENDED_H
 | 
			
		||||
 | 
			
		||||
#include <mount/filesystem.h>
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern const struct filesystem_handler extended_handler;
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										79
									
								
								libmount/include/mount/filesystem.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								libmount/include/mount/filesystem.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/filesystem.h
 | 
			
		||||
    Filesystem abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_FILESYSTEM_H
 | 
			
		||||
#define INCLUDE_MOUNT_FILESYSTEM_H
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/error.h>
 | 
			
		||||
 | 
			
		||||
struct blockdevice;
 | 
			
		||||
struct filesystem;
 | 
			
		||||
struct filesystem_handler;
 | 
			
		||||
 | 
			
		||||
#define FILESYSTEM_FLAG_UUID (1 << 0)
 | 
			
		||||
#define FILESYSTEM_FLAG_FSCK_SHOULD (1 << 1)
 | 
			
		||||
#define FILESYSTEM_FLAG_FSCK_MUST (1 << 2)
 | 
			
		||||
 | 
			
		||||
struct filesystem
 | 
			
		||||
{
 | 
			
		||||
	struct blockdevice* bdev;
 | 
			
		||||
	const struct filesystem_handler* handler;
 | 
			
		||||
	void* handler_private;
 | 
			
		||||
	const char* fstype_name;
 | 
			
		||||
	const char* fsck;
 | 
			
		||||
	const char* driver;
 | 
			
		||||
	int flags;
 | 
			
		||||
	unsigned char uuid[16];
 | 
			
		||||
	void* user_ctx;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct filesystem_handler
 | 
			
		||||
{
 | 
			
		||||
	const char* handler_name;
 | 
			
		||||
	size_t (*probe_amount)(struct blockdevice*);
 | 
			
		||||
	bool (*probe)(struct blockdevice*, const unsigned char*, size_t);
 | 
			
		||||
	enum filesystem_error (*inspect)(struct filesystem**, struct blockdevice*);
 | 
			
		||||
	void (*release)(struct filesystem*);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const char* filesystem_error_string(enum filesystem_error);
 | 
			
		||||
enum filesystem_error
 | 
			
		||||
blockdevice_inspect_filesystem(struct filesystem**, struct blockdevice*);
 | 
			
		||||
void filesystem_release(struct filesystem*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										93
									
								
								libmount/include/mount/gpt.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								libmount/include/mount/gpt.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/gpt.h
 | 
			
		||||
    GUID Partition Table.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_GPT_H
 | 
			
		||||
#define INCLUDE_MOUNT_GPT_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
struct blockdevice;
 | 
			
		||||
struct partition_table;
 | 
			
		||||
 | 
			
		||||
struct gpt
 | 
			
		||||
{
 | 
			
		||||
	char signature[8];
 | 
			
		||||
	uint32_t revision;
 | 
			
		||||
	uint32_t header_size;
 | 
			
		||||
	uint32_t header_crc32;
 | 
			
		||||
	uint32_t reserved0;
 | 
			
		||||
	uint64_t my_lba;
 | 
			
		||||
	uint64_t alternate_lba;
 | 
			
		||||
	uint64_t first_usable_lba;
 | 
			
		||||
	uint64_t last_usable_lba;
 | 
			
		||||
	unsigned char disk_guid[16];
 | 
			
		||||
	uint64_t partition_entry_lba;
 | 
			
		||||
	uint32_t number_of_partition_entries;
 | 
			
		||||
	uint32_t size_of_partition_entry;
 | 
			
		||||
	uint32_t partition_entry_array_crc32;
 | 
			
		||||
	unsigned char reserved1[420];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(struct gpt) == 512, "sizeof(struct gpt) == 512");
 | 
			
		||||
 | 
			
		||||
#define GPT_PARTITION_NAME_LENGTH 36
 | 
			
		||||
struct gpt_partition
 | 
			
		||||
{
 | 
			
		||||
	unsigned char partition_type_guid[16];
 | 
			
		||||
	unsigned char unique_partition_guid[16];
 | 
			
		||||
	uint64_t starting_lba;
 | 
			
		||||
	uint64_t ending_lba;
 | 
			
		||||
	uint64_t attributes;
 | 
			
		||||
	uint16_t partition_name[GPT_PARTITION_NAME_LENGTH];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(struct gpt_partition) == 128, "sizeof(struct gpt_partition) == 128");
 | 
			
		||||
 | 
			
		||||
struct gpt_partition_table
 | 
			
		||||
{
 | 
			
		||||
	struct gpt gpt;
 | 
			
		||||
	unsigned char* rpt;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void gpt_decode(struct gpt*);
 | 
			
		||||
void gpt_encode(struct gpt*);
 | 
			
		||||
void gpt_partition_decode(struct gpt_partition*);
 | 
			
		||||
void gpt_partition_encode(struct gpt_partition*);
 | 
			
		||||
char* gpt_decode_utf16(uint16_t* string, size_t length);
 | 
			
		||||
uint32_t gpt_crc32(const void*, size_t);
 | 
			
		||||
void gpt_partition_table_release(struct gpt_partition_table*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										65
									
								
								libmount/include/mount/harddisk.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								libmount/include/mount/harddisk.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,65 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/harddisk.h
 | 
			
		||||
    Harddisk abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_HARDDISK_H
 | 
			
		||||
#define INCLUDE_MOUNT_HARDDISK_H
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
 | 
			
		||||
struct harddisk
 | 
			
		||||
{
 | 
			
		||||
	struct blockdevice bdev;
 | 
			
		||||
	struct stat st;
 | 
			
		||||
	int fd;
 | 
			
		||||
	char* path;
 | 
			
		||||
	char* driver;
 | 
			
		||||
	char* model;
 | 
			
		||||
	char* serial;
 | 
			
		||||
	blksize_t logical_block_size;
 | 
			
		||||
	uint16_t cylinders;
 | 
			
		||||
	uint16_t heads;
 | 
			
		||||
	uint16_t sectors;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct harddisk* harddisk_openat(int, const char*, int);
 | 
			
		||||
bool harddisk_inspect_blockdevice(struct harddisk*);
 | 
			
		||||
void harddisk_close(struct harddisk*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										86
									
								
								libmount/include/mount/mbr.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								libmount/include/mount/mbr.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/mbr.h
 | 
			
		||||
    Master Boot Record.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_MBR_H
 | 
			
		||||
#define INCLUDE_MOUNT_MBR_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
struct blockdevice;
 | 
			
		||||
struct partition_table;
 | 
			
		||||
 | 
			
		||||
struct mbr_partition
 | 
			
		||||
{
 | 
			
		||||
	uint8_t flags;
 | 
			
		||||
	uint8_t start_head;
 | 
			
		||||
	uint16_t start_sector_cylinder;
 | 
			
		||||
	uint8_t system_id;
 | 
			
		||||
	uint8_t end_head;
 | 
			
		||||
	uint16_t end_sector_cylinder;
 | 
			
		||||
	uint32_t start_sector;
 | 
			
		||||
	uint32_t total_sectors;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(struct mbr_partition) == 16, "sizeof(struct mbr_partition) == 16");
 | 
			
		||||
 | 
			
		||||
struct mbr
 | 
			
		||||
{
 | 
			
		||||
	uint8_t bootstrap[446];
 | 
			
		||||
	unsigned char partitions[4][16];
 | 
			
		||||
	uint8_t signature[2];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static_assert(sizeof(struct mbr) == 512, "sizeof(struct mbr) == 512");
 | 
			
		||||
 | 
			
		||||
struct mbr_ebr_link
 | 
			
		||||
{
 | 
			
		||||
	struct mbr ebr;
 | 
			
		||||
	off_t offset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mbr_partition_table
 | 
			
		||||
{
 | 
			
		||||
	struct mbr mbr;
 | 
			
		||||
	size_t ebr_chain_count;
 | 
			
		||||
	struct mbr_ebr_link* ebr_chain;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool mbr_is_partition_used(const struct mbr_partition* partition);
 | 
			
		||||
void mbr_partition_decode(struct mbr_partition*);
 | 
			
		||||
void mbr_partition_encode(struct mbr_partition*);
 | 
			
		||||
void mbr_partition_table_release(struct mbr_partition_table*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										109
									
								
								libmount/include/mount/partition.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								libmount/include/mount/partition.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/partition.h
 | 
			
		||||
    Partition abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_PARTITION_H
 | 
			
		||||
#define INCLUDE_MOUNT_PARTITION_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/error.h>
 | 
			
		||||
 | 
			
		||||
enum partition_type
 | 
			
		||||
{
 | 
			
		||||
	PARTITION_TYPE_PRIMARY,
 | 
			
		||||
	PARTITION_TYPE_EXTENDED,
 | 
			
		||||
	PARTITION_TYPE_LOGICAL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum partition_table_type
 | 
			
		||||
{
 | 
			
		||||
	PARTITION_TABLE_TYPE_NONE,
 | 
			
		||||
	PARTITION_TABLE_TYPE_UNKNOWN,
 | 
			
		||||
	PARTITION_TABLE_TYPE_MBR,
 | 
			
		||||
	PARTITION_TABLE_TYPE_GPT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct partition
 | 
			
		||||
{
 | 
			
		||||
	struct blockdevice bdev;
 | 
			
		||||
	struct blockdevice* parent_bdev;
 | 
			
		||||
	char* path;
 | 
			
		||||
	off_t start;
 | 
			
		||||
	off_t length;
 | 
			
		||||
	off_t extended_start;
 | 
			
		||||
	off_t extended_length;
 | 
			
		||||
	enum partition_type type;
 | 
			
		||||
	enum partition_table_type table_type;
 | 
			
		||||
	unsigned int index;
 | 
			
		||||
	unsigned char gpt_type_guid[16];
 | 
			
		||||
	unsigned char gpt_unique_guid[16];
 | 
			
		||||
	unsigned char mbr_system_id;
 | 
			
		||||
	char* gpt_name;
 | 
			
		||||
	uint64_t gpt_attributes;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct partition_table
 | 
			
		||||
{
 | 
			
		||||
	enum partition_table_type type;
 | 
			
		||||
	struct partition** partitions;
 | 
			
		||||
	size_t partitions_count;
 | 
			
		||||
	enum partition_error error;
 | 
			
		||||
	unsigned char gpt_disk_guid[16];
 | 
			
		||||
	void* raw_partition_table;
 | 
			
		||||
	off_t usable_start;
 | 
			
		||||
	off_t usable_end;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int partition_compare_index(const struct partition*, const struct partition*);
 | 
			
		||||
int partition_compare_index_indirect(const void*, const void*);
 | 
			
		||||
int partition_compare_start(const struct partition*, const struct partition*);
 | 
			
		||||
int partition_compare_start_indirect(const void*, const void*);
 | 
			
		||||
const char* partition_error_string(enum partition_error);
 | 
			
		||||
bool partition_check_overlap(const struct partition*, off_t, off_t);
 | 
			
		||||
void partition_release(struct partition*);
 | 
			
		||||
bool blockdevice_probe_partition_table_type(enum partition_table_type*, struct blockdevice*);
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table(struct partition_table**, struct blockdevice*);
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table_mbr(struct partition_table**, struct blockdevice*);
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table_gpt(struct partition_table**, struct blockdevice*);
 | 
			
		||||
void partition_table_release(struct partition_table*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										46
									
								
								libmount/include/mount/uuid.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libmount/include/mount/uuid.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mount/uuid.h
 | 
			
		||||
    Universally unique identifier.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef INCLUDE_MOUNT_UUID_H
 | 
			
		||||
#define INCLUDE_MOUNT_UUID_H
 | 
			
		||||
 | 
			
		||||
#if !defined(__cplusplus)
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define UUID_STRING_LENGTH 36 /* and of course a nul byte not included here */
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool uuid_validate(const char*);
 | 
			
		||||
void uuid_from_string(unsigned char[16], const char*);
 | 
			
		||||
void uuid_to_string(const unsigned char[16], char*);
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
} /* extern "C" */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										270
									
								
								libmount/mbr.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								libmount/mbr.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,270 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    mbr.c
 | 
			
		||||
    Master Boot Record.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/harddisk.h>
 | 
			
		||||
#include <mount/mbr.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
void mbr_partition_decode(struct mbr_partition* v)
 | 
			
		||||
{
 | 
			
		||||
	// flags is endian agnostic.
 | 
			
		||||
	// start_head is endian agnostic.
 | 
			
		||||
	v->start_sector_cylinder = le16toh(v->start_sector_cylinder);
 | 
			
		||||
	v->end_sector_cylinder = le16toh(v->end_sector_cylinder);
 | 
			
		||||
	// system_id is endian agnostic.
 | 
			
		||||
	// end_head is endian agnostic.
 | 
			
		||||
	v->start_sector = le32toh(v->start_sector);
 | 
			
		||||
	v->total_sectors = le32toh(v->total_sectors);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbr_partition_encode(struct mbr_partition* v)
 | 
			
		||||
{
 | 
			
		||||
	v->start_sector_cylinder = htole16(v->start_sector_cylinder);
 | 
			
		||||
	v->end_sector_cylinder = htole16(v->end_sector_cylinder);
 | 
			
		||||
	// flags is endian agnostic.
 | 
			
		||||
	// start_head is endian agnostic.
 | 
			
		||||
	v->start_sector = htole32(v->start_sector);
 | 
			
		||||
	v->total_sectors = htole32(v->total_sectors);
 | 
			
		||||
	// system_id is endian agnostic.
 | 
			
		||||
	// end_head is endian agnostic.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbr_partition_table_release(struct mbr_partition_table* pt)
 | 
			
		||||
{
 | 
			
		||||
	if ( !pt )
 | 
			
		||||
		return;
 | 
			
		||||
	free(pt->ebr_chain);
 | 
			
		||||
	free(pt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool mbr_is_extended_partition(const struct mbr_partition* partition)
 | 
			
		||||
{
 | 
			
		||||
	return partition->system_id == 0x05 || // CHS addressing.
 | 
			
		||||
	       partition->system_id == 0x0F;   // LBA addressing.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool mbr_is_partition_used(const struct mbr_partition* partition)
 | 
			
		||||
{
 | 
			
		||||
	if ( memiszero(partition, sizeof(*partition)) )
 | 
			
		||||
		return false;
 | 
			
		||||
	if ( !partition->system_id ||
 | 
			
		||||
	     !partition->total_sectors )
 | 
			
		||||
		return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table_mbr(struct partition_table** pt_ptr,
 | 
			
		||||
                                    struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	*pt_ptr = NULL;
 | 
			
		||||
	blksize_t logical_block_size = blockdevice_logical_block_size(bdev);
 | 
			
		||||
	if ( !blockdevice_check_reasonable_block_size(logical_block_size) )
 | 
			
		||||
		return errno = EINVAL, PARTITION_ERROR_ERRNO;
 | 
			
		||||
	off_t device_size = blockdevice_size(bdev);
 | 
			
		||||
	const char* device_path = bdev->p ? bdev->p->path : bdev->hd->path;
 | 
			
		||||
 | 
			
		||||
	struct mbr mbr;
 | 
			
		||||
	if ( blockdevice_preadall(bdev, &mbr, sizeof(mbr), 0) != sizeof(mbr) )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
 | 
			
		||||
	if ( mbr.signature[0] != 0x55 && mbr.signature[1] != 0xAA )
 | 
			
		||||
		return errno = EINVAL, PARTITION_ERROR_ERRNO;
 | 
			
		||||
 | 
			
		||||
	struct partition_table* pt = CALLOC_TYPE(struct partition_table);
 | 
			
		||||
	if ( !pt )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	*pt_ptr = pt;
 | 
			
		||||
	pt->type = PARTITION_TABLE_TYPE_MBR;
 | 
			
		||||
	size_t pt__partitions_length = 0;
 | 
			
		||||
	pt->usable_start = logical_block_size;
 | 
			
		||||
	off_t last_sector = device_size / logical_block_size;
 | 
			
		||||
	if ( UINT32_MAX + 1LL < last_sector )
 | 
			
		||||
		last_sector = UINT32_MAX + 1LL;
 | 
			
		||||
	pt->usable_end = last_sector * logical_block_size;
 | 
			
		||||
 | 
			
		||||
	struct mbr_partition_table* mbrpt = CALLOC_TYPE(struct mbr_partition_table);
 | 
			
		||||
	if ( !mbrpt )
 | 
			
		||||
		return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	pt->raw_partition_table = mbrpt;
 | 
			
		||||
	memcpy(&mbrpt->mbr, &mbr, sizeof(mbr));
 | 
			
		||||
 | 
			
		||||
	unsigned int extended_partition_count = 0;
 | 
			
		||||
	for ( unsigned int i = 0; i < 4; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		struct mbr_partition pmbr;
 | 
			
		||||
		memcpy(&pmbr, mbr.partitions[i], sizeof(pmbr));
 | 
			
		||||
		mbr_partition_decode(&pmbr);
 | 
			
		||||
		if ( mbr_is_partition_used(&pmbr) && mbr_is_extended_partition(&pmbr) )
 | 
			
		||||
			extended_partition_count++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ( 2 <= extended_partition_count ) // Violates assumptions.
 | 
			
		||||
		return PARTITION_ERROR_TOO_EXTENDED;
 | 
			
		||||
 | 
			
		||||
	for ( unsigned int i = 0; i < 4; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		struct mbr_partition pmbr;
 | 
			
		||||
		memcpy(&pmbr, mbr.partitions[i], sizeof(pmbr));
 | 
			
		||||
		mbr_partition_decode(&pmbr);
 | 
			
		||||
		if ( !mbr_is_partition_used(&pmbr) )
 | 
			
		||||
			continue;
 | 
			
		||||
		// TODO: Potential overflow.
 | 
			
		||||
		if ( pmbr.start_sector == 0 )
 | 
			
		||||
			return PARTITION_ERROR_BEFORE_USABLE;
 | 
			
		||||
		off_t start = (off_t) pmbr.start_sector * (off_t) logical_block_size;
 | 
			
		||||
		off_t length = (off_t) pmbr.total_sectors * (off_t) logical_block_size;
 | 
			
		||||
		if ( device_size < start || device_size - start < length )
 | 
			
		||||
			return PARTITION_ERROR_BEYOND_DEVICE;
 | 
			
		||||
		for ( size_t j = 0; j < pt->partitions_count; j++ )
 | 
			
		||||
			if ( partition_check_overlap(pt->partitions[j], start, length) )
 | 
			
		||||
				return PARTITION_ERROR_OVERLAP;
 | 
			
		||||
		struct partition* p = CALLOC_TYPE(struct partition);
 | 
			
		||||
		if ( !p )
 | 
			
		||||
			return PARTITION_ERROR_ERRNO;
 | 
			
		||||
		memset(&p->bdev, 0, sizeof(p->bdev));
 | 
			
		||||
		p->bdev.p = p;
 | 
			
		||||
		p->parent_bdev = bdev;
 | 
			
		||||
		p->index = 1 + i;
 | 
			
		||||
		p->start = start;
 | 
			
		||||
		p->length = length;
 | 
			
		||||
		p->type = PARTITION_TYPE_PRIMARY;
 | 
			
		||||
		if ( mbr_is_extended_partition(&pmbr) )
 | 
			
		||||
		{
 | 
			
		||||
			p->extended_start = start;
 | 
			
		||||
			p->extended_length = length;
 | 
			
		||||
			p->type = PARTITION_TYPE_EXTENDED;
 | 
			
		||||
		}
 | 
			
		||||
		p->table_type = PARTITION_TABLE_TYPE_MBR;
 | 
			
		||||
		p->mbr_system_id = pmbr.system_id;
 | 
			
		||||
		if ( !array_add((void***) &pt->partitions,
 | 
			
		||||
		                &pt->partitions_count,
 | 
			
		||||
		                &pt__partitions_length,
 | 
			
		||||
		                p) )
 | 
			
		||||
			return free(p), PARTITION_ERROR_ERRNO;
 | 
			
		||||
		if ( device_path &&
 | 
			
		||||
		     asprintf(&p->path, "%sp%u", device_path, p->index) < 0 )
 | 
			
		||||
			return PARTITION_ERROR_ERRNO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for ( unsigned int i = 0; i < 4; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		struct mbr_partition pextmbr;
 | 
			
		||||
		memcpy(&pextmbr, mbr.partitions[i], sizeof(pextmbr));
 | 
			
		||||
		mbr_partition_decode(&pextmbr);
 | 
			
		||||
		if ( !mbr_is_partition_used(&pextmbr) )
 | 
			
		||||
			continue;
 | 
			
		||||
		if ( !mbr_is_extended_partition(&pextmbr) )
 | 
			
		||||
			continue;
 | 
			
		||||
		// TODO: Potential overflow.
 | 
			
		||||
		off_t pext_start = (off_t) pextmbr.start_sector * (off_t) logical_block_size;
 | 
			
		||||
		off_t pext_length = (off_t) pextmbr.total_sectors * (off_t) logical_block_size;
 | 
			
		||||
		off_t ebr_rel = 0;
 | 
			
		||||
		unsigned int j = 0;
 | 
			
		||||
		while ( true )
 | 
			
		||||
		{
 | 
			
		||||
			struct mbr ebr;
 | 
			
		||||
			if ( pext_length <= ebr_rel )
 | 
			
		||||
				return PARTITION_ERROR_BEYOND_EXTENDED;
 | 
			
		||||
			off_t ebr_off = pext_start + ebr_rel;
 | 
			
		||||
			if ( blockdevice_preadall(bdev, &ebr, sizeof(ebr), ebr_off) != sizeof(ebr) )
 | 
			
		||||
				return PARTITION_ERROR_ERRNO;
 | 
			
		||||
			if ( ebr.signature[0] != 0x55 && ebr.signature[1] != 0xAA )
 | 
			
		||||
				return PARTITION_ERROR_BAD_EXTENDED;
 | 
			
		||||
			size_t new_chain_count = mbrpt->ebr_chain_count + 1;
 | 
			
		||||
			size_t chain_size = sizeof(struct mbr_ebr_link) * new_chain_count;
 | 
			
		||||
			struct mbr_ebr_link* new_chain =
 | 
			
		||||
				(struct mbr_ebr_link*) realloc(mbrpt->ebr_chain, chain_size);
 | 
			
		||||
			if ( !new_chain )
 | 
			
		||||
				return PARTITION_ERROR_ERRNO;
 | 
			
		||||
			mbrpt->ebr_chain = new_chain;
 | 
			
		||||
			mbrpt->ebr_chain_count = new_chain_count;
 | 
			
		||||
			memcpy(&mbrpt->ebr_chain[j].ebr, &ebr, sizeof(ebr));
 | 
			
		||||
			mbrpt->ebr_chain[j].offset = ebr_off;
 | 
			
		||||
			struct mbr_partition pmbr;
 | 
			
		||||
			memcpy(&pmbr, ebr.partitions[0], sizeof(pmbr));
 | 
			
		||||
			mbr_partition_decode(&pmbr);
 | 
			
		||||
			if ( mbr_is_partition_used(&pmbr) )
 | 
			
		||||
			{
 | 
			
		||||
				// TODO: Potential overflow.
 | 
			
		||||
				off_t start = (off_t) pmbr.start_sector * (off_t) logical_block_size;
 | 
			
		||||
				off_t length = (off_t) pmbr.total_sectors * (off_t) logical_block_size;
 | 
			
		||||
				if ( pext_length - ebr_rel < start )
 | 
			
		||||
					return PARTITION_ERROR_BEYOND_EXTENDED;
 | 
			
		||||
				off_t max_length = (pext_length - ebr_rel) - start;
 | 
			
		||||
				if ( max_length < length )
 | 
			
		||||
					return PARTITION_ERROR_BEYOND_EXTENDED;
 | 
			
		||||
				struct partition* p = CALLOC_TYPE(struct partition);
 | 
			
		||||
				if ( !p )
 | 
			
		||||
					return PARTITION_ERROR_ERRNO;
 | 
			
		||||
				memset(&p->bdev, 0, sizeof(p->bdev));
 | 
			
		||||
				p->bdev.p = p;
 | 
			
		||||
				p->parent_bdev = bdev;
 | 
			
		||||
				p->index = 5 + j;
 | 
			
		||||
				p->start = ebr_off + start;
 | 
			
		||||
				p->length = length;
 | 
			
		||||
				p->type = PARTITION_TYPE_LOGICAL;
 | 
			
		||||
				p->table_type = PARTITION_TABLE_TYPE_MBR;
 | 
			
		||||
				p->mbr_system_id = pmbr.system_id;
 | 
			
		||||
				if ( !array_add((void***) &pt->partitions,
 | 
			
		||||
						        &pt->partitions_count,
 | 
			
		||||
						        &pt__partitions_length,
 | 
			
		||||
						        p) )
 | 
			
		||||
					return free(p), PARTITION_ERROR_ERRNO;
 | 
			
		||||
				if ( device_path &&
 | 
			
		||||
				     asprintf(&p->path, "%sp%u", device_path, p->index) < 0 )
 | 
			
		||||
					return PARTITION_ERROR_ERRNO;
 | 
			
		||||
			}
 | 
			
		||||
			j++;
 | 
			
		||||
			struct mbr_partition next;
 | 
			
		||||
			memcpy(&next, ebr.partitions[1], sizeof(next));
 | 
			
		||||
			mbr_partition_decode(&next);
 | 
			
		||||
			// TODO: Potential overflow.
 | 
			
		||||
			off_t next_rel = (off_t) next.start_sector * (off_t) logical_block_size;
 | 
			
		||||
			if ( !next_rel )
 | 
			
		||||
				break;
 | 
			
		||||
			if ( next_rel <= ebr_rel ) // Violates assumptions.
 | 
			
		||||
				return PARTITION_ERROR_NONLINEAR_EXTENDED;
 | 
			
		||||
			if ( pext_length <= next_rel )
 | 
			
		||||
				return PARTITION_ERROR_BEYOND_EXTENDED;
 | 
			
		||||
			ebr_rel = next_rel;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return PARTITION_ERROR_NONE;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										238
									
								
								libmount/partition.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								libmount/partition.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,238 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    partition.c
 | 
			
		||||
    Partition abstraction.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/blockdevice.h>
 | 
			
		||||
#include <mount/gpt.h>
 | 
			
		||||
#include <mount/mbr.h>
 | 
			
		||||
#include <mount/partition.h>
 | 
			
		||||
 | 
			
		||||
#include "util.h"
 | 
			
		||||
 | 
			
		||||
int partition_compare_index(const struct partition* a, const struct partition* b)
 | 
			
		||||
{
 | 
			
		||||
	if ( a->index < b->index )
 | 
			
		||||
		return -1;
 | 
			
		||||
	if ( b->index < a->index )
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int partition_compare_index_indirect(const void* a_ptr, const void* b_ptr)
 | 
			
		||||
{
 | 
			
		||||
	const struct partition* a = *(const struct partition* const*) a_ptr;
 | 
			
		||||
	const struct partition* b = *(const struct partition* const*) b_ptr;
 | 
			
		||||
	return partition_compare_index(a, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int partition_compare_start(const struct partition* a, const struct partition* b)
 | 
			
		||||
{
 | 
			
		||||
	if ( a->start < b->start )
 | 
			
		||||
		return -1;
 | 
			
		||||
	if ( b->start < a->start )
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int partition_compare_start_indirect(const void* a_ptr, const void* b_ptr)
 | 
			
		||||
{
 | 
			
		||||
	const struct partition* a = *(const struct partition* const*) a_ptr;
 | 
			
		||||
	const struct partition* b = *(const struct partition* const*) b_ptr;
 | 
			
		||||
	return partition_compare_index(a, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* partition_error_string(enum partition_error error)
 | 
			
		||||
{
 | 
			
		||||
	switch ( error )
 | 
			
		||||
	{
 | 
			
		||||
	case PARTITION_ERROR_NONE:
 | 
			
		||||
		break;
 | 
			
		||||
	case PARTITION_ERROR_ABSENT:
 | 
			
		||||
		return "No partition table found";
 | 
			
		||||
	case PARTITION_ERROR_UNRECOGNIZED:
 | 
			
		||||
		return "Unrecognized partitioning scheme";
 | 
			
		||||
	case PARTITION_ERROR_ERRNO:
 | 
			
		||||
		return (const char*) strerror(errno);
 | 
			
		||||
	case PARTITION_ERROR_INVALID:
 | 
			
		||||
		return "Invalid partition table";
 | 
			
		||||
	case PARTITION_ERROR_HEADER_TOO_LARGE:
 | 
			
		||||
		return "Partition table header larger than logical sector size";
 | 
			
		||||
	case PARTITION_ERROR_CHECKSUM:
 | 
			
		||||
		return "Partition table does not match its checksum";
 | 
			
		||||
	case PARTITION_ERROR_OVERLAP:
 | 
			
		||||
		return "Partition table contains overlapping partitions";
 | 
			
		||||
	case PARTITION_ERROR_END_BEFORE_START:
 | 
			
		||||
		return "Invalid partition ends before its start";
 | 
			
		||||
	case PARTITION_ERROR_BEFORE_USABLE:
 | 
			
		||||
		return "Invalid partition begins before the usable region";
 | 
			
		||||
	case PARTITION_ERROR_BEYOND_DEVICE:
 | 
			
		||||
		return "Invalid partition exceeds device";
 | 
			
		||||
	case PARTITION_ERROR_BEYOND_EXTENDED:
 | 
			
		||||
		return "Invalid logical partition exceeds its extended partition";
 | 
			
		||||
	case PARTITION_ERROR_BEYOND_USABLE:
 | 
			
		||||
		return "Invalid partition ends after the usable region";
 | 
			
		||||
	case PARTITION_ERROR_TOO_EXTENDED:
 | 
			
		||||
		return "Bad partition table (more than one extended partition)";
 | 
			
		||||
	case PARTITION_ERROR_BAD_EXTENDED:
 | 
			
		||||
		return "Bad extended partition";
 | 
			
		||||
	case PARTITION_ERROR_NONLINEAR_EXTENDED:
 | 
			
		||||
		return "Extended partition is not linearly linked together";
 | 
			
		||||
	}
 | 
			
		||||
	return "Unknown error condition";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool partition_check_overlap(const struct partition* partition,
 | 
			
		||||
                             off_t start,
 | 
			
		||||
                             off_t length)
 | 
			
		||||
{
 | 
			
		||||
	assert(0 <= start);
 | 
			
		||||
	assert(0 <= length);
 | 
			
		||||
	assert(0 <= partition->start);
 | 
			
		||||
	assert(0 <= partition->length);
 | 
			
		||||
	if ( start <= partition->start )
 | 
			
		||||
	{
 | 
			
		||||
		off_t max_length = partition->start - start;
 | 
			
		||||
		return max_length < length;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		off_t max_length = start - partition->start;
 | 
			
		||||
		return max_length < partition->length;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool blockdevice_probe_partition_table_type(enum partition_table_type* result_out,
 | 
			
		||||
                                            struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	blksize_t logical_block_size = blockdevice_logical_block_size(bdev);
 | 
			
		||||
	if ( !blockdevice_check_reasonable_block_size(logical_block_size) )
 | 
			
		||||
		return errno = EINVAL, false;
 | 
			
		||||
 | 
			
		||||
	// TODO: Overflow checks for truncation, and the multiplication.
 | 
			
		||||
	size_t block_size = logical_block_size;
 | 
			
		||||
	size_t leading_size = 2 * block_size;
 | 
			
		||||
	unsigned char* leading = (unsigned char*) malloc(leading_size);
 | 
			
		||||
	if ( !leading )
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	size_t amount = blockdevice_preadall(bdev, leading, leading_size, 0);
 | 
			
		||||
	if ( amount < leading_size && errno != EEOF )
 | 
			
		||||
		return free(leading), false;
 | 
			
		||||
 | 
			
		||||
	enum partition_table_type result = PARTITION_TABLE_TYPE_NONE;
 | 
			
		||||
 | 
			
		||||
	do if ( 2*block_size <= amount )
 | 
			
		||||
	{
 | 
			
		||||
		struct gpt gpt;
 | 
			
		||||
		memcpy(&gpt, leading + 1 * block_size, sizeof(gpt));
 | 
			
		||||
		gpt_decode(&gpt);
 | 
			
		||||
		if ( memcmp(gpt.signature, "EFI PART", 8) != 0 )
 | 
			
		||||
			break;
 | 
			
		||||
		result = PARTITION_TABLE_TYPE_GPT;
 | 
			
		||||
		goto out;
 | 
			
		||||
	} while ( 0 );
 | 
			
		||||
 | 
			
		||||
	do if ( sizeof(struct mbr) <= amount )
 | 
			
		||||
	{
 | 
			
		||||
		struct mbr mbr;
 | 
			
		||||
		memcpy(&mbr, leading, sizeof(mbr));
 | 
			
		||||
		if ( mbr.signature[0] != 0x55 && mbr.signature[1] != 0xAA )
 | 
			
		||||
			break;
 | 
			
		||||
		result = PARTITION_TABLE_TYPE_MBR;
 | 
			
		||||
		goto out;
 | 
			
		||||
	} while ( 0 );
 | 
			
		||||
 | 
			
		||||
	for ( size_t i = 0; i < leading_size; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		if ( leading[i] == 0x00 )
 | 
			
		||||
			continue;
 | 
			
		||||
		result = PARTITION_TABLE_TYPE_UNKNOWN;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	free(leading);
 | 
			
		||||
	return *result_out = result, true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum partition_error
 | 
			
		||||
blockdevice_get_partition_table(struct partition_table** pt_ptr,
 | 
			
		||||
                                struct blockdevice* bdev)
 | 
			
		||||
{
 | 
			
		||||
	enum partition_table_type pt_type;
 | 
			
		||||
	if ( !blockdevice_probe_partition_table_type(&pt_type, bdev) )
 | 
			
		||||
		return *pt_ptr = NULL, PARTITION_ERROR_ERRNO;
 | 
			
		||||
	switch ( pt_type )
 | 
			
		||||
	{
 | 
			
		||||
	case PARTITION_TABLE_TYPE_NONE:
 | 
			
		||||
		return *pt_ptr = NULL, PARTITION_ERROR_ABSENT;
 | 
			
		||||
	case PARTITION_TABLE_TYPE_UNKNOWN:
 | 
			
		||||
		break;
 | 
			
		||||
	case PARTITION_TABLE_TYPE_MBR:
 | 
			
		||||
		return blockdevice_get_partition_table_mbr(pt_ptr, bdev);
 | 
			
		||||
	case PARTITION_TABLE_TYPE_GPT:
 | 
			
		||||
		return blockdevice_get_partition_table_gpt(pt_ptr, bdev);
 | 
			
		||||
	}
 | 
			
		||||
	return *pt_ptr = NULL, PARTITION_ERROR_UNRECOGNIZED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void partition_release(struct partition* p)
 | 
			
		||||
{
 | 
			
		||||
	if ( !p )
 | 
			
		||||
		return;
 | 
			
		||||
	free(p->gpt_name);
 | 
			
		||||
	free(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void partition_table_release(struct partition_table* pt)
 | 
			
		||||
{
 | 
			
		||||
	if ( !pt )
 | 
			
		||||
		return;
 | 
			
		||||
	switch ( pt->type )
 | 
			
		||||
	{
 | 
			
		||||
	case PARTITION_TABLE_TYPE_NONE: break;
 | 
			
		||||
	case PARTITION_TABLE_TYPE_UNKNOWN: break;
 | 
			
		||||
	case PARTITION_TABLE_TYPE_MBR:
 | 
			
		||||
		mbr_partition_table_release(
 | 
			
		||||
			(struct mbr_partition_table*) pt->raw_partition_table);
 | 
			
		||||
		break;
 | 
			
		||||
	case PARTITION_TABLE_TYPE_GPT:
 | 
			
		||||
		gpt_partition_table_release(
 | 
			
		||||
			(struct gpt_partition_table*) pt->raw_partition_table);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	for ( size_t i = 0; i < pt->partitions_count; i++ )
 | 
			
		||||
		partition_release(pt->partitions[i]);
 | 
			
		||||
	free(pt->partitions);
 | 
			
		||||
	free(pt);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								libmount/util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								libmount/util.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    util.h
 | 
			
		||||
    Utility functions.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifndef UTIL_H
 | 
			
		||||
#define UTIL_H
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#define MALLOC_TYPE(type) (type*) malloc(sizeof(type))
 | 
			
		||||
#define CALLOC_TYPE(type) (type*) calloc(1, sizeof(type))
 | 
			
		||||
 | 
			
		||||
__attribute__((unused))
 | 
			
		||||
static bool memiszero(const void* mem, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	const unsigned char* buf = (const unsigned char*) mem;
 | 
			
		||||
	for ( size_t i = 0; i < size; i++ )
 | 
			
		||||
		if ( buf[i] )
 | 
			
		||||
			return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((unused))
 | 
			
		||||
static bool array_add(void*** array_ptr,
 | 
			
		||||
                      size_t* used_ptr,
 | 
			
		||||
                      size_t* length_ptr,
 | 
			
		||||
                      void* value)
 | 
			
		||||
{
 | 
			
		||||
	void** array;
 | 
			
		||||
	memcpy(&array, array_ptr, sizeof(array)); // Strict aliasing.
 | 
			
		||||
 | 
			
		||||
	if ( *used_ptr == *length_ptr )
 | 
			
		||||
	{
 | 
			
		||||
		// TODO: Avoid overflow.
 | 
			
		||||
		size_t new_length = 2 * *length_ptr;
 | 
			
		||||
		if ( !new_length )
 | 
			
		||||
			new_length = 16;
 | 
			
		||||
		// TODO: Avoid overflow and use reallocarray.
 | 
			
		||||
		size_t new_size = new_length * sizeof(void*);
 | 
			
		||||
		void** new_array = (void**) realloc(array, new_size);
 | 
			
		||||
		if ( !new_array )
 | 
			
		||||
			return false;
 | 
			
		||||
		array = new_array;
 | 
			
		||||
		memcpy(array_ptr, &array, sizeof(array)); // Strict aliasing.
 | 
			
		||||
		*length_ptr = new_length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memcpy(array + (*used_ptr)++, &value, sizeof(value)); // Strict aliasing.
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										125
									
								
								libmount/uuid.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								libmount/uuid.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,125 @@
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 | 
			
		||||
    Copyright(C) Jonas 'Sortie' Termansen 2015.
 | 
			
		||||
 | 
			
		||||
    This file is part of Sortix libmount.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount is free software: you can redistribute it and/or modify it
 | 
			
		||||
    under the terms of the GNU Lesser General Public License as published by the
 | 
			
		||||
    Free Software Foundation, either version 3 of the License, or (at your
 | 
			
		||||
    option) any later version.
 | 
			
		||||
 | 
			
		||||
    Sortix libmount 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 Lesser General Public
 | 
			
		||||
    License for more details.
 | 
			
		||||
 | 
			
		||||
    You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
    along with Sortix libmount. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
    uuid.c
 | 
			
		||||
    Universally unique identifier.
 | 
			
		||||
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <mount/uuid.h>
 | 
			
		||||
 | 
			
		||||
static bool is_hex_digit(char c)
 | 
			
		||||
{
 | 
			
		||||
	return ('0' <= c && c <= '9') ||
 | 
			
		||||
	       ('a' <= c && c <= 'f') ||
 | 
			
		||||
	       ('A' <= c && c <= 'F');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char base(unsigned char bit4)
 | 
			
		||||
{
 | 
			
		||||
	return "0123456789abcdef"[bit4];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned char debase(char c)
 | 
			
		||||
{
 | 
			
		||||
	if ( '0' <= c && c <= '9' )
 | 
			
		||||
		return (unsigned char) (c - '0');
 | 
			
		||||
	if ( 'a' <= c && c <= 'f' )
 | 
			
		||||
		return (unsigned char) (c - 'a' + 10);
 | 
			
		||||
	if ( 'A' <= c && c <= 'F' )
 | 
			
		||||
		return (unsigned char) (c - 'A' + 10);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool uuid_validate(const char* uuid)
 | 
			
		||||
{
 | 
			
		||||
	// Format: 01234567-0123-0123-0123-0123456789AB
 | 
			
		||||
	if ( strlen(uuid) != 36 )
 | 
			
		||||
		return false;
 | 
			
		||||
	for ( size_t i = 0; i < 36; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		if ( i == 8 || i == 13 || i == 18 || i == 23 )
 | 
			
		||||
		{
 | 
			
		||||
			if ( uuid[i] != '-' )
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			if ( !is_hex_digit(uuid[i]) )
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void uuid_from_string(unsigned char uuid[16], const char* string)
 | 
			
		||||
{
 | 
			
		||||
	size_t output_index = 0;
 | 
			
		||||
	size_t i = 0;
 | 
			
		||||
	while ( i < 36 )
 | 
			
		||||
	{
 | 
			
		||||
		assert(string[i + 0] != '\0');
 | 
			
		||||
		if ( i == 8 || i == 13 || i == 18 || i == 23 )
 | 
			
		||||
		{
 | 
			
		||||
			i++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		uuid[output_index++] = debase(string[i + 0]) << 4 |
 | 
			
		||||
		                       debase(string[i + 1]) << 0;
 | 
			
		||||
		i += 2;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void uuid_to_string(const unsigned char uuid[16], char* string)
 | 
			
		||||
{
 | 
			
		||||
	for ( size_t i = 0; i < 4; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		*string++ = base((uuid[i] >> 4) & 0xF);
 | 
			
		||||
		*string++ = base((uuid[i] >> 0) & 0xF);
 | 
			
		||||
	}
 | 
			
		||||
	*string++ = '-';
 | 
			
		||||
	for ( size_t i = 4; i < 6; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		*string++ = base((uuid[i] >> 4) & 0xF);
 | 
			
		||||
		*string++ = base((uuid[i] >> 0) & 0xF);
 | 
			
		||||
	}
 | 
			
		||||
	*string++ = '-';
 | 
			
		||||
	for ( size_t i = 6; i < 8; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		*string++ = base((uuid[i] >> 4) & 0xF);
 | 
			
		||||
		*string++ = base((uuid[i] >> 0) & 0xF);
 | 
			
		||||
	}
 | 
			
		||||
	*string++ = '-';
 | 
			
		||||
	for ( size_t i = 8; i < 10; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		*string++ = base((uuid[i] >> 4) & 0xF);
 | 
			
		||||
		*string++ = base((uuid[i] >> 0) & 0xF);
 | 
			
		||||
	}
 | 
			
		||||
	*string++ = '-';
 | 
			
		||||
	for ( size_t i = 10; i < 16; i++ )
 | 
			
		||||
	{
 | 
			
		||||
		*string++ = base((uuid[i] >> 4) & 0xF);
 | 
			
		||||
		*string++ = base((uuid[i] >> 0) & 0xF);
 | 
			
		||||
	}
 | 
			
		||||
	*string = '\0';
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue