blob: b5f50d3b205d43db4b129d71a4bda23a30b17808 [file] [log] [blame]
/*
* 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;
}