return 0;
if (read(fd, sb, 1024) != 1024)
return 0;
- if (strncmp(sb+52, "ReIsErFs",8)!=0 &&
- strncmp(sb+52, "ReIsEr2Fs",9)!=0)
+ if (strncmp((char*)sb+52, "ReIsErFs",8)!=0 &&
+ strncmp((char*)sb+52, "ReIsEr2Fs",9)!=0)
return 0;
fprintf(stderr, Name ": %s appears to contain a reiserfs file system\n",name);
size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
return 1;
}
-int load_super(int fd, void **sbp, int vers)
-{
- return load_super0(fd, sbp, NULL);
-}
int check_raid(int fd, char *name)
{
void *super;
struct mdinfo info;
time_t crtime;
- if (load_super(fd, &super, -1))
- return 0;
+ struct supertype *st = guess_super(fd);
+
+ if (!st) return 0;
+ st->ss->load_super(st, fd, &super, name);
/* Looks like a raid array .. */
fprintf(stderr, Name ": %s appears to be part of a raid array:\n",
name);
- getinfo_super0(&info, super);
+ st->ss->getinfo_super(&info, super);
free(super);
crtime = info.array.ctime;
fprintf(stderr, " level=%d devices=%d ctime=%s",
return 1;
}
-
int ask(char *mesg)
{
char *add = "";
else if (strncmp(d, "/md", 3)==0)
d += 3, type=-1; /* /dev/mdN */
else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
- type = -1; /* /dev/md/N */
+ d += 1, type=-1; /* /dev/md/N */
else
return 0;
if (!*d)
/*
* Find a block device with the right major/minor number.
- * Avoid /dev/mdNN and /dev/md/dNN if possible
+ * If we find multiple names, choose the shortest.
+ * If we find a non-standard name, it is probably there
+ * deliberately so prefer it over a standard name.
+ * This applies only to names for MD devices.
*/
char *map_dev(int major, int minor)
{
struct devmap *p;
- char *std = NULL;
+ char *std = NULL, *nonstd=NULL;
if (!devlist_ready) {
#ifndef __dietlibc__
nftw("/dev", add_dev, 10, FTW_PHYS);
for (p=devlist; p; p=p->next)
if (p->major == major &&
p->minor == minor) {
- if (is_standard(p->name, NULL))
- std = p->name;
- else
- return p->name;
+ if (is_standard(p->name, NULL)) {
+ if (std == NULL ||
+ strlen(p->name) < strlen(std))
+ std = p->name;
+ } else {
+ if (nonstd == NULL ||
+ strlen(p->name) < strlen(nonstd))
+ nonstd = p->name;
+ }
}
- return std;
+ return nonstd ? nonstd : std;
}
#endif
for(i=0; i<bytes/4; i++)
newcsum+= superc[i];
csum = (newcsum& 0xffffffff) + (newcsum>>32);
+#ifdef __alpha__
+/* The in-kernel checksum calculation is always 16bit on
+ * the alpha, though it is 32 bit on i386...
+ * I wonder what it is elsewhere... (it uses and API in
+ * a way that it shouldn't).
+ */
+ csum = (csum & 0xffff) + (csum >> 16);
+ csum = (csum & 0xffff) + (csum >> 16);
+#endif
return csum;
}
char *human_size(long long bytes)
{
static char buf[30];
-
+
+ /* We convert bytes to either centi-M{ega,ibi}bytes or
+ * centi-G{igi,ibi}bytes, with appropriate rounding,
+ * and then print 1/100th of those as a decimal.
+ * We allow upto 2048Megabytes before converting to
+ * gigabytes, as that shows more precision and isn't
+ * too large a number.
+ * Terrabytes are not yet handled.
+ */
if (bytes < 5000*1024)
buf[0]=0;
- else if (bytes < 2*1024LL*1024LL*1024LL)
+ else if (bytes < 2*1024LL*1024LL*1024LL) {
+ long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
+ long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2;
sprintf(buf, " (%ld.%02ld MiB %ld.%02ld MB)",
- (long)(bytes>>20),
- (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100),
- (long)(bytes/1000/1000),
- (long)(((bytes%1000000)+5000)/10000)
- );
- else
+ cMiB/100 , cMiB % 100,
+ cMB/100, cMB % 100);
+ } else {
+ long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
+ long cGB = (bytes / (1000000000LL/200LL ) +1) /2;
sprintf(buf, " (%ld.%02ld GiB %ld.%02ld GB)",
- (long)(bytes>>30),
- (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100),
- (long)(bytes/1000LL/1000LL/1000LL),
- (long)((((bytes/1000)%1000000)+5000)/10000)
- );
+ cGiB/100 , cGiB % 100,
+ cGB/100, cGB % 100);
+ }
return buf;
}
if (strncmp(name, "/dev/.tmp.md", 12)==0)
unlink(name);
}
+
+
+
+
+struct superswitch *superlist[] = { &super0, &super1, NULL };
+
+struct supertype *super_by_version(int vers, int minor)
+{
+ struct supertype *st = malloc(sizeof(*st));
+ if (!st) return st;
+ if (vers == 0) {
+ st->ss = &super0;
+ st->max_devs = MD_SB_DISKS;
+ }
+
+ if (vers == 1) {
+ st->ss = &super1;
+ st->max_devs = 384;
+ }
+ st->minor_version = minor;
+ return st;
+}
+
+struct supertype *guess_super(int fd)
+{
+ /* try each load_super to find the best match,
+ * and return the best superswitch
+ */
+ struct superswitch *ss;
+ struct supertype *st;
+ unsigned long besttime = 0;
+ int bestsuper = -1;
+
+ void *sbp = NULL;
+ int i;
+
+ st = malloc(sizeof(*st));
+ memset(st, 0, sizeof(*st));
+ for (i=0 ; superlist[i]; i++) {
+ int rv;
+ ss = superlist[i];
+ rv = ss->load_super(st, fd, &sbp, NULL);
+ if (rv == 0) {
+ struct mdinfo info;
+ ss->getinfo_super(&info, sbp);
+ if (bestsuper == -1 ||
+ besttime < info.array.ctime) {
+ bestsuper = i;
+ besttime = info.array.ctime;
+ }
+ st->ss = NULL;
+ free(sbp);
+ }
+ }
+ if (bestsuper != -1) {
+ int rv;
+ rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
+ if (rv == 0) {
+ free(sbp);
+ return st;
+ }
+ }
+ free(st);
+ return NULL;
+}