diff options
Diffstat (limited to 'perl-install/resize_fat/c_rewritten.xs')
-rw-r--r-- | perl-install/resize_fat/c_rewritten.xs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/perl-install/resize_fat/c_rewritten.xs b/perl-install/resize_fat/c_rewritten.xs new file mode 100644 index 000000000..a42f3d133 --- /dev/null +++ b/perl-install/resize_fat/c_rewritten.xs @@ -0,0 +1,90 @@ +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +/* set by scan_fat, used by next */ +short *fat = NULL; +int type_size, nb_clusters, bad_cluster_value; +char *fat_flag_map; + +unsigned int next(unsigned int cluster) { + short *p = fat + type_size * cluster; + if (cluster > nb_clusters + 2) croak("fat::next: cluster %d outside filesystem", cluster); + return type_size == 1 ? *p : *((unsigned int *) p); +} + +MODULE = resize_fat::c_rewritten PACKAGE = resize_fat::c_rewritten + +void +scan_fat(fat_, nb_clusters_, type_size_) + char *fat_ + int nb_clusters_ + int type_size_ + PPCODE: + unsigned int v; + int free = 0, bad = 0, used = 0; + short *p; + + fat = (short*) fat_; type_size = type_size_; nb_clusters = nb_clusters_; + bad_cluster_value = type_size ? 0xffffff7 : 0xfff7; + + if (type_size % 16) fprintf(stderr, "unable to handle type_size"), exit(1); + type_size /= 16; + + for (p = fat + 2 * type_size; p < fat + type_size * (nb_clusters + 2); p += type_size) { + v = type_size == 1 ? *p : *((unsigned int *) p); + + if (v == 0) free++; + else if (v == bad_cluster_value) bad++; + } + used = nb_clusters - free - bad; + EXTEND(SP, 3); + PUSHs(sv_2mortal(newSViv(free))); + PUSHs(sv_2mortal(newSViv(bad))); + PUSHs(sv_2mortal(newSViv(used))); + +unsigned int +next(unused, cluster) + void *unused + unsigned int cluster + CODE: + RETVAL = next(cluster); + OUTPUT: + RETVAL + +int +checkFat(fat_flag_map_, cluster, type, name) + char *fat_flag_map_ + unsigned int cluster + int type + char *name + CODE: + int nb = 0; + fat_flag_map = fat_flag_map_; + + for (; cluster < bad_cluster_value; cluster = next(cluster)) { + if (cluster == 0) croak("Bad FAT: unterminated chain for %s\n", name); + + if (fat_flag_map[cluster]) croak("Bad FAT: cluster $cluster is cross-linked for %s\n", name); + fat_flag_map[cluster] = type; + nb++; + } + RETVAL = nb; + OUTPUT: + RETVAL + +unsigned int +flag(cluster) + unsigned int cluster + CODE: + RETVAL = fat_flag_map[cluster]; + OUTPUT: + RETVAL + +void +set_flag(cluster, flag) + unsigned int cluster + int flag + CODE: + fat_flag_map[cluster] = flag; + |