201 lines
4.0 KiB
C
201 lines
4.0 KiB
C
/*
|
|
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "misc/malloc.h"
|
|
#include "misc/misc.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
#include <string.h>
|
|
|
|
void misc_die (char * fmt, ...)
|
|
{
|
|
static char buf[4096];
|
|
va_list args;
|
|
|
|
va_start (args, fmt);
|
|
vsprintf (buf, fmt, args);
|
|
va_end (args);
|
|
|
|
fprintf (stderr, "\n%s\n", buf);
|
|
abort ();
|
|
}
|
|
|
|
|
|
__u32 misc_random (void)
|
|
{
|
|
srandom (time (0));
|
|
return random ();
|
|
}
|
|
|
|
/* this implements binary search in the array 'base' among 'num' elements each
|
|
of those is 'width' bytes long. 'comp_func' is used to compare keys */
|
|
int misc_bin_search (const void * key, void * base, __u32 num, int width,
|
|
int * ppos, misc_comp_func_t comp_func)
|
|
{
|
|
__u32 rbound, lbound, j;
|
|
int ret;
|
|
|
|
if (num == 0 || base == NULL) {
|
|
/* objectid map may be 0 elements long */
|
|
*ppos = 0;
|
|
return 0;
|
|
}
|
|
|
|
lbound = 0;
|
|
rbound = num - 1;
|
|
|
|
for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
|
|
ret = comp_func ((void *)((char *)base + j * width), key ) ;
|
|
if (ret < 0) { /* second is greater */
|
|
lbound = j + 1;
|
|
continue;
|
|
|
|
} else if (ret > 0) { /* first is greater */
|
|
if (j == 0)
|
|
break;
|
|
rbound = j - 1;
|
|
continue;
|
|
} else { /* equal */
|
|
*ppos = j;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
*ppos = lbound;
|
|
return 0;
|
|
}
|
|
|
|
|
|
#define BLOCKLIST__ELEMENT_NUMBER 10
|
|
|
|
/*element is block number and device*/
|
|
int blockdev_list_compare (const void * block1, const void * block2) {
|
|
if (*(__u32 *)block1 < *(__u32 *)block2)
|
|
return -1;
|
|
if (*(__u32 *)block1 > *(__u32 *)block2)
|
|
return 1;
|
|
|
|
if (*((__u32 *)block1 + 1) < *((__u32 *)block2 + 1))
|
|
return -1;
|
|
if (*((__u32 *)block1 + 1) > *((__u32 *)block2 + 1))
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void blocklist__insert_in_position (void *elem, void **base, __u32 *count,
|
|
int elem_size, int *position)
|
|
{
|
|
if (elem_size == 0)
|
|
return;
|
|
|
|
if (*base == NULL)
|
|
*base = misc_getmem (BLOCKLIST__ELEMENT_NUMBER * elem_size);
|
|
|
|
if (*count == misc_memsize((void *)*base) / elem_size)
|
|
*base = misc_expandmem (*base, misc_memsize((void *)*base),
|
|
BLOCKLIST__ELEMENT_NUMBER * elem_size);
|
|
|
|
if (*position < *count) {
|
|
memmove (*base + (*position + 1),
|
|
*base + (*position),
|
|
(*count - *position) * elem_size);
|
|
}
|
|
|
|
memcpy (*base + (char) *position * elem_size, elem, elem_size);
|
|
*count+=1;
|
|
}
|
|
|
|
int misc_device_rdev_match(char *path, void *data) {
|
|
dev_t *rdev = (dev_t *)data;
|
|
struct stat st;
|
|
|
|
/* If stat fails just continue walking. */
|
|
if (stat(path, &st))
|
|
return 0;
|
|
|
|
/* Only block files are interesting. */
|
|
if (!S_ISBLK(st.st_mode))
|
|
return 0;
|
|
|
|
/* Matched rdev wanted. */
|
|
if (st.st_rdev != *rdev)
|
|
return 0;
|
|
|
|
/* Stop walking. */
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* The method walks through all subtree of the path,
|
|
open all directories and walk through them recursevely.
|
|
|
|
Return values:
|
|
positive: stop walking;
|
|
negative: error occured.
|
|
*/
|
|
int misc_dir_walk(char *path, dir_walk_func_t func, void *data) {
|
|
struct dirent *dirent;
|
|
struct stat st;
|
|
off_t pos;
|
|
DIR *dir;
|
|
int len;
|
|
int res;
|
|
|
|
strcat(path, "/");
|
|
|
|
if (!(dir = opendir(path)))
|
|
return 0;
|
|
|
|
len = strlen(path);
|
|
|
|
while ((dirent = readdir(dir)) != NULL) {
|
|
path[len] = 0;
|
|
|
|
if (strcmp(dirent->d_name, ".") == 0 ||
|
|
strcmp(dirent->d_name, "..") == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
strcat(path, dirent->d_name);
|
|
|
|
if ((res = func(path, data))) {
|
|
closedir(dir);
|
|
return res;
|
|
}
|
|
|
|
if (stat(path, &st) != 0)
|
|
continue;
|
|
|
|
if ((S_ISDIR(st.st_mode))) {
|
|
pos = telldir(dir);
|
|
closedir(dir);
|
|
|
|
if ((res = misc_dir_walk(path, func, data)))
|
|
return res;
|
|
|
|
path[len] = 0;
|
|
if (!(dir = opendir(path)))
|
|
return -1;
|
|
|
|
seekdir(dir, pos);
|
|
}
|
|
}
|
|
|
|
closedir(dir);
|
|
return 0;
|
|
}
|
|
|