anysurrect-plugins(3)

NAME
anysurrect-plugins - anysurrect plug-ins allows you to recognize and recover additional file formats besides formats which includes anysurrect. The manual page describes macroses and functions which will useful for format recognizers new functions programming.

SYNOPSIS
#include <anysurrect.h>

SKIP_STRING(const char *name, any_off_t len);

SKIP_BYTE(const char *name);

SKIP_SHORT(const char *name);
SKIP_BESHORT(const char *name);
SKIP_LESHORT(const char *name);

SKIP_LONG64(const char *name);
SKIP_BELONG64(const char *name);
SKIP_LELONG64(const char *name);

SKIP_LONG(const char *name);
SKIP_BELONG(const char *name);
SKIP_LELONG(const char *name);

COND_STRING(const char *name, size_t len, CONDITION);

EX_STRING(const char *name, const char *string);

LIST_STRING(const char *name, size_t len , {const char string_1[len+1], const char string_2[len+1], ..., NULL} );

uint32_t READ_BELONG64(const char *name);
uint32_t COND_BELONG64(const char *name, CONDITION);
EX_BELONG64(const char *name, uint32_t value);

uint32_t READ_BELONG(const char *name);
uint32_t COND_BELONG(const char *name, CONDITION);
EX_BELONG(const char *name, uint32_t value);

uint16_t READ_BESHORT(const char *name);
uint16_t COND_BESHORT(const char *name, CONDITION);
EX_BESHORT(const char *name, uint16_t value);

uint32_t READ_LELONG64(const char *name);
uint32_t COND_LELONG64(const char *name, CONDITION);
EX_LELONG64(const char *name, uint32_t value);

uint32_t READ_LELONG(const char *name);
uint32_t COND_LELONG(const char *name, CONDITION);
EX_LELONG(const char *name, uint32_t value);

uint16_t READ_LESHORT(const char *name);
uint16_t COND_LESHORT(const char *name, CONDITION);
EX_LESHORT(const char *name, uint16_t value);

uint8_t READ_BYTE(const char *name);
uint8_t COND_BYTE(const char *name, CONDITION);
EX_BYTE(const char *name, uint8_t value);

FUNCOVER(name, operation);
MAYBE(operation);

int read_byte(uint8_t *value);

int read_beshort(uint16_t *value);
int read_belong(uint32_t *value);
int read_belong64(uint32_t *value);

int read_leshort(uint16_t *value);
int read_lelong(uint32_t *value);
int read_lelong64(uint32_t *value);

any_off_t fd_seek(any_off_t offset, int whence);
any_size_t fd_size();
any_ssize_t fd_read(void *buf, any_size_t count);

char* <file_format>_surrect();
void* <file_format>_parseopts(const int argc, const char* argv[]);
void* <file_format>_usage();
const char* <file_format>_indicator="<short_format_name>";
const int <file_format>_text=1;
const mode_t <file_format>_mode=<mode>;
const char* <file_format>_opts=<module_name>;

DESCRIPTION
You always can to write anysurrect module for recognizing new formats, and load it with -g option. Below will describes functions useful for writing such modules.

NECESSARY MODULE DECLARATIONS

char* <file_format>_surrect();
    Format recognize function must has such name format and type. If format recognizing is successful, the function must return string -- path to directory for founded file. For example: "audio/MIDI" for MIDI-files. Reading pointer set by fd_seek() function (see below) must point to end of founded file. In case of unsuccessful -- function must return NULL.

void* <file_format>_parseopts(const int argc, const char* argv[]);
    Function for parse module options, called if founded according options (see. <file_format>_opts ) At that first module option number writes to global variable optind (it sets with getopt library function) Expected that after parsing funcrion sets according value for optind to point the end of module options.

void* <file_format>_usage();
    The module usage function. It called with using -H option in anysurrect command.

const char* <file_format>_indicator="<short_format_name>";
    Short name for indicator in progress string. If this declaration is leaved, by default it will set to "UNKNOWN".

const int <file_format>_text=1;
    Optionally declaration useful for text formats such as text_ASCII, text_EIGTH_BIT, text_UTF8, text_UTF16BE and text_UTF16LE. It is need when there are very long text symbols sequence (but not text). So as at end of such sequence, text format processor understands that it is not text format, but after it anysurrect once more call it for the next block, i.e. for the same text and processor once more runs on almost all this text to understand that it is not text (after all texts doesn't have any magic sequences in the beginning of file, so at the begin, and at the middle from the point of processor view it is such text). But on each such call spends much time (so as text symbols sequence may be very long), and for many such calls forever. For time saving, service this declaration. It talks to anysurrect, that if format processor returns NULL, it is need to see at fd_seek pointer and don't call this processor to end of block which very similar to text.

const mode_t <file_format>_mode=<mode>;
    By default recovered files has access mode mask 0666. This optionally declaration may to change access mode for you file types. So, for example, ELF32 file format use the next declaration: const mode_t executable_ELF32_mode=0777;

const char* <file_format>_opts=<module_name>;
    Short module name to passing to its options through anysurrect command.

READ FILE FUNCTIONS
Writing file processor module, you should not direct use functions to read from device. anysurrect opens device, move read pointer to some supposed location of file beginning and then call format processor. What is more anysurrect may put blocks for reading to format processor in not device reading order -- it may skip blocks, which already busy by other files (description of which loads with -i options in external inode table). Use the next read functions from file and don't think about information on device before your file, but think about "garbage" on device after the file -- you need to stop processing in time.

any_off_t fd_seek(any_off_t offset, int whence);
    The function similar to lseek64 but it doesn't have file descriptor argument -- anysurrect already knows it.

any_size_t fd_size();
    Returns max filesize, which format processor may return.

any_ssize_t fd_read(void *buf, any_size_t count);
    Similar to read(2) but it doesn't have file descriptor argument -- anysurrect already knows it.

int read_byte(uint8_t *value);
    Reads 1 byte to buffer, on which points value. Returns 0 if successful and 1 -- if unsuccessful.

int read_beshort(uint16_t *value);
    Reads value of uint16_t type (2 bytes) to buffer, on which points value, consider that high byte on disk keeps forward (i.e. value saved in Big Endian format). Returns 0 if successful and 1 -- if unsuccessful.

int read_belong(uint32_t *value);
    Reads value of uint32_t type (4 bytes) to buffer, on which points value, consider that high byte on disk keeps forward (i.e. value saved in Big Endian format). Returns 0 if successful and 1 -- if unsuccessful.

int read_belong64(uint64_t *value);
    Reads value of uint64_t type (8 bytes) to buffer, on which points value, consider that high byte on disk keeps forward (i.e. value saved in Big Endian format). Returns 0 if successful and 1 -- if unsuccessful.

int read_leshort(uint16_t *value);
    Reads value of uint16_t type (2 bytes) to buffer, on which points value, consider that low byte on disk keeps forward (i.e. value saved in Little Endian format). Returns 0 if successful and 1 -- if unsuccessful.

int read_lelong(uint32_t *value);
    Reads value of uint32_t type (4 bytes) to buffer, on which points value, consider that low byte on disk keeps forward (i.e. value saved in Little Endian format). Returns 0 if successful and 1 -- if unsuccessful.

int read_lelong64(uint64_t *value);
    Reads value of uint64_t type (8 bytes) to buffer, on which points value, consider that low byte on disk keeps forward (i.e. value saved in Little Endian format). Returns 0 if successful and 1 -- if unsuccessful.

READ FUNCTIONS MACROSES
Macroses for file reading was created for simplifying file processors programming and increasing of its code readability. Any from this macros may NOT return control to the next function instruction if it was unsuccessful, or was failed a condition. Then the function returns ERROR_VALUE value.

const char *name
    name Argument in all this macroses is some string, description of reading, checking or skipping file field by instruction. If you want, then it is necessary code comments.

SKIP_STRING(const char *name, any_off_t len);
    is wrapper for the next type instructions: fd_seek(len, SEEK_CUR); with checking of out from bounds fd_size().

SKIP_*
    Other macroses for skipping of different type fields. It is similar to SKIP_STRING but skipping field length defined by type of skipping field, and there is not the second argument for it.

COND_STRING(const char *name, size_t len, CONDITION);
    Reads string with len length and check its CONDITION. Condition is some expression with using of val variable, in which it keeps value of string.

EX_STRING(const char *name, const char *string);
    Reads string and check if it match with string. Similar to the next call: COND_STRING(name, strlen(string), strcmp(val, string)==0);

LIST_STRING(const char *name, size_t len, {const char string_1[len+1], const char string_2[len+1], ..., NULL} );
    Reads string with len length and check if it match with one of strings in the list (the list must be in braces, consists from strings with len length and finish with NULL)

READ_*
    Macroses -- wrappers for correspondents read_* functions with exit if unsuccessful. Unlike the functions, it doesn't have argument -- buffer pointer, but it returns read value direct to the program.

COND_*
    Macroses for reading from file values with different types with check if CONDITION is true. The condition is some expression with using val variable in which it keeps read value before returning it to the program.

EX_*
    Macroses for reading from file different values and check if it equal to the value. It is the same as the next call: COND_*(name, val==value); By the way it returns the read value, but if the macroses return control to the program then returning value always equal value.

FUNCOVER(name, operation);
    All macroses above doesn't return control to the program at all in case of unsuccessful reading or false specified condition, but often if condition is false you don't need to return from format processor function -- but you may need to do anything else. In this case may be useful this macros. It put operation (operation group) in function wrapper: int name() { operation; return !ERROR_VALUE; } which in case of successful operation return !ERROR_VALUE And in case of unsuccessful operation return ERROR_VALUE

MAYBE(operation);
    Using FUNCOVER macros, you may now to get control back in the function independent from any condition, but the fd_seek pointer will be whipped -- it will points after all unsuccessful read values. Because MAYBE macros remember fd_seek pointer, execute operation and in case of ERROR_VALUE returning, it move fd_seek pointer back on position before operation execution. The operation returning value returns back to the program without modification.

FORMAT PROCESSOR MODULE EXAMPLES
The simple examples of format processors is MIDI and RAR format processors. The formats description you may find on http://www.wotsit.org. The functions (such as you may find it in anysurrect sources) see below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <anysurrect.h>
/*MIDI*/
const char* audio_MIDI_indicator="MIDI";
char *audio_MIDI_surrect()
{
	int res;
	unsigned short number_tracks;
	EX_STRING("header", "MThd");
	EX_BELONG("magic_number", 0x00000006);
	COND_BESHORT("FileFormat", val<=2);
	number_tracks =
		READ_BESHORT("NumberTracks");
	SKIP_BESHORT("ticks_per_note");

	for (int i=0; i<number_tracks; i++)
	{
		unsigned long	size;
		EX_STRING("track_header", "MTrk");
		size = READ_BELONG("track_size");
		SKIP_STRING("track_body", size);
	}
	return "audio/MIDI";
}
/*RAR*/
const char* archieve_RAR_indicator="RAR";
#define RAR_BLOCK ({                                                 \
	SKIP_LESHORT("crc");                                            \
	COND_BYTE("type", val>=0x72 && val<=0x7F);                      \
	uint16_t flags = READ_LESHORT("flags");                         \
	uint16_t size = READ_LESHORT("size");                           \
	uint32_t add_size=0;                                            \
	if (flags&0x8000)                                               \
	{ add_size=READ_LELONG("add_size")-4; }	                        \
	SKIP_STRING("data", add_size + size - 7);                       \
})
FUNCOVER(rar_block, RAR_BLOCK);
char *archieve_RAR_surrect()
{
	int res;
	EX_LESHORT("crc", 0x6152);
	EX_BYTE("type", 0x72);
	EX_LESHORT("flags", 0x1a21);
	EX_LESHORT("size", 0x0007);

	while( MAYBE( rar_block() )!=ERROR_VALUE );

	return "archieve/RAR";
}
You can build this functions by similar the next command:
$ gcc -std=gnu99 -nostdlib -shared -I /usr/local/include/anyfs-tools -o anysurrect_plug-in.so anysurrect_plug-in.c

After it you may plug-in and list exported by the module formats by the next way
$ /usr/local/sbin/anysurrect -g ./anysurrect_plug-in.so -l
anysurrect 0.84.5 (06 Aug 2006)
FILE SURRECTERS EXPORTED BY "anysurrect" MODULE:
archieve_BZIP2 archieve_RAR archieve_TAR archieve_ZIP audio_MIDI audio_MP3 audio_video_AVI audio_video_MPEG12PM audio_video_MPEG12 audio_video_OGG audio_WAV document_PDF executable_ELF32 filesystem_info_ext2fs_direct_blocks_links filesystem_info_ext2fs_double_indirect_blocks_links filesystem_info_ext2fs_indirect_blocks_links image_BMP image_JPEG image_PNG image_PNM image_TIFF text_ASCII text_EIGHT_BIT text_UTF16BE text_UTF16LE text_UTF8
FILE SURRECTERS EXPORTED BY "anysurrect_plug-in.so" MODULE:
archieve_RAR audio_MIDI
So as archieve_RAR and audio_MIDI format processors names in anysurrect matches with names in the module, then if you will try to run restoring at the first found and used will processors in anysurrect. Because don't write format processors with names same as in anysurrect.

AUTHOR
Nikolaj Krivchenkov aka unDEFER <undefer@gmail.com>

BUG REPORTS
Messages about any problem with using anyfs-tools package send to undefer@gmail.com

AVAILABILITY
You can obtain the last version of package at http://anyfs-tools.sourceforge.net

SEE ALSO
anyfs-tools(8), anysurrect(8), lseek(2), read(2)