Split src/list.h in 3

This commit is contained in:
Christophe Grenier 2023-09-02 10:17:38 +02:00
parent 14210bd402
commit 0c9784cb76
7 changed files with 404 additions and 105 deletions

View file

@ -39,7 +39,7 @@ EXTRA_PROGRAMS = photorecf fuzzerfidentify
smallbase_C = common.c crc.c apfs_common.c ext2_common.c fat_common.c log.c misc.c setdate.c
smallbase_H = common.h crc.h apfs_common.h ext2_common.h fat_common.h log.h misc.h setdate.h
base_C = $(smallbase_C) autoset.c ewf.c fnctdsk.c hdaccess.c hdcache.c hdwin32.c hidden.c hpa_dco.c intrf.c iso.c list_sort.c log_part.c msdos.c parti386.c partgpt.c parthumax.c partmac.c partsun.c partnone.c partxbox.c io_redir.c ntfs_io.c ntfs_utl.c partauto.c sudo.c unicode.c win32.c
base_H = $(smallbase_H) alignio.h autoset.h ewf.h fnctdsk.h hdaccess.h hdwin32.h hidden.h guid_cmp.h guid_cpy.h hdcache.h hpa_dco.h intrf.h iso.h iso9660.h lang.h list.h list_sort.h log_part.h types.h io_redir.h msdos.h ntfs_utl.h parti386.h partgpt.h parthumax.h partmac.h partsun.h partxbox.h partauto.h sudo.h unicode.h win32.h
base_H = $(smallbase_H) apfs_common.h alignio.h autoset.h ewf.h fnctdsk.h hdaccess.h hdwin32.h hidden.h guid_cmp.h guid_cpy.h hdcache.h hpa_dco.h intrf.h iso.h iso9660.h lang.h list.h list_add_sorted.h list_add_sorted_uniq.h list_sort.h log_part.h types.h io_redir.h msdos.h ntfs_utl.h parti386.h partgpt.h parthumax.h partmac.h partsun.h partxbox.h partauto.h sudo.h unicode.h win32.h
fs_C = analyse.c apfs.c bfs.c bsd.c btrfs.c cramfs.c exfat.c ext2.c fat.c fatx.c f2fs.c jfs.c gfs2.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c refs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c vmfs.c wbfs.c xfs.c zfs.c
fs_H = analyse.h apfs.h bfs.h bsd.h btrfs.h cramfs.h exfat.h ext2.h fat.h fatx.h f2fs.h f2fs_fs.h jfs_superblock.h jfs.h gfs2.h hfs.h hfsp.h hpfs.h hfsp_struct.h luks.h luks_struct.h lvm.h md.h netware.h ntfs.h ntfs_struct.h refs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h vmfs.h wbfs.h xfs.h xfs_struct.h zfs.h

View file

@ -45,6 +45,72 @@
#include "common.h"
#include "log.h"
static int signature_cmp(const struct td_list_head *a, const struct td_list_head *b);
#ifndef __FRAMAC__
#include "list_add_sorted.h"
/*@ requires compar == signature_cmp; */
static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b));
#else
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires separation: \separated(newe, head);
@ requires list_separated(head->prev, newe);
@ requires list_separated(head, newe);
@ requires finite(head->prev);
@ requires finite(head);
@*/
static inline void td_list_add_sorted_sig(struct td_list_head *newe, struct td_list_head *head)
{
struct td_list_head *pos;
/*@
@ loop invariant \valid(pos);
@ loop invariant \valid(pos->prev);
@ loop invariant \valid(pos->next);
@ loop invariant pos == head || \separated(pos, head);
@ loop assigns pos;
@*/
td_list_for_each(pos, head)
{
/*@ assert \valid_read(newe); */
/*@ assert \valid_read(pos); */
if(signature_cmp(newe,pos)<0)
break;
}
if(pos != head)
{
__td_list_add(newe, pos->prev, pos);
}
else
{
/*@ assert finite(head->prev); */
/*@ assert finite(head); */
/*@ assert list_separated(head->prev, newe); */
/*@ assert list_separated(head, newe); */
td_list_add_tail(newe, head);
}
}
#endif
#if 0
/*@ requires valid_string_s: valid_read_string(s);
@ ensures valid_string(\result);
@*/
static char *td_strdup(const char *s)
{
size_t l = strlen(s) + 1;
char *p = (char *)MALLOC(l);
/*@ assert valid_read_string(s); */
memcpy(p, s, l);
p[l-1]='\0';
/*@ assert valid_read_string(p); */
return p;
}
#endif
/*@ requires valid_register_header_check(file_stat); */
static void register_header_check_sig(file_stat_t *file_stat);
const file_hint_t file_hint_sig= {
@ -65,7 +131,7 @@ struct signature_s
{
struct td_list_head list;
const char *extension;
const unsigned char *sig;
const char *sig;
unsigned int sig_size;
unsigned int offset;
};
@ -86,21 +152,25 @@ static signature_t signatures={
.list = TD_LIST_HEAD_INIT(signatures.list)
};
#ifndef __FRAMAC__
static
#endif
int signature_cmp(const struct td_list_head *a, const struct td_list_head *b)
/*@
@ assigns \nothing;
@*/
static int signature_cmp(const struct td_list_head *a, const struct td_list_head *b)
{
const signature_t *sig_a=td_list_entry_const(a, const signature_t, list);
const signature_t *sig_b=td_list_entry_const(b, const signature_t, list);
int res;
/*@ assert \valid_read(sig_a); */
/*@ assert \valid_read(sig_b); */
/*@ assert valid_signature(sig_a); */
/*@ assert valid_signature(sig_b); */
if(sig_a->sig_size==0 && sig_b->sig_size!=0)
return -1;
if(sig_a->sig_size!=0 && sig_b->sig_size==0)
return 1;
res=sig_a->offset-sig_b->offset;
/*@ assert 0 <= sig_a->offset <= PHOTOREC_MAX_SIG_OFFSET; */
/*@ assert 0 <= sig_b->offset <= PHOTOREC_MAX_SIG_OFFSET; */
res=(int)sig_a->offset - (int)sig_b->offset;
if(res!=0)
return res;
if(sig_a->sig_size<=sig_b->sig_size)
@ -133,8 +203,9 @@ static void signature_insert(const char *ext, unsigned int offset, const void*si
/*@ assert \valid_read((const char *)sig+(0..sig_size-1)); */
/*@ assert valid_read_string(ext); */
newsig=(signature_t*)MALLOC(sizeof(*newsig));
/*@ assert \valid(newsig); */
newsig->extension=ext;
newsig->sig=(const unsigned char *)sig;
newsig->sig=(const char *)sig;
newsig->sig_size=sig_size;
newsig->offset=offset;
/*@ assert newsig->sig_size == sig_size; */
@ -153,7 +224,11 @@ static void signature_insert(const char *ext, unsigned int offset, const void*si
/*@ assert \valid_read((const char *)newsig->sig+(0..newsig->sig_size-1)); */
/*@ assert valid_signature(newsig); */
#ifdef __FRAMAC__
td_list_add_sorted_sig(&newsig->list, &signatures.list);
#else
td_list_add_sorted(&newsig->list, &signatures.list, signature_cmp);
#endif
}
/*@
@ -165,10 +240,14 @@ static void signature_insert(const char *ext, unsigned int offset, const void*si
static int header_check_sig(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
struct td_list_head *pos;
/*@ loop assigns pos; */
/*@
@ loop invariant \valid(pos);
@ loop assigns pos;
@*/
td_list_for_each(pos, &signatures.list)
{
const signature_t *sig = td_list_entry(pos, signature_t, list);
/*@ assert \valid_read(sig); */
/*@ assert sig->offset + sig->sig_size <= buffer_size; */
/*@ assert valid_read_string(sig->extension); */
/*@ assert valid_signature(sig); */

View file

@ -46,6 +46,57 @@
#include "filegen.h"
#include "log.h"
static int file_check_cmp(const struct td_list_head *a, const struct td_list_head *b);
#ifndef __FRAMAC__
#include "list_add_sorted.h"
/*@ requires compar == file_check_cmp; */
static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b));
#else
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires separation: \separated(newe, head);
@ requires list_separated(head->prev, newe);
@ requires list_separated(head, newe);
@ requires finite(head->prev);
@ requires finite(head);
@*/
static inline void td_list_add_sorted_fcc(struct td_list_head *newe, struct td_list_head *head)
{
struct td_list_head *pos;
/*@
@ loop invariant \valid(pos);
@ loop invariant \valid(pos->prev);
@ loop invariant \valid(pos->next);
@ loop invariant pos == head || \separated(pos, head);
@ loop assigns pos;
@*/
td_list_for_each(pos, head)
{
/*@ assert \valid_read(newe); */
/*@ assert \valid_read(pos); */
if(file_check_cmp(newe,pos)<0)
break;
}
if(pos != head)
{
__td_list_add(newe, pos->prev, pos);
}
else
{
/*@ assert finite(head->prev); */
/*@ assert finite(head); */
/*@ assert list_separated(head->prev, newe); */
/*@ assert list_separated(head, newe); */
td_list_add_tail(newe, head);
}
}
#endif
uint64_t gpls_nbr=0;
static uint64_t offset_skipped_header=0;
@ -57,16 +108,12 @@ file_check_list_t file_check_list={
.list = TD_LIST_HEAD_INIT(file_check_list.list)
};
// X requires \valid_read(b);
/*@
@ requires \valid_read(a);
@ requires \valid_read(b);
@ assigns \nothing;
@*/
#ifndef DISABLED_FOR_FRAMAC
static
#endif
int file_check_cmp(const struct td_list_head *a, const struct td_list_head *b)
static int file_check_cmp(const struct td_list_head *a, const struct td_list_head *b)
{
#ifdef DISABLED_FOR_FRAMAC
return 1;
@ -149,6 +196,7 @@ void register_header_check(const unsigned int offset, const void *value, const u
file_stat_t *file_stat)
{
file_check_t *file_check_new=(file_check_t *)MALLOC(sizeof(*file_check_new));
/*@ assert \valid(file_check_new); */
file_check_new->value=value;
file_check_new->length=length;
file_check_new->offset=offset;
@ -166,7 +214,11 @@ void register_header_check(const unsigned int offset, const void *value, const u
/*@ assert \valid(file_check_new->file_stat); */
/*@ assert valid_file_check_node(file_check_new); */
#ifdef __FRAMAC__
td_list_add_sorted_fcc(&file_check_new->list, &file_check_plist.list);
#else
td_list_add_sorted(&file_check_new->list, &file_check_plist.list, file_check_cmp);
#endif
}
/*@
@ -187,9 +239,14 @@ static void index_header_check_aux(file_check_t *file_check_new)
if(pos->offset >= file_check_new->offset &&
pos->offset < file_check_new->offset+file_check_new->length)
{
#ifdef __FRAMAC__
td_list_add_sorted_fcc(&file_check_new->list,
&pos->file_checks[((const unsigned char *)file_check_new->value)[pos->offset-file_check_new->offset]].list);
#else
td_list_add_sorted(&file_check_new->list,
&pos->file_checks[((const unsigned char *)file_check_new->value)[pos->offset-file_check_new->offset]].list,
file_check_cmp);
#endif
return ;
}
if(pos->offset>file_check_new->offset)
@ -319,6 +376,7 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
memset(&buffer[4096],0,footer_length-1);
/*@
@ loop invariant 0 <= offset <= \at(offset, Pre);
@ loop invariant offset <= PHOTOREC_MAX_FILE_SIZE;
@ loop assigns errno, *handle, Frama_C_entropy_source;
@ loop assigns offset, buffer[0 .. 8192-1];
@ loop variant offset;
@ -333,6 +391,7 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
offset-=4096;
else
offset=offset-(offset%4096);
/*@ assert offset + 4096 <= PHOTOREC_MAX_FILE_SIZE; */
if(my_fseek(handle,offset,SEEK_SET)<0)
return 0;
taille=fread(&buffer, 1, 4096, handle);
@ -342,9 +401,13 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
#ifdef __FRAMAC__
Frama_C_make_unknown(&buffer, 4096);
#endif
/*@ loop assigns i; */
/*@
@ loop invariant -1 <= i < taille;
@ loop assigns i;
@*/
for(i=taille-1;i>=0;i--)
{
/*@ assert offset + i <= PHOTOREC_MAX_FILE_SIZE; */
if(buffer[i]==*(const char *)footer && memcmp(&buffer[i],footer,footer_length)==0)
{
return offset + i;
@ -357,17 +420,25 @@ uint64_t file_rsearch(FILE *handle, uint64_t offset, const void*footer, const un
void file_search_footer(file_recovery_t *file_recovery, const void*footer, const unsigned int footer_length, const unsigned int extra_length)
{
/*@ assert \valid(file_recovery); */
if(footer_length==0 || file_recovery->file_size <= extra_length)
return ;
file_recovery->file_size=file_rsearch(file_recovery->handle, file_recovery->file_size-extra_length, footer, footer_length);
/*@ assert 0 < footer_length < 4096; */
/*@ assert extra_length <= PHOTOREC_MAX_FILE_SIZE; */
/*@ assert file_recovery->file_size < 0x8000000000000000; */
if(file_recovery->file_size > 0)
file_recovery->file_size+= footer_length + extra_length;
file_recovery->file_size+= (uint64_t)footer_length + extra_length;
/*@ assert \valid(file_recovery->handle); */
/*@ assert valid_file_check_result(file_recovery); */
}
data_check_t data_check_size(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
/*@ assert \valid_read(file_recovery); */
/*@ assert valid_file_recovery(file_recovery); */
/*@ assert file_recovery->file_size <= PHOTOREC_MAX_FILE_SIZE; */
/*@ assert buffer_size <= 2 * PHOTOREC_MAX_BLOCKSIZE; */
if(file_recovery->file_size + buffer_size/2 >= file_recovery->calculated_file_size)
{
/*@ assert valid_file_recovery(file_recovery); */
@ -379,6 +450,7 @@ data_check_t data_check_size(const unsigned char *buffer, const unsigned int buf
void file_check_size(file_recovery_t *file_recovery)
{
/*@ assert \valid(file_recovery); */
if(file_recovery->file_size<file_recovery->calculated_file_size)
file_recovery->file_size=0;
else
@ -388,6 +460,7 @@ void file_check_size(file_recovery_t *file_recovery)
void file_check_size_min(file_recovery_t *file_recovery)
{
/*@ assert \valid(file_recovery); */
if(file_recovery->file_size<file_recovery->calculated_file_size)
file_recovery->file_size=0;
/*@ assert valid_file_check_result(file_recovery); */
@ -395,6 +468,7 @@ void file_check_size_min(file_recovery_t *file_recovery)
void file_check_size_max(file_recovery_t *file_recovery)
{
/*@ assert \valid(file_recovery); */
if(file_recovery->file_size > file_recovery->calculated_file_size)
file_recovery->file_size=file_recovery->calculated_file_size;
/*@ assert valid_file_check_result(file_recovery); */
@ -528,11 +602,14 @@ static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext)
/*@
@ requires \valid(file_recovery);
@ requires strlen((char*)&file_recovery->filename) < 1<<30;
@ requires valid_file_recovery(file_recovery);
@ requires valid_read_string((char*)&file_recovery->filename);
@ requires 0 <= offset < buffer_size;
@ requires buffer_size < 1<<30;
@ requires \valid_read((char *)buffer+(0..buffer_size-1));
@ requires new_ext==\null || valid_read_string(new_ext);
@ ensures new_ext==\null || valid_read_string(new_ext);
@ requires new_ext==\null || (valid_read_string(new_ext) && strlen(new_ext) < 1<<30);
@ ensures new_ext==\null || (valid_read_string(new_ext) && strlen(new_ext) < 1<<30);
@ ensures valid_file_recovery(file_recovery);
@*/
static int _file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
@ -542,7 +619,7 @@ static int _file_rename(file_recovery_t *file_recovery, const void *buffer, cons
const char *ext=NULL;
char *dst;
char *directory_sep;
int len;
size_t len;
len=strlen(src)+1;
/*@ assert offset < buffer_size; */
len+=buffer_size-offset+1;
@ -667,11 +744,14 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu
/* The original filename begins at offset in buffer and is null terminated */
/*@
@ requires \valid(file_recovery);
@ requires strlen((char*)&file_recovery->filename) < 1<<30;
@ requires valid_file_recovery(file_recovery);
@ requires valid_read_string((char*)&file_recovery->filename);
@ requires 0 <= offset < buffer_size;
@ requires buffer_size < 1<<30;
@ requires \valid_read((char *)buffer+(0..buffer_size-1));
@ requires new_ext==\null || valid_read_string(new_ext);
@ requires new_ext==\null || (valid_read_string(new_ext) && strlen(new_ext) < 1<<30);
@ ensures new_ext==\null || (valid_read_string(new_ext) && strlen(new_ext) < 1<<30);
@ ensures valid_read_string((char*)&file_recovery->filename);
@ ensures valid_file_recovery(file_recovery);
@*/
@ -682,7 +762,7 @@ static int _file_rename_unicode(file_recovery_t *file_recovery, const void *buff
const char *src_ext=src;
char *dst;
char *dst_dir_sep;
int len=strlen(src)+1;
size_t len=strlen(src)+1;
/*@ assert offset < buffer_size; */
len+=buffer_size-offset;
if(new_ext!=NULL)
@ -855,6 +935,7 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery
}
/*@
@ requires file_recovery_new == \null || \valid_read(file_recovery_new);
@ requires \separated(file_recovery_new, &offset_skipped_header);
@ assigns offset_skipped_header;
@*/
@ -865,6 +946,7 @@ void header_ignored(const file_recovery_t *file_recovery_new)
offset_skipped_header=0;
return ;
}
/*@ assert \valid_read(file_recovery_new); */
if(file_recovery_new->location.start < offset_skipped_header || offset_skipped_header==0)
offset_skipped_header=file_recovery_new->location.start;
}
@ -878,13 +960,18 @@ void get_prev_location_smart(const alloc_data_t *list_search_space, alloc_data_t
alloc_data_t *file_space=*current_search_space;
if(offset_skipped_header==0)
return ;
#ifndef __FRAMAC__
gpls_nbr++;
#endif
/*@
@ loop invariant \valid_read(file_space);
@ loop invariant \separated(file_space, current_search_space, offset);
@ loop assigns file_space, offset_skipped_header, *current_search_space, *offset;
@*/
while(1)
{
file_space=td_list_prev_entry(file_space, list);
/*@ assert \valid_read(file_space); */
if(file_space==list_search_space)
break;
if(file_space->start <= offset_skipped_header && offset_skipped_header < file_space->end)
@ -903,11 +990,14 @@ void get_prev_location_smart(const alloc_data_t *list_search_space, alloc_data_t
(long long unsigned)(*offset/512));
#endif
/*@
@ loop invariant \valid_read(file_space);
@ loop invariant \separated(file_space, current_search_space, offset);
@ loop assigns file_space, offset_skipped_header, *current_search_space, *offset;
@*/
while(1)
{
file_space=td_list_prev_entry(file_space, list);
/*@ assert \valid_read(file_space); */
if(file_space==list_search_space)
{
offset_skipped_header=0;

View file

@ -21,6 +21,7 @@
*/
#ifndef _LIST_H
#define _LIST_H
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
@ -44,37 +45,42 @@ struct td_list_head {
struct td_list_head *next, *prev;
};
#ifdef __FRAMAC__
/*@
@ requires \valid_read(a);
@ requires \valid_read(b);
@ assigns \nothing;
@*/
int file_check_cmp(const struct td_list_head *a, const struct td_list_head *b);
/*@
@ assigns \nothing;
@*/
int signature_cmp(const struct td_list_head *a, const struct td_list_head *b);
#endif
/*@
inductive reachable{L}(struct td_list_head *root, struct td_list_head *node) {
case root_reachable{L}:
\forall struct td_list_head *root; reachable(root,root) ;
inductive reachable_forward{L}(struct td_list_head *root, struct td_list_head *node) {
case root_reachable_forward{L}:
\forall struct td_list_head *root; reachable_forward(root,root) ;
case next_reachable{L}:
\forall struct td_list_head *root,*node;
\valid(root) && reachable(root->next,node) ==> reachable(root,node);
\valid(root) && reachable_forward(root->next,node) ==> reachable_forward(root,node);
}
inductive reachable_backward{L}(struct td_list_head *root, struct td_list_head *node) {
case root_reachable_backward{L}:
\forall struct td_list_head *root; reachable_backward(root,root) ;
case prev_reachable{L}:
\forall struct td_list_head *root,*node;
\valid(root) && reachable_backward(root->prev,node) ==> reachable_backward(root,node);
}
@*/
// root->next->prev == root
/*@ predicate finite{L}(struct td_list_head *root) = reachable(root->next,root); */
/*@ predicate finite{L}(struct td_list_head *root) = reachable_forward(root->next,root) && reachable_backward(root->prev,root); */
/*
\forall struct td_list_head *l1;
reachable(l, l1) && \valid(l1) ==> \valid(l1->next) && l1->next->prev == l1;
*/
/*@ inductive list_separated3{L}(struct td_list_head *root, struct td_list_head *node, struct td_list_head *elt) {
case node_is_root{L}:
\forall struct td_list_head *root, *elt; \separated(root, elt) ==> list_separated3(root, root, elt);
case node_reachable{L}:
\forall struct td_list_head *root, *node, *elt;
\valid(node) && \separated(node, elt) && list_separated3(root, node->next, elt) ==> list_separated3(root, node, elt);
}
*/
/*@ predicate list_separated{L}(struct td_list_head *root, struct td_list_head *elt) = list_separated3(root, root->next, elt); */
#define TD_LIST_HEAD_INIT(name) { &(name), &(name) }
@ -97,10 +103,16 @@ int signature_cmp(const struct td_list_head *a, const struct td_list_head *b);
@ requires \valid(next);
@ requires separation: \separated(newe, \union(prev,next));
@ requires prev == next || \separated(prev,next,newe);
@ ensures next->prev == newe;
@ ensures newe->next == next;
@ ensures newe->prev == prev;
@ requires finite(prev);
@ requires finite(next);
@ requires prev->next == next;
@ requires next->prev == prev;
@ requires list_separated(prev, newe);
@ requires list_separated(next, newe);
@ ensures prev->next == newe;
@ ensures newe->prev == prev;
@ ensures newe->next == next;
@ ensures next->prev == newe;
@ ensures newe->next->prev == newe;
@ ensures newe->prev->next == newe;
@ assigns next->prev,newe->next,newe->prev,prev->next;
@ -109,14 +121,24 @@ static inline void __td_list_add(struct td_list_head *newe,
struct td_list_head *prev,
struct td_list_head *next)
{
/*@ assert finite(prev); */
/*@ assert finite(next); */
/*@ assert reachable_forward(prev->next,prev); */
/*@ assert reachable_forward(next->next,next); */
/*@ assert reachable_backward(prev->prev,prev); */
/*@ assert reachable_backward(next->prev,next); */
/*@ assert reachable_forward(next,prev); */
newe->next = next;
newe->prev = prev;
next->prev = newe;
prev->next = newe;
next->prev = newe;
/*@ assert next->prev == newe; */
/*@ assert newe->next == next; */
/*@ assert newe->prev == prev; */
/*@ assert prev->next == newe; */
/*@ assert reachable_forward(prev,newe); */
/*@ assert reachable_backward(next,newe); */
}
/**
@ -132,6 +154,9 @@ static inline void __td_list_add(struct td_list_head *newe,
@ requires \valid(head);
@ requires \valid(head->next);
@ requires separation: \separated(newe, \union(head,head->next));
@ requires finite(head);
@ requires finite(head->next);
@ requires list_separated(head, newe);
@ ensures head->next == newe;
@ ensures newe->prev == head;
@ ensures newe->next == \old(head->next);
@ -155,8 +180,13 @@ static inline void td_list_add(struct td_list_head *newe, struct td_list_head *h
@ requires \valid(newe);
@ requires \valid(head);
@ requires \valid(head->prev);
@ requires separation: \separated(newe, head);
@ requires \separated(newe, \union(head->prev, head));
@ requires head->prev == head || \separated(head->prev, head, newe);
@ requires finite(head->prev);
@ requires list_separated(head->prev, newe);
@ requires list_separated(head, newe);
@ requires finite(head);
@ ensures head->prev == newe;
@ ensures newe->next == head;
@ ensures newe->prev == \old(head->prev);
@ -218,6 +248,7 @@ static inline void td_list_del(struct td_list_head *entry)
/*@ assert \at(entry->next,Pre)->prev == \at(entry->prev,Pre); */
}
#if 0
/**
* td_list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
@ -227,7 +258,9 @@ static inline void td_list_del_init(struct td_list_head *entry)
__td_list_del(entry->prev, entry->next);
TD_INIT_LIST_HEAD(entry);
}
#endif
#if 0
/**
* td_list_move - delete from one list and add as another's head
* @list: the entry to move
@ -250,6 +283,7 @@ static inline void td_list_move_tail(struct td_list_head *list,
__td_list_del(list->prev, list->next);
td_list_add_tail(list, head);
}
#endif
/**
* td_list_empty - tests whether a list is empty
@ -264,6 +298,7 @@ static inline int td_list_empty(const struct td_list_head *head)
return head->next == head;
}
#if 0
/**
* td_list_empty_careful - tests whether a list is
* empty _and_ checks that no other CPU might be
@ -322,6 +357,7 @@ static inline void td_list_splice_init(struct td_list_head *list,
TD_INIT_LIST_HEAD(list);
}
}
#endif
/**
* td_list_entry - get the struct for this entry
@ -473,67 +509,6 @@ static inline void td_list_splice_init(struct td_list_head *list,
td_list_entry((pos)->member.prev, typeof(*(pos)), member)
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires \valid_function(compar);
@ requires compar == signature_cmp || compar == file_check_cmp;
@ requires separation: \separated(newe, head);
@*/
static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
struct td_list_head *pos;
/*@
@ loop invariant pos == head || \separated(pos, head);
@ loop invariant compar == signature_cmp || compar == file_check_cmp;
@*/
td_list_for_each(pos, head)
{
/*@ assert compar == signature_cmp || compar == file_check_cmp; */
/*@ assert \valid_read(newe); */
/*@ assert \valid_read(pos); */
if(compar(newe,pos)<0)
{
__td_list_add(newe, pos->prev, pos);
return ;
}
}
td_list_add_tail(newe, head);
}
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires \valid_function(compar);
@ requires separation: \separated(newe, head);
@*/
static inline int td_list_add_sorted_uniq(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
struct td_list_head *pos;
/*@
@ loop invariant pos == head || \separated(pos, head);
@ loop invariant \valid_function(compar);
@ loop assigns pos;
@*/
td_list_for_each(pos, head)
{
// TODO const
/* calls spacerange_cmp; */
int res=compar(newe,pos);
if(res<0)
{
__td_list_add(newe, pos->prev, pos);
return 0;
}
else if(res==0)
return 1;
}
td_list_add_tail(newe, head);
return 0;
}
typedef struct alloc_list_s alloc_list_t;
struct alloc_list_s
{

80
src/list_add_sorted.h Normal file
View file

@ -0,0 +1,80 @@
/*
File: list_add_sorted.h
Copyright (C) 2006-2008 Christophe GRENIER <grenier@cgsecurity.org>
This software is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _LIST_ADD_SORTED_UNIQ_H
#define _LIST_ADD_SORTED_UNIQ_H
/*
X requires finite(head);
X ensures finite(head);
X ensures finite(newe);
X ensures reachable(head,newe);
*/
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires \valid_function(compar);
@ requires separation: \separated(newe, head);
@ requires list_separated(head->prev, newe);
@ requires list_separated(head, newe);
@ requires finite(head->prev);
@ requires finite(head);
@*/
static inline void td_list_add_sorted(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
struct td_list_head *pos;
/*@
@ loop invariant \valid(pos);
@ loop invariant \valid(pos->prev);
@ loop invariant \valid(pos->next);
@ loop invariant pos == head || \separated(pos, head);
@ loop invariant \valid_function(compar);
@ loop assigns pos;
@*/
/*
X loop invariant finite(head->prev);
X loop invariant finite(head);
*/
td_list_for_each(pos, head)
{
/*@ assert \valid_function(compar); */
/*@ assert \valid_read(newe); */
/*@ assert \valid_read(pos); */
if(compar(newe,pos)<0)
break;
}
if(pos != head)
{
__td_list_add(newe, pos->prev, pos);
}
else
{
/*@ assert finite(head->prev); */
/*@ assert finite(head); */
/*@ assert list_separated(head->prev, newe); */
/*@ assert list_separated(head, newe); */
td_list_add_tail(newe, head);
}
/*X assert finite(head); */
/*X assert finite(newe); */
}
#endif

View file

@ -0,0 +1,74 @@
/*
File: list_add_sorted_uniq.h
Copyright (C) 2006-2008 Christophe GRENIER <grenier@cgsecurity.org>
This software is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _LIST_ADD_SORTED_UNIQ_H
#define _LIST_ADD_SORTED_UNIQ_H
/*@
@ requires \valid(newe);
@ requires \valid(head);
@ requires \valid_function(compar);
@ requires finite(head->prev);
@ requires finite(head);
@ requires separation: \separated(newe, head);
@ requires list_separated(head, newe);
@*/
static inline int td_list_add_sorted_uniq(struct td_list_head *newe, struct td_list_head *head,
int (*compar)(const struct td_list_head *a, const struct td_list_head *b))
{
struct td_list_head *pos;
/*@
@ loop invariant \valid(pos);
@ loop invariant \valid(pos->prev);
@ loop invariant \valid(pos->next);
@ loop invariant pos == head || \separated(pos, head);
@ loop invariant \valid_function(compar);
@ loop invariant finite(head->prev);
@ loop invariant finite(head);
@ loop invariant finite(pos->prev);
@ loop invariant finite(pos);
@ loop assigns pos;
@*/
td_list_for_each(pos, head)
{
/*@ assert \valid_function(compar); */
// TODO const
/* calls spacerange_cmp; */
int res=compar(newe,pos);
/*@ assert \valid(pos); */
/*@ assert \valid(pos->prev); */
/*@ assert \valid(pos->next); */
if(res<0)
{
__td_list_add(newe, pos->prev, pos);
return 0;
}
else if(res==0)
return 1;
}
/*@ assert finite(head->prev); */
/*@ assert finite(head); */
/*@ assert list_separated(head->prev, newe); */
/*@ assert list_separated(head, newe); */
td_list_add_tail(newe, head);
return 0;
}
#endif

View file

@ -42,6 +42,7 @@ extern int need_to_stop;
#include "geometry.h"
#include "poptions.h"
#include "phcli.h"
#include "list_add_sorted_uniq.h"
typedef enum { INIT_SPACE_WHOLE, INIT_SPACE_PREINIT, INIT_SPACE_EXT2_GROUP, INIT_SPACE_EXT2_INODE } init_mode_t;