With this document we want to explain how we organized the source code of GNU Fdisk.
When we designed this new version we had one rule in mind: the development of a new graphical interface and a new backend should be easy. To do this we have organized the code into several components. Each one of these components provides a well defined interface, but hides the implementation. In this way each component can be modified and others are not affected.
In later chapters we will examine all these components, explaining what is their role, and how it was implemented. Most of the source code is written in C language, some parts are written in Scheme. In this document we assume you’re familiar with these languages.
gnufdisk
is a small executable that takes care of loading the
implementation that you want, with the options you specified.
The model of control to start gnufdisk is as follows:
gnufdisk IMPLEMENTATION [ ARGUMENTS ]
In this model, IMPLEMENTATION means the user interface that you want to use. ARGUMENTS indicates the parameters that you want to provide to this interface.
User interfaces are separate modules, are not part of the gnufdisk
program,
so you can only use interfaces that you have installed on your system.
The only interface included in the program is shell
.
The shell
interface allows you to use the gnufdisk scheme interpreter interactively.
If you run gnufdisk selecting this interface, you’ll be shown the guile prompt:
~/$ gnufdisk shell guile>
In this mode you can work on devices interactively, using the language scheme. See Scheme shell.
To develop GNU fdisk we have used various tools from the GNU project. In this chapter we e
In this library there are functions for general use. This library is used by all the others.
Many times it happens that a pointer contains an invalid address. In
these cases not enough to check if its value is NULL
. Values such
as 0x01
, 0x64
and 0x345
are not equal to NULL
,
but if we try to access these addresses, our program will terminate
with a SIGSEGV
signal. The following function allows
us to check if an address is valid:
int
gnufdisk_check_memory ( void *address, size_t size, int readonly )
¶This function checks if the memory area from address to address + size is accessible for reading. If the parameter readonly is not zero, then this function checks if we have write access.
On success this function returns 0
. If an error occurs, this function returns
-1
and errno is set with the error code.
There are cases where we do not know in advance which addresses are used. Examples of these cases are the functions with variable number of arguments. For these cases, the library provides the following functions:
int
gnufdisk_vfprintf ( FILE* stream, const char *format, va_list args )
¶This function behaves like vfprintf
, capturing any SIGSEGV
signal. On success
this function returns the number of bytes printed. If an error occurs the function returns -1
and errno is set with the appropriate code.
Note: If the function captures a
SIGSEGV
signal, the output is undefined.
int
gnufdisk_vasprintf (char **dest, const char *format, va_list args )
¶This function behaves like vasprintf
, capturing any SIGSEGV
signal. On success
this function returns the number of bytes printed. If an error occurs the function returns -1
and errno is set with the appropriate code.
This library includes some functions for string
handling. The strings are represented with the structure
struct gnufdisk_string
. This structure is hidden,
you can use it only throught pointers and related functions:
struct gnufdisk_string*
gnufdisk_string_new ( const char* format, ... )
¶This function allocates a new string and sets its content in accordance with the format format (and its arguments).
On success the function returns the pointer to the new string. If an error
occurs the function returns NULL
and errno is set with the error value.
int
gnufdisk_string_set ( struct gnufdisk_string* string, const char *format, ... )
¶This function sets the contents of string according with the format format (and it’s arguments).
On success this function returns the length of the string. If an error occurs the function returns -1 and the variable errno is set with the error number.
Note: If the function fails, the contents of the string remains unchanged.
int
gnufdisk_string_length ( struct gnufdisk_string* string )
¶This function returns the length of the string string. If an error occurs the function returns -1 and the variable errno is set with the error number.
const char*
gnufdisk_string_c_string ( struct gnufdisk_string* string )
¶This function returns a pointer to the string data. If an error occurs the
function returns NULL
and sets the variable errno with the error number.
char*
gnufdisk_string_c_string_dup ( struct gnufdisk_string* string )
¶This function returns a pointer to the string data. Pointer must be freed with free
.
If an error occurs the function returns NULL
and sets the variable errno with the error number.
int
gnufdisk_string_delete ( struct gnufdisk_string* string )
¶This function eliminates the string string and frees all its resources. On success the function returns 0. If an error occurs the function returns -1 and errno is set with the error number.
struct gnufdisk_stack*
gnufdisk_stack_new ( void )
¶int
gnufdisk_stack_delete ( struct gnufdisk_stack* stack )
¶int
gnufdisk_stack_push ( struct gnufdisk_stack* stack, void* data, size_t size )
¶int
gnufdisk_stack_pop ( struct gnufdisk_stack* stack, void* dest, size_t size )
¶GNU fdisk includes a small library to send messages to the terminal. To use this library you must include the file gnufdisk-debug.h.
To send logging messages on the terminal you can use the following macro:
The parameter arguments is a function-argument-list that should be
passed to a print function. The format of these arguments is:
(enabled, format, args
).
The parameter enabled should be a boolean expression. If the evaluation of this expression is true then the message will be printed. Otherwise not.
The parameter format is a printf-like format string and args are arguments for this strings.
Once this macro is called, there are 2 ways to configure logging. The first is global, and then enable or disable all messges. The second is through the parameter enabled.
To enable global logging you must define the macro GNUFDISK_DEBUG
while compiling your source. For example, using gcc you can compile with:
gcc -DGNUFDISK_DEBUG -c -o source-file.o source-file.c
To enable or disable logging local to the source you must use the parameter enable. As mentioned above the parameter must be a boolean expression. If the result of this expression is 0 (zero), the message is not displayed. For example:
GNUFDISK_LOG((1, "I received %d bytes", nbytes)); GNUFDISK_LOG((0, "prepare to write..."));
The first message will be displayed. The second message is not displayed. Note that the double parentheses are necessary. If we omit this particular the C preprocessor fails.
If the macro GNUFDISK_DEBUG
is defined and the parameter enable
expands to true, the library will print the message in the following format:
PROCESSID-THREADID:SOURCE:LINENO: MESSAGE
PROCESSID
indicates the id of the process that sent the message.
THREADID
indicates which thread has sent the message. The value is printed as
a sequence of hexadecimal values. SOURCE
is the source file name and LINENO
the number of line where the message is sent.
To send warning messages on the terminal you can use the following macro:
This macro prints a warning message to stderr. The message is formatted according with the string format.
The message is printed according to the following schema:
*** WARNING *** PROCESSID-THREADID:SOURCE:LINENO: MESSAGE
In this section we will make an example of how to use the library. The sample program will copy a file and use the library to display informations. In the second part will show you how to enable and disable logging at global level and at local level. What follows is our source code:
#include <stdlib.h> #include <stdio.h> /* Get definition of GNUFDISK_LOG */ #include <gnufdisk-debug.h> /* We define boolean expressions as calls to getenv, * so that we can enable or disable local logging * using environment variables. */ #define INFO (getenv("INFO") != NULL) #define IO (getenv("IO") != NULL) int main(int argc, char* argv[]) { FILE* in; FILE* out; char buf[512]; int count; GNUFDISK_LOG((INFO, "main: argc=%d, argv=%p", argc, argv)); if(argc < 3) { fprintf(stderr, "USAGE: mycopy source dest\n"); exit(EXIT_FAILURE); } if((in = fopen(argv[1], "rb")) == NULL) { perror("fopen"); exit(EXIT_FAILURE); } GNUFDISK_LOG((INFO, "input stream: %p", in)); if((out = fopen(argv[2], "wb")) == NULL) { perror("fopen"); exit(EXIT_FAILURE); } GNUFDISK_LOG((INFO, "output stream: %p", out)); while((count = fread(buf, 1, sizeof(buf), in)) > 0) { GNUFDISK_LOG((IO, "got %d bytes", count)); if(fwrite(buf, 1, count, out) != count) { perror("fwrite"); exit(EXIT_FAILURE); } } GNUFDISK_LOG((INFO, "done copy")); fclose(in); fclose(out); return EXIT_SUCCESS; }
Now that we have written the code, we can compile. For this example we will build two executables, the first one with debugging enabled at the global level, the second with debugging disabled globally. We will call these two executables mycopy-with-debug and mycopy-without-debug. Here are two commands to compile the two executables:
gcc -DGNUFDISK_DEBUG -o mycopy-with-debug mycopy.c -lgnufdisk-debug gcc -o mycopy-without-debug mycopy.c
Note that if the macro GNUFDISK_DEBUG
is not defined, we do
not need to link our executable to the library, because it is not
used. Now that the executables are compiled we can see their behavior.
The first executable has debug enabled globally, then we can enable
messages using environment variables:
$ # no log at all: $ ./mycopy-with-debug input-file output-file $ # enable logging from category INFO: $ INFO= ./mycopy-with-debug input-file output-file 26925-00000000:mycopy.c:20: main: argc=3, argv=0xbfe8fb94 26925-00000000:mycopy.c:34: input stream: 0x8a19008 26925-00000000:mycopy.c:42: output stream: 0x8a19170 26925-00000000:mycopy.c:55: done copy $ # enable logging for all categories: $ INFO= IO= ./mycopy-with-debug input-file output-file 26926-00000000:mycopy.c:20: main: argc=3, argv=0xbfcef574 26926-00000000:mycopy.c:34: input stream: 0x855e008 26926-00000000:mycopy.c:42: output stream: 0x855e170 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 512 bytes 26926-00000000:mycopy.c:46: got 335 bytes 26926-00000000:mycopy.c:55: done copy
The second executable has debug disabled globally, even if we try to enable messages using environment variables, they will not be displayed:
$ # no log at all: $ ./mycopy-with-debug input-file output-file $ # enable logging from category INFO: $ INFO= ./mycopy-with-debug input-file output-file $ # enable logging for all categories: $ INFO= IO= ./mycopy-with-debug input-file output-file $
When the source code is compiled without defining the macro
GNUFDISK_DEBUG
, each occurrence of GNUFDISK_LOG
is expanded in an
empty statement. In this way, we do not have an impact on the speed of
the program.
GNU Fdisk includes a library for exception handling. This library is capable of handling exceptions in multi-threaded applications in a flexible manner. Exception handling is similar to the one implemented in most modern programming languages where we try, catch and throw. In addition to this we have the ability to block an exception before it is raised, and then continue execution from where the exception was created, or further back (through the continuation points). We can also record functions to clean the data before the stack is cleared, get information about the current state, current exception and so on.
In this chapter we will explain how this library works. Since it is not easy, we begin with a flowchart and then explain each element. The flow chart below explains what happens when an exception is raised:
The following sections will examine the elements of this diagram, associating them to the library. All macros and functions are declared in the file gnufdisk-exception.h.
When an error occurs, and you do not know how to solve it, the best choice is to throw an exception and let the error be managed at the highest level. To throw an exception you can use the following macro:
With this macro you can raise an exception for error error (a signed integer value). You can decide what value to use for this parameter, but you can not use the value 0 (zero) because this value is reserved to the library.
With the mode parameter you can decide how this exception should be
handled. To do this you can use the or operator (|
) and the following
enumerations:
GNUFDISK_EXCEPTION_MANAGEABLE
The exception can be handled by a function before being reported and before the stack is cleared. The handler for this exception will be given at a higher level, at the beginning of the try block. You can pass data to this function using the parameter data (a void pointer). See Throw handlers.
GNUFDISK_EXCEPTION_LOCKABLE
The function that handles the exception can stop the error. If this happens, the stack is not cleared and execution continues to the next statement or jump to a retry-point. You can indicate a retry-point using the parameter retry. See Blocking exceptions.
With the parameter format you can enter a descriptive message for this error. The parameter accepts a printf-like string. The rest of parameters are those required for the format-string.
Once an exception is raised, the library ensures that there is a try
context. If there is no context, the thread is finished using
pthread_kill, and the signal 6 (SIGABORT
).
When an exception was raised, the library checks the value
indicated for the mode parameter. If you have specified the value
GNUFDISK_EXCEPTION_MANAGEABLE
, the library checks whether a handler
has been specified. If this is specified, then calls it.
This is the type for an exception handler. It’s declaration is:
int gnufdisk_exception_handler ( void * handler_data, struct gnufdisk_exception_info *info, void *exception_data );
The parameter handler_data is a void pointer. The value of this
parameter is specified when registering the handler. The parameter
info is a pointer to a structure that contains information about
this exception (see below). The parameter exception_data is a void
pointer. Its value is specified within the macro GNUFDISK_THROW
,
using the parameter data.
This structure contains information about the exception. Its members are:
message
The error message indicated with the macro GNUFDISK_THROW
.
file
The source file name where this exception was raised.
line
The line number where this exception was raised.
error
The error associated with this exception (the value given for parameter
error of GNUFDISK_THROW
)
If you want to specify an exception handler, you must do when starting a try context, using the following macro:
This macro begins a context where you can manage exceptions. The
parameter handler is a pointer to a function that manage the
error before it is reported. The parameter handler_arg
is a void
pointer. You can use it to pass
data to the handler.
If you are able to fix an error in an exception handler, you can tell the library that the error was resolved. To do this you must return a zero value from the exception handler. In this case, the library checks whether the exception can be blocked. If the exception can be blocked then the execution continues from where it was raised (or more back if you specified a retry-point).
To indicate a retry-point you have to use a variable, set it to the
location where you want to jump and indicate it as a parameter retry
when using the macro GNUFDISK_THROW
. To declare and set a retry-point
you can use the following macros:
This allows you to declare a variable where you can jump back.
With this macro you can set a location to jump back. The parameter
retry should be a variable of type GNUFDISK_RETRY
.
You can have multiple GNUFDISK_RETRY
variables, but you can only
use one for each call to GNUFDISK_THROW
. The retry mechanism is
similar to a goto
statement, but it is not a label. Unlike the labels
you can get the address of a retry-point variable and pass it to a
function. This function can throw an exception using this variable and,
if this exception is resolved, execution jumps to where you’ve set the jump.
You can register functions that must be called before cleaning the stack. We call these functions unwind-handlers because they are run just prior to clean up the stack and move the execution at the first properly catch block. To register/unregister handlers you must use the following functions:
int
gnufdisk_exception_register_unwind_handler ( void (*handler)(void *), void *data )
¶This function registers an unwind-handler. The parameter handler is the pointer to the function you want to register. The parameter data is the argument you want passed to the function.
The return value is 0 (zero) if the handler was registered. If an error occurs the function returns -1 and errno is set to error number.
int
gnufdisk_exception_unregister_unwind_handler ( void (*handler)(void *), void *data )
¶This function allows to remove an handler from a try context. The parameters handler and data must be the same as you entered when you registered the handler.
The return value is 0 (zero) if the handler was removed. If an error occurs the function returns -1 and errno is set to error number.
You can register more than one handler, they are called in reverse order. Each handler will be called with its argument.
When an exception occurs and this is not blocked, the library calls the registered handlers, cleans up the stack and then move code execution on an appropriate catch block. To insert one or more catch blocks you must use the following macros:
This macro indicates a statement (or a block of statements) prepared to handle the error error. The parameter error is an integer id for the type of exception.
This macro indicates a set of instructions to be executed if the exception was not handled.
Within each catch block you can use the variable
exception_info.
This variable is an automatic
variable, local to the catch block. For more information about the
type of this variable See struct
gnufdisk_exception_info
.
At the end of a try/catch block should be a call to the macro GNUFDISK_EXCEPTION_END
.
This macro has the following format:
The macro GNUFDISK_EXCEPTION_END
indicates the end of a context
where you can manage exceptions. If there are unhandled exceptions, they
will be raised at the highest level. If no one handles these exceptions,
the thread will be terminated.
Then the template to handle exceptions using this library is as follows:
GNUFDISK_TRY ( handler, handler_arg ) { /* Code where exceptions can be raised */ } [ GNUFDISK_CATCH ( error ) { /* Codet to manage error error */ } ] [ GNUFDISK_CATCH_DEFAULT { /* Default code to manage exceptions */ } ] GNUFDISK_EXCEPTION_END;
The call to GNUFDISK_TRY
is mandatory. It prepares a new
environment where you can catch exceptions. Following this macro
there may be a series of GNUFDISK_CATCH
, one for each error. If
you want, you can place a call to GNUFDISK_CATCH_DEFAULT
to handle uncaught exception. At the end there must be a call to
GNUFDISK_EXCEPTION_END
. This is also mandatory, is used to control
the final state of the context and to release the allocated memory.
In this section we will make an example using the library gnufdisk-exception.
The sample program will try to open a socket listening on port 953 and
use the library to signal errors. If the bind
fails,
we use a throw-handler to resolve the error, and a retry-point variable
to resume operation. The following is sample code:
#include <errno.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <stdint.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <gnufdisk-debug.h> #include <gnufdisk-exception.h> /* define macros for GNUFDISK_LOG */ #define ERROR (getenv("ERROR") != NULL) #define INFO (getenv("INFO") != NULL) /* This is our throw-handler */ static int throw_handler (void *_udata, struct gnufdisk_exception_info *_info, void *_edata) { GNUFDISK_LOG ((ERROR, "handle exception from %s:%d error %d (%s)", _info->file, _info->line, _info->error, strerror (_info->error))); switch (_info->error) { case EACCES: case EADDRINUSE: { /* We assume that the port is busy. We ask you to enter a new port or 'q' to quit. */ char buf[32]; struct sockaddr_in *name; uint16_t new_port; memset (buf, 0, sizeof (buf)); name = _edata; new_port = ntohs (name->sin_port); printf ( "cannot bind socket on port %hu" ", type another port or q to quit: ", new_port ); fflush (stdout); if (scanf ("%31s", buf) < 1 || strchr (buf, 'q') != NULL) return -1; new_port = atoi (buf); name->sin_port = htons (new_port); return 0; /* block the exception */ } } return -1; /* let the exception continue */ } static int create_socket(uint16_t _port) { int sock; struct sockaddr_in name; GNUFDISK_RETRY r1; /* retry point variable */ GNUFDISK_LOG((INFO, "create socket on port %hu", _port)); /* Create the socket. */ sock = socket (PF_INET, SOCK_STREAM, 0); /* On failure we raise an exception. This exception is not manageable, an then not lockable */ if (sock < 0) GNUFDISK_THROW(0, NULL, errno, NULL, "cannot create socket"); /* bind socket */ name.sin_family = AF_INET; name.sin_port = htons (_port); name.sin_addr.s_addr = htonl (INADDR_ANY); GNUFDISK_RETRY_SET(r1); /* set the retry point */ /* On failure we raise an exception. Exception is manageable and lockable. Use retry point `r1' and pass the variable `name' as exception data. */ if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) GNUFDISK_THROW(GNUFDISK_EXCEPTION_MANAGEABLE |GNUFDISK_EXCEPTION_LOCKABLE, &r1, errno, &name, "cannot bind socket on port %hd", ntohs(name.sin_port)); return sock; } /* unwind handler to free a pointer */ static void cleanup_memory(void* _p) { GNUFDISK_LOG((ERROR, "free memory %p", _p)); free(_p); } /* unwind handler to close a socket */ static void close_socket(void* _p) { GNUFDISK_LOG((ERROR, "close socket %p", _p)); close(*(int*) _p); } int main(int argc, char* argv[]) { int ret; /* begin a try context using `throw_handler' as throw-handler pass NULL as handler data */ GNUFDISK_TRY(&throw_handler, NULL) { char* buf; int sock; /* On failure raise an exception. Exception is not manageable and not lockable */ if((buf = malloc(1024)) == NULL) GNUFDISK_THROW(0, NULL, errno, NULL, "cannot allocate memory"); /* register an unwind handler to free buf */ gnufdisk_exception_register_unwind_handler(&cleanup_memory, buf); /* here we can have some exceptions */ sock = create_socket(953); /* registers an unwind handler to close the socket */ gnufdisk_exception_register_unwind_handler(&close_socket, &sock); /* continue */ /* if we walk here, there isn't exceptions so we can close an cleanup explicitly */ close(sock); free(buf); ret = EXIT_SUCCESS; } GNUFDISK_CATCH_DEFAULT { fprintf(stderr, "caught an exception from %s:%d: %s\n", exception_info.file, exception_info.line, exception_info.message); ret = EXIT_FAILURE; } GNUFDISK_EXCEPTION_END; /* end of exception context */ return ret; }
Now that the code is written, we can compile and test our example: We compile using gcc, and enable debugging at all levels:
~$ gcc -o exception -DGNUFDISK_DEBUG exception.c \ -lgnufdisk-debug -lgnufdisk-exception ~$ INFO= ERROR= ./exception 26350-c0061b40:exception.c:72: create socket on port 953 26350-c0061b40:exception.c:29: handle exception from \ exception.c:93 error 13 (Permission denied) cannot bind socket on port 953, type another port or q to quit: 80 26350-c0061b40:exception.c:29: handle exception \ from exception.c:93 error 13 (Permission denied) cannot bind socket on port 80, type another port or q to quit: 98 26350-c0061b40:exception.c:29: handle exception from \ exception.c:93 error 13 (Permission denied) cannot bind socket on port 98, type another port or q to quit: 20 26350-c0061b40:exception.c:29: handle exception from \ exception.c:93 error 13 (Permission denied) cannot bind socket on port 20, type another port or q to quit: q 26350-c0061b40:exception.c:100: free memory 0x9450058 caught an exception from exception.c:93: cannot bind socket on port 20 ~$
As we can see from the logs, it was not possible to bind using port
953. At this point there was an exception and the throw-handler has asked to
enter a new port. The user selects the port number 80, and the exception
has been blocked. This was repeated for port 80, 98 and 20, until the
user has decided to quit. This time the exception was not locked. The
library has called the cleanup_memory
, and the execution has moved
to the catch block.
As we said at the beginning of this document, the new version of GNU fdisk has been built to make easier the implementation of new back-end. With the library gnufdisk-device we offer the possibility to use different implementations having the same interface. In addition, this library is responsible for checking that data is reliable, and resume the operation when an error occurs.
In this chapter we will examine the functions and structures exported by this library. All public functions are declared in the file gnufdisk-device.h, private functions in the file gnufdisk-device-internals.h.
Any error that occurs in this library is signaled by an exception. The type of error is indicated by an integer value, specific data is provided through a union. Below is the list of errors:
GNUFDISK_DEVICE_EMODULEPOINTER
Invalid struct gnufdisk_string
pointer (address is not valid).
GNUFDISK_DEVICE_EMODULE
Invalid module name (module not found).
GNUFDISK_DEVICE_EGEOMETRYLENGTH
Invalid geometry length (less than or equal to 0).
GNUFDISK_DEVICE_EGEOMETRYPOINTER
Invalid struct gnufdisk_geometry
pointer (address is not valid).
GNUFDISK_DEVICE_EGEOMETRY
Invalid geometry (start and/or end are not valid).
GNUFDISK_DEVICE_EDEVICEPOINTER,
Invalid struct gnmufdisk_device
pointer (address is not valid).
GNUFDISK_DEVICE_EDEVICE
Invalid device (internal values are not valid)
GNUFDISK_DEVICE_EDISKLABELPOINTER
Invalid struct gnufdisk_disklabel
pointer (address is not valid).
GNUFDISK_DEVICE_EDISKLABEL
Invalid disklabel (internal values are not valid).
GNUFDISK_DEVICE_EPARTITIONPOINTER
Invalid struct gnufdisk_partition
pointer (address is not valid).
GNUFDISK_DEVICE_EPARTITION
Invalid partition (internal values are not valid).
GNUFDISK_DEVICE_EPARTITIONNUMBER
Partition number out of range.
GNUFDISK_DEVICE_ENOTSUP
Operation not supported.
GNUFDISK_DEVICE_EPATHPOINTER
Invalid struct gnufdisk_string
pointer (address is not valid).
GNUFDISK_DEVICE_EPATH
Invalid device path (device is not accessible).
GNUFDISK_DEVICE_EDESTINATIONPOINTER
Invalid destination pointer (address is not valid).
GNUFDISK_DEVICE_ESIZEPOINTER
Invalid size pointer (address is not valid).
GNUFDISK_DEVICE_EDISKLABELSYSTEMPOINTER
Invalid struct gnufdisk_string
pointer (address is not valid).
GNUFDISK_DEVICE_EDISKLABELSYSTEM
Invalid disklabel system (type is unknown).
GNUFDISK_DEVICE_EPARTITIONTYPEPOINTER
Invalid struct gnufdisk_string
pointer (address is not valid).
GNUFDISK_DEVICE_EPARTITIONTYPE
Invalid partition type (type is unknown).
GNUFDISK_DEVICE_EPARAMETERPOINTER
Invalid struct gnufdisk_string
pointer (address is not valid).
GNUFDISK_DEVICE_EPARAMETER
Invalid parameter (unknown by implementation).
GNUFDISK_DEVICE_EPARAMETERDATA
Invalid parameter pointer (address is not valid).
GNUFDISK_DEVICE_EPARAMETERSIZE
Unexpected parameter size.
GNUFDISK_DEVICE_EREADBUFFER
Invalid read buffer (address is not valid).
GNUFDISK_DEVICE_EWRITEBUFFER
Invalid write buffer (address is not valid).
GNUFDISK_DEVICE_EINTERNAL
Internal error.
GNUFDISK_DEVICE_ENOTOPEN
Device is not open.
GNUFDISK_DEVICE_EIO
Lov level I/O error.
Many of these errors can be resolved through a throw-handler. Errors
that can not be resolved are not manageable by the handler
(they are not reported using the mode GNUFDISK_EXCEPTION_MANAGEABLE
).
Each error is reported along with its data. For example, the
error GNUFDISK_DEVICE_EGEOMETRY
is accompanied by a pointer to
the geometry. The error data are always passed through the union
gnufdisk_device_exception_data
:
union gnufdisk_device_exception_data { struct gnufdisk_string** emodulepointer; struct gnufdisk_string* emodule; struct gnufdisk_string** edisklabelsystempointer; struct gnufdisk_string* edisklabelsystem; struct gnufdisk_string** epartitiontypepointer; struct gnufdisk_string* epartitiontype; size_t* epartitionnumber; struct gnufdisk_string** epathpointer; struct gnufdisk_string* epath; void*** edestinationpointer; size_t ** esizepointer; gnufdisk_integer* egeometrylength; struct gnufdisk_geometry** egeometrypointer; struct gnufdisk_geometry* egeometry; struct gnufdisk_device** edevicepointer; struct gnufdisk_disklabel** edisklabelpointer; struct gnufdisk_partition** epartitionpointer; void **ereadbuffer; void **ewritebuffer; struct gnufdisk_device* enotopen; };
Each element of this structure corresponds to an error. You can correct the data and lock the exception, then the library will resume the operation. If the values are incorrect the exception will be reported again. Here’s an example:
static int throw_handler(void* _hdata, struct gnufdisk_exception_info* _info, void* _edata) { union gnufdisk_device_exception_data* exception_data; exception_data = _edata; if(_info->error == GNUFDISK_DEVICE_EGEOMETRYLENGTH) { *exception_data.egeometrylength = 1; return 0; /* lock the exception */ } return -1; /* let the exception continue */ }
This way you can handle any error. If you do not manage the error the operation will be canceled.
In this library, the geometry of disk is represented by the structure
struct gnufdisk_geometry
. In this structure, the positions
are represented in logical sectors.
This structure is not public, you can use it only through pointers. To create/destroy variables of this type you can use the following functions:
struct gnufdisk_geometry*
gnufdisk_geometry_new ( struct gnufdisk_device* device )
¶This function allocates a new geometry. The parameter device indicates the device to which this geometry refers. This is necessary for the alignment and size restrictions.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_COMMON_ENOMEM
void
gnufdisk_geometry_delete ( struct gnufdisk_geometry* geometry )
¶This function destroys and frees the memory allocated for geometry geometry.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
Once you have allocated a variable, you can set its value. The values of a geometry can be expressed through logical sectors or CHS values. To put a value through a chs triplet, you can use the following structure:
This structure is used to indicate geometric values through a triple (cylinder, head, sector), its definition is as follows:
struct gnufdisk_chs { gnufdisk_integer cylinder; gnufdisk_integer head; gnufdisk_integer sector; };
To set/get geometry values, you can use the following functions:
struct gnufdisk_geometry*
gnufdisk_geometry_set ( struct gnufdisk_geometry *geometry, gnufdisk_integer start, gnufdisk_integer length )
¶This function sets the geometry geometry with the values start and length. On success return geometry.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EGEOMETRYLENGTH
struct gnufdisk_geometry*
gnufdisk_geometry_set_chs ( struct gnufdisk_geometry *geometry, struct gnufdisk_chs start, struct gnufdisk_chs length )
¶This function is similar to the previous one, but the values are indicated by chs triplets.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EGEOMETRYLENGTH
gnufdisk_integer
gnufdisk_geometry_start ( struct gnufdisk_geometry* )
¶This function returns the start sector from geometry.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
struct gnufdisk_chs
gnufdisk_geometry_start_chs ( struct gnufdisk_geometry* )
¶This function is similar to the previous one, but the value is returnet throught a chs triplet.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
gnufdisk_integer
gnufdisk_geometry_end ( struct gnufdisk_geometry* )
¶This function returns the end sector from geometry.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
struct gnufdisk_chs
gnufdisk_geometry_end_chs ( struct gnufdisk_geometry* )
¶This function is similar to the previous one, but the value is returnet throught a chs triplet.
gnufdisk_integer
gnufdisk_geometry_length ( struct gnufdisk_geometry* )
¶This function returns the lenght of geometry in sectors.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
struct gnufdisk_chs
gnufdisk_geometry_length_chs ( struct gnufdisk_geometry* )
¶This function is similar to the previous one, but the value is returnet throught a chs triplet.
GNUFDISK_DEVICE_EGEOMETRYPOINTER
GNUFDISK_DEVICE_EDEVICEPOINTER
In this library devices are represented through the structure
gnufdisk_device
. This structure is hidden, you can use it only
through pointers.
To create or destroy struct gnufdisk_device
variables,
you can use the following functions:
struct gnufdisk_device*
gnufdisk_device_new ( struct gnufdisk_string* module, struct gnufdisk_string* options )
¶With this function you can create a new variable of type struct gnufdisk_device
.
The parameter module indicates which implementation
you want to use for this variable. The parameter options means options
that you specify for this implementation. See Backend API.
GNUFDISK_DEVICE_EMODULEPOINTER
GNUFDISK_DEVICE_EMODULE
GNUFDISK_COMMON_ENOMEM
void
gnufdisk_device_delete ( struct gnufdisk_device* device )
¶This function destroys the variable device and frees all allocated resources. Once destroyed, this variable is no longer usable.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
Once a variable has been allocated, you can perform operations on it using the following functions:
void
gnufdisk_device_ref ( struct gnufdisk_device* device )
¶This function adds a reference to the variable device. Even if someone tries to destroy it, the variable remains allocated as long as you do not destroy it.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
void
gnufdisk_device_open ( struct gnufdisk_device* device, struct gnufdisk_string* path )
¶This function binds the variable device variable to the file path (usually a device). After calling this function, you can begin to perform operations on this device.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_EPATHPOINTER
GNUFDISK_DEVICE_ENOTSUP
struct gnufdisk_disklabel *
gnufdisk_device_disklabel ( struct gnufdisk_device* device )
¶This function allows you to get the partition table on the device device.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_ENOTSUP
GNUFDISK_DEVICE_ENOTOPEN
GNUFDISK_DEVICE_EDISKLABELSYSTEM
struct gnufdisk_disklabel*
gnufdisk_device_create_disklabel ( struct gnufdisk_device* device, struct gnufdisk_string* system )
¶This function allows you to create a new partition table on device. The parameter system indicates the type of table you want to create.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDIKS_DEVICE_ENOTSUP
GNUFDISK_COMMON_ENOMEM
GNUFDISK_DEVICE_EDISKLABELSYSTEMPOINTER
GNUFDISK_DEVICE_EDISKLABELSYSTEM
GNUFDISK_DEVICE_ENOTOPEN
void
gnufdisk_device_set_parameter ( struct gnufdisk_device* device, struct gnufdisk_string* parameter, const void* data, size_t size )
¶This function allows you to set a specific parameter on device. parameter is the name of the parameter that you want to set. The parameter data is the value that you want to set. The parameter size indicates the size of data.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_EPARAMETERPOINTER
GNUFDISK_DEVICE_EPARAMETER
GNUFDISK_DEVICE_EPARAMETERDATA
GNUFDISK_DEVICE_ENOTSUP
GNUFDISK_DEVICE_ENOTOPEN
void
gnufdisk_device_get_parameter ( struct gnufdisk_device* device, struct gnufdisk_string* parameter, void* data, size_t size )
¶This function allows you to read a specific parameter from device. parameter is the name of the parameter you want to read. The parameter data is the buffer where the value will be written. The parameter size" indicates the size of data buffer.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_EPARAMETERPOINTER
GNUFDISK_DEVICE_EPARAMETER
GNUFDISK_DEVICE_EPARAMETERDATA
GNUFDISK_DEVICE_ENOTSUP
GNUFDISK_DEVICE_ENOTOPEN
void
gnufdisk_device_commit ( struct gnufdisk_device* device )
¶Any changes made to devices remains in memory. With this function you can make the changes effective.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_ENOTSUP
GNUFDISK_DEVICE_ENOTOPEN
void
gnufdisk_device_close ( struct gnufdisk_device* device )
¶This function closes the file associated with device. The changes
are not made effective. If you want to write changes, you must
call gnufdisk_device_commit
before closing device.
GNUFDISK_DEVICE_EDEVICEPOINTER
GNUFDISK_DEVICE_EDEVICE
GNUFDISK_DEVICE_ENOTSUP
GNUFDISK_DEVICE_ENOTOPEN
Partition tables are represented by the structure
struct gnufdisk_disklabel
. This structure is hidden, you can use it only
through pointers. Also you can not implicitly create a variable of this
type, you can only get it through a device. See Devices.
Once you have a pointer of type struct gnufdisk_disklabel
, you can perform
operations using the following functions:
void
gnufdisk_disklabel_delete ( struct gnufdisk_disklabel *disklabel )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
void
gnufdisk_disklabel_ref ( struct gnufdisk_disklabel *disklabel )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
void
gnufdisk_disklabel_raw ( struct gnufdisk_disklabel *disklabel, void **dest, size_t * size )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
struct gnufdisk_string*
gnufdisk_disklabel_system ( struct gnufdisk_disklabel* disklabel )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
struct gnufdisk_partition*
gnufdisk_disklabel_partition ( struct gnufdisk_disklabel* disklabel, size_t number )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
struct gnufdisk_partition*
gnufdisk_disklabel_create_partition ( struct gnufdisk_disklabel* disklabel, struct gnufdisk_geometry* start_range, struct gnufdisk_geometry* end_range, struct gnufdisk_string* type )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
void
gnufdisk_disklabel_remove_partition ( struct gnufdisk_disklabel* disklabel, size_t number )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
void
gnufdisk_disklabel_set_parameter ( struct gnufdisk_disklabel* disklabel, struct gnufdisk_string* parameter, const void* data, size_t size )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
void
gnufdisk_disklabel_get_parameter ( struct gnufdisk_disklabel* disklabel, struct gnufdisk_string* parameter, void* data, size_t size )
¶
GNUFDISK_DEVICE_EDISKLABELPOINTER
GNUFDISK_DEVICE_EDISKLABEL
In this library partitions are represented by the structure
struct gnufdisk_partition
. This structure is hidden, you can use it only
through pointers. Also you can not implicitly allocate variables of this
type, you can only get them through a partition table. See Disklabels.
When you have a variable of type struct gnufdisk_partition
,
you can use the following functions to work on it:
void
gnufdisk_partition_ref ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
void
gnufdisk_partition_delete ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
void
gnufdisk_partition_set_parameter ( struct gnufdisk_partition* partition struct gnufdisk_string* parameter, const void* data, size_t size )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
void
gnufdisk_partition_get_parameter ( struct gnufdisk_partition* parameter, struct gnufdisk_string* param, void* data, size_t size )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
struct gnufdisk_string*
gnufdisk_partition_type ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
int
gnufdisk_partition_number ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
gnufdisk_integer
gnufdisk_partition_start ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
gnufdisk_integer
gnufdisk_partition_length ( struct gnufdisk_partition* partition )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
void
gnufdisk_partition_move ( struct gnufdisk_partition* partition, struct gnufdisk_geometry* start_range )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
void
gnufdisk_partition_resize ( struct gnufdisk_partition* partition, struct gnufdisk_geometry* end_range )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
int
gnufdisk_partition_read ( struct gnufdisk_partition* partition, gnufdisk_integer start, void* buf, size_t size )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
int
gnufdisk_partition_write ( struct gnufdisk_partition* partition, gnufdisk_integer sector, const void* buf, size_t size )
¶
GNUFDISK_DEVICE_EPARTITIONPOINTER
GNUFDISK_DEVICE_EPARTITION
In this section we will make a small example of how to use the library gnufdisk-device. Since we do not have a module, we create a basic as it only exports a few functions:
#include <stdio.h> #include <gnufdisk-device.h> #include <gnufdisk-device-internals.h> static void device_open(void *_dev, struct gnufdisk_string* _path) { printf("open `%s' with device %p\n", gnufdisk_string_c_string(_path), _dev); } static void device_delete(void* _dev) { printf("delete device %p\n", _dev); free(_dev); } static struct gnufdisk_device_operations devop = {0}; void module_register(struct gnufdisk_string * _options, struct gnufdisk_device_operations * _operations, void **_private_data) { printf("register module `testmod'\n"); devop.open = &device_open; devop.delete = &device_delete; *_operations = devop; *_private_data = malloc(16); }
Once the module is compiled, we can test its use. What follows is a piece of code that uses the module:
#include <stdio.h> #include <gnufdisk-exception.h> #include <gnufdisk-device.h> int main(int argc, char* argv[]) { struct gnufdisk_string* s; struct gnufdisk_device* dev; GNUFDISK_TRY(NULL, NULL) { s = gnufdisk_string_new("testmod"); dev = gnufdisk_device_new(s, NULL); gnufdisk_string_set(s, "/dev/sda"); gnufdisk_device_open(dev, s); sleep(1); gnufdisk_device_delete(dev); gnufdisk_string_delete(s); } GNUFDISK_CATCH_DEFAULT { printf("caught an exception from %s:%d: %s\n", exception_info.file, exception_info.line, exception_info.message); } GNUFDISK_EXCEPTION_END; return 0; }
struct gnufdisk_devicemanager *
gnufdisk_devicemanager_new ( struct gnufdisk_userinterface *ui )
¶int
gnufdisk_devicemanager_ref ( struct gnufdisk_devicemanager *dm )
¶int
gnufdisk_devicemanager_delete ( struct gnufdisk_devicemanager *dm )
¶struct gnufdisk_geometry *
gnufdisk_devicemanager_geometry_new ( struct gnufdisk_devicemanager* dm, struct gnufdisk_device* dev )
¶struct gnufdisk_geometry *
gnufdisk_devicemanager_geometry_duplicate ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry *geom )
¶int
gnufdisk_devicemanager_geometry_delete ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶struct gnufdisk_geometry *
gnufdisk_devicemanager_geometry_set ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom, gnufdisk_integer start, gnufdisk_integer end )
¶gnufdisk_integer
gnufdisk_devicemanager_geometry_start ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom)
¶struct gnufdisk_chs
gnufdisk_devicemanager_geometry_start_chs ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶gnufdisk_integer
gnufdisk_devicemanager_geometry_end ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶struct gnufdisk_chs
gnufdisk_devicemanager_geometry_end_chs ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶gnufdisk_integer
gnufdisk_devicemanager_geometry_length ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶struct gnufdisk_chs
gnufdisk_devicemanager_geometry_length_chs ( struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom )
¶struct gnufdisk_device *
gnufdisk_devicemanager_device_new ( struct gnufdisk_devicemanager *dm, struct gnufdisk_string *module, struct gnufdisk_string *module_options )
¶int
gnufdisk_devicemanager_device_open ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev, struct gnufdisk_string *path )
¶struct gnufdisk_disklabel *
gnufdisk_devicemanager_device_disklabel ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev )
¶struct gnufdisk_disklabel *
gnufdisk_devicemanager_device_create_disklabel ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev, struct gnufdisk_string *system )
¶int
gnufdisk_devicemanager_device_set_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev, struct gnufdisk_string *param, const void *data, size_t size )
¶int
gnufdisk_devicemanager_device_get_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev, struct gnufdisk_string *param, void *dest, size_t size )
¶int
gnufdisk_devicemanager_device_commit ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev )
¶int
gnufdisk_devicemanager_device_close ( struct gnufdisk_devicemanager *dm, struct gnufdisk_device *dev )
¶int
gnufdisk_devicemanager_device_delete ( struct gnufdisk_devicemanager * dm, struct gnufdisk_device* dev )
¶int
gnufdisk_devicemanager_disklabel_raw ( struct gnufdisk_devicemanager * dm, struct gnufdisk_disklabel * disk, void **dest, size_t *size )
¶struct gnufdisk_string *
gnufdisk_devicemanager_disklabel_system ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk )
¶struct gnufdisk_partition *
gnufdisk_devicemanager_disklabel_partition ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk, size_t number )
¶struct gnufdisk_partition *
gnufdisk_devicemanager_disklabel_create_partition ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk, struct gnufdisk_geometry *start, struct gnufdisk_geometry *end, struct gnufdisk_string *type )
¶int
gnufdisk_devicemanager_disklabel_remove_partition ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk, size_t number )
¶int
gnufdisk_devicemanager_disklabel_set_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk, struct gnufdisk_string *param, const void *data, size_t size )
¶int
gnufdisk_devicemanager_disklabel_get_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_disklabel *disk, struct gnufdisk_string *param, void *dest, size_t size )
¶int
gnufdisk_devicemanager_partition_set_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, struct gnufdisk_string *param, const void *data, size_t size )
¶int
gnufdisk_devicemanager_disklabel_delete ( struct gnufdisk_devicemanager* dm, struct gnufdisk_disklabel* disk )
¶int
gnufdisk_devicemanager_partition_get_parameter ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, struct gnufdisk_string *param, void *dest, size_t size )
¶struct gnufdisk_string *
gnufdisk_devicemanager_partition_type ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part )
¶gnufdisk_integer
gnufdisk_devicemanager_partition_start ( struct gnufdisk_devicemanager* dm, struct gnufdisk_partition *part )
¶gnufdisk_integer
gnufdisk_devicemanager_partition_length ( struct gnufdisk_devicemanager* dm, struct gnufdisk_partition *part )
¶int
gnufdisk_devicemanager_partition_number ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part )
¶int
gnufdisk_devicemanager_partition_move ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, struct gnufdisk_geometry *range )
¶int
gnufdisk_devicemanager_partition_resize ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, struct gnufdisk_geometry *range )
¶int
gnufdisk_devicemanager_partition_read ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, gnufdisk_integer start, void *buf, size_t size)
¶int
gnufdisk_devicemanager_partition_write ( struct gnufdisk_devicemanager *dm, struct gnufdisk_partition *part, gnufdisk_integer start, const void *buf, size_t size )
¶int
gnufdisk_devicemanager_partition_delete ( struct gnufdisk_devicemanager* dm, struct gnufdisk_partition* part )
¶struct gnufdisk_userinterface*
gnufdisk_userinterface_new ( void )
¶int
gnufdisk_userinterface_ref ( struct gnufdisk_userinterface* ui )
¶int
gnufdisk_userinterface_delete ( struct gnufdisk_userinterface* ui )
¶int
gnufdisk_userinterface_run ( struct gnufdisk_userinterface* ui, struct gnufdisk_string* implementation, int argc, char **argv )
¶int
gnufdisk_userinterface_print ( struct gnufdisk_userinterface* ui, const char* format, ... )
¶int
gnufdisk_userinterface_yes_no ( struct gnufdisk_userinterface* ui, const char * format, ... )
¶struct gnufdisk_string*
gnufdisk_userinterface_get_path ( struct gnufdisk_userinterface* ui, const char *format, ... )
¶struct gnufdisk_string*
gnufdisk_userinterface_get_disklabel_system ( struct gnufdisk_userinterface* ui, const char* format, ... )
¶int
gnufdisk_userinterface_get_geometry ( struct gnufdisk_userinterface* ui, struct gnufdisk_devicemanager* dm, struct gnufdisk_geometry* geom, const char* format, ... )
¶struct gnufdisk_string*
gnufdisk_userinterface_get_partition_type ( struct gnufdisk_userinterface* ui, const char* format, ... )
¶To run gnufdisk in shell mode:
~$ gnufdisk shell guile>
In shell mode you can use all symbols, plus the gnufdisk-help
This procedure allows you to create a new device. The parameter
devicemanager is the manager to create this device (created with
gnufdisk-make-devicemanager
). The parameter module is a string
with the name of the module (backend) you want to use. options is
a string of options to pass to the backend.
'INT
'INTEGER
'STR
'STRING
'INT
'INTEGER
'STR
'STRING
'INT
'INTEGER
'STR
'STRING
- Function: print message ¶
- Function: error message ¶
- Function: yes-no message ¶
- Function: get-path message ¶
- Function: get-disklabel-system message ¶
- Function: get-geometry message geom ¶
- Function: get-partition-system message ¶
struct gnufdisk_device_operations { void (*open)(void*, struct gnufdisk_string*); void (*disklabel)(void*, struct gnufdisk_disklabel_operations*, void**); void (*create_disklabel)(void*, struct gnufdisk_string*, struct gnufdisk_disklabel_operations*, void**); void (*set_parameter)(void*, struct gnufdisk_string*, const void*, size_t); void (*get_parameter)(void*, struct gnufdisk_string*, void*, size_t); void (*commit)(void*); void (*close)(void*); void (*delete)(void*); };
struct gnufdisk_disklabel_operations { void (*raw)(void*, void**, size_t*); struct gnufdisk_string* (*system)(void*); void (*partition)(void*, size_t, struct gnufdisk_partition_operations*, void**); void (*create_partition)(void*, struct gnufdisk_geometry*, struct gnufdisk_geometry*, struct gnufdisk_string*, struct gnufdisk_partition_operations*, void**); void (*remove_partition)(void*, size_t); void (*set_parameter)(void*, struct gnufdisk_string*, const void*, size_t); void (*get_parameter)(void*, struct gnufdisk_string*, void*, size_t); void (*delete)(void*); };
struct gnufdisk_partition_operations { void (*set_parameter)(void*, struct gnufdisk_string*, const void*, size_t); void (*get_parameter)(void*, struct gnufdisk_string*, void*, size_t); struct gnufdisk_string* (*type)(void*); gnufdisk_integer (*start)(void*); gnufdisk_integer (*length)(void*); int (*number)(void*); void (*move)(void*, struct gnufdisk_geometry*); void (*resize)(void*, struct gnufdisk_geometry*); int (*read)(void*, gnufdisk_integer, void*, size_t); int (*write)(void*, gnufdisk_integer, const void*, size_t _size); void (*delete)(void*); };
int
register_module ( struct gnufdisk_device_operations* devops, void **pdata )
¶#include <stdlib.h> #include <string.h> #include <gnufdisk-debug.h> #include <gnufdisk-exception.h> #include <gnufdisk-device-internals.h> #define INFO (getenv("SAMPLE_BACKEND") != NULL) static size_t ndev = 0; static size_t ndisk = 0; static size_t npart = 0; static void partition_set_parameter (void *_data, struct gnufdisk_string *_name, const void *_pdata, size_t _psize) { GNUFDISK_LOG ((INFO, "partition_set_parameter(%s, %p, %p, %u)", _data, _name, _pdata, _psize)); } static void partition_get_parameter (void *_data, struct gnufdisk_string *_name, void *_pdata, size_t _psize) { GNUFDISK_LOG ((INFO, "partition_get_parameter(%s, %p, %p, %u)", _data, _name, _pdata, _psize)); } static struct gnufdisk_string * partition_type (void *_data) { struct gnufdisk_string *s; GNUFDISK_LOG ((INFO, "partition_type(%s)", _data)); if ((s = gnufdisk_string_new ("undefined")) == NULL) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_ENOMEM, NULL, "can not allocate memory"); return s; } static gnufdisk_integer partition_start (void *_data) { GNUFDISK_LOG ((INFO, "partition_start(%s)", _data)); return 0xffff; } static gnufdisk_integer partition_end (void *_data) { GNUFDISK_LOG ((INFO, "partition_end(%s)", _data)); return 0xffff; } static int partition_number (void *_data) { GNUFDISK_LOG ((INFO, "partition_number(%s)", _data)); return 0x45; } static void partition_move (void *_data, struct gnufdisk_geometry *_s) { GNUFDISK_LOG ((INFO, "partition_move(%s, %p)", _data, _s)); } static void partition_resize (void *_data, struct gnufdisk_geometry *_e) { GNUFDISK_LOG ((INFO, "partition_resize(%s, %p)", _data, _e)); } static int partition_read (void *_data, gnufdisk_integer _sector, void *_dest, size_t _size) { GNUFDISK_LOG ((INFO, "partition_read(%s, %lld, %p, %u)", _data, _sector, _dest, _size)); return _size; } static int partition_write (void *_data, gnufdisk_integer _sector, const void *_src, size_t _size) { GNUFDISK_LOG ((INFO, "partition_write(%s, %lld, %p, %u)", _data, _sector, _src, _size)); } static void partition_delete (void *_data) { GNUFDISK_LOG ((INFO, "partition_delete(%s)", _data)); free(_data); } static struct gnufdisk_partition_operations partition_operations = { &partition_set_parameter, &partition_get_parameter, &partition_type, &partition_start, &partition_end, &partition_number, &partition_move, &partition_resize, &partition_read, &partition_write, &partition_delete }; static void disklabel_raw (void *_data, void **_dest, size_t * _size) { GNUFDISK_LOG ((INFO, "disklabel_raw(%s, %p, %p)", _data, _dest, _size)); if ((*_dest = malloc (512)) == NULL) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_ENOMEM, NULL, "can not allocate memory"); *_size = 512; } static struct gnufdisk_string * disklabel_system (void *_data) { struct gnufdisk_string *s; GNUFDISK_LOG ((INFO, "disklabel_system(%s)", _data)); if ((s = gnufdisk_string_new ("BSD")) == NULL) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_ENOMEM, NULL, "can not allocate memory"); return s; } static void disklabel_partition (void *_data, size_t _n, struct gnufdisk_partition_operations *_operations, void **_specific) { char buf[64]; GNUFDISK_LOG ((INFO, "disklabel_partition(%s, %u, %p, %p)", _data, _n, _operations, _specific)); memcpy (_operations, &partition_operations, sizeof (partition_operations)); npart++; snprintf(buf, sizeof(buf), "PARTITION %u", npart); *_specific = strdup(buf); } static void disklabel_create_partition (void *_data, struct gnufdisk_geometry *_s, struct gnufdisk_geometry *_e, struct gnufdisk_string *_type, struct gnufdisk_partition_operations *_operations, void **_specific) { char buf[64]; GNUFDISK_LOG ((INFO, "disklabel_create_partition(%s, %p, %p, %p, %p, %p)", _data, _s, _e, _type, _operations, _specific)); memcpy (_operations, &partition_operations, sizeof (partition_operations)); npart++; snprintf(buf, sizeof(buf), "PARTITION %u", npart); *_specific = strdup(buf); } static void disklabel_remove_partition (void *_data, size_t _n) { GNUFDISK_LOG ((INFO, "disklabel_remove_partition(%s, %u)", _data, _n)); } static void disklabel_set_parameter (void *_data, struct gnufdisk_string *_name, const void *_pdata, size_t _psize) { GNUFDISK_LOG ((INFO, "disklabel_set_parameter(%s, %p, %p, %u)", _data, _name, _pdata, _psize)); } static void disklabel_get_parameter (void *_data, struct gnufdisk_string *_name, void *_pdata, size_t _psize) { GNUFDISK_LOG ((INFO, "disklabel_get_parameter(%s, %p, %p, %u)", _data, _name, _pdata, _psize)); } static void disklabel_delete (void *_data) { GNUFDISK_LOG ((INFO, "disklabel_delete(%s)", _data)); free(_data); } static struct gnufdisk_disklabel_operations disklabel_operations = { &disklabel_raw, &disklabel_system, &disklabel_partition, &disklabel_create_partition, &disklabel_remove_partition, &disklabel_set_parameter, &disklabel_get_parameter, &disklabel_delete }; static void device_open (void *_data, struct gnufdisk_string *_path) { GNUFDISK_LOG ((INFO, "device_open(%s, %p)", _data, _path)); } static void device_disklabel (void *_data, struct gnufdisk_disklabel_operations *_operations, void **_specific) { char buf[64]; GNUFDISK_LOG ((INFO, "device_disklabel(%s, %p, %p)", _data, _operations, _specific)); memcpy (_operations, &disklabel_operations, sizeof (disklabel_operations)); ndisk++; snprintf(buf, sizeof(buf), "DISKLABEL %u", ndisk); *_specific = strdup(buf); } static void device_create_disklabel (void *_data, struct gnufdisk_string *_type, struct gnufdisk_disklabel_operations *_operations, void **_specific) { char buf[64]; GNUFDISK_LOG ((INFO, "device_create_disklabel(%s, %p, %p, %p)", _data, _type, _operations, _specific)); memcpy (_operations, &disklabel_operations, sizeof (disklabel_operations)); ndisk++; snprintf(buf, sizeof(buf), "DISKLABEL %u", ndisk); *_specific = strdup(buf); } static void device_set_parameter (void *_data, struct gnufdisk_string *_parameter, const void *_pdata, size_t _psize) { GNUFDISK_LOG ((INFO, "device_set_parameter(%s, %p, %p, %u)", _data, _parameter, _pdata, _psize)); } static void device_get_parameter (void *_data, struct gnufdisk_string *_parameter, void *_pdata, size_t _psize) { char *param; GNUFDISK_LOG ((INFO, "device_get_parameter(%s, %p, %p, %u)", _data, _parameter, _pdata, _psize)); if ((param = gnufdisk_string_c_string_dup (_parameter)) == NULL) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_ENOMEM, NULL, "can not allocate memory"); gnufdisk_exception_register_unwind_handler (&free, param); if (strcmp (param, "SECTORS-PER-TRACK") == 0) { if (_psize != sizeof (gnufdisk_integer)) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_EPARAMETERSIZE, NULL, "unexpected parameter size: %u", _psize); *((gnufdisk_integer *) _pdata) = 0xff; } else if (strcmp (param, "HEADS-PER-CYLINDER") == 0) { if (_psize != sizeof (gnufdisk_integer)) GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_EPARAMETERSIZE, NULL, "unexpected parameter size: %u", _psize); *((gnufdisk_integer *) _pdata) = 0x02; } else GNUFDISK_THROW (0, NULL, GNUFDISK_DEVICE_EPARAMETER, NULL, "parameter `%s' is not supported", param); free (param); } static void device_commit (void *_data) { GNUFDISK_LOG ((INFO, "device_commit(%s)", _data)); } static void device_close (void *_data) { GNUFDISK_LOG ((INFO, "device_close(%s)", _data)); } static void device_delete (void *_data) { GNUFDISK_LOG ((INFO, "device_delete(%s)", _data)); free(_data); } static struct gnufdisk_device_operations device_operations = { &device_open, &device_disklabel, &device_create_disklabel, &device_set_parameter, &device_get_parameter, &device_commit, &device_close, &device_delete }; void module_register (struct gnufdisk_string *_options, struct gnufdisk_device_operations *_operations, void **_pdata) { char buf[64]; GNUFDISK_LOG ((INFO, "register_module(%p, %p, %p)", _options, _operations, _pdata)); memcpy (_operations, &device_operations, sizeof (device_operations)); ndev++; snprintf(buf, sizeof(buf), "DEVICE %u", ndev); *_pdata = strdup(buf); }
Index Entry | Section | |
---|---|---|
* | ||
*command-line* | Scheme shell | |
*userinterface* | Scheme shell | |
E | ||
exception_info | Catch | |