From bb2962385214cdcca81813d818ae6250c9fd63b0 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Tue, 9 Oct 2001 16:13:12 +0000 Subject: [PATCH] o dev-mgr disappears --- lib/dev-mgr/dev-cache.c | 272 --------------------- lib/dev-mgr/dev-cache.h | 57 ----- lib/dev-mgr/dev-manager.c | 496 -------------------------------------- lib/dev-mgr/dev-manager.h | 42 ---- lib/dev-mgr/hash.c | 44 ---- 5 files changed, 911 deletions(-) delete mode 100644 lib/dev-mgr/dev-cache.c delete mode 100644 lib/dev-mgr/dev-cache.h delete mode 100644 lib/dev-mgr/dev-manager.c delete mode 100644 lib/dev-mgr/dev-manager.h delete mode 100644 lib/dev-mgr/hash.c diff --git a/lib/dev-mgr/dev-cache.c b/lib/dev-mgr/dev-cache.c deleted file mode 100644 index fecc54a15..000000000 --- a/lib/dev-mgr/dev-cache.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software (UK) Limited. - * - * This file is released under the GPL. - */ - -#include "dev-cache.h" -#include "log.h" -#include "pool.h" -#include "hash.h" -#include "list.h" -#include "dbg_malloc.h" - -#include -#include -#include -#include -#include -#include - -/* - * FIXME: really need to seperate names from the devices since - * multiple names can point to the same device. - */ - -struct dev_iter { - struct hash_node *current; - struct dev_filter *filter; -}; - -struct dir_list { - struct list_head list; - char dir[0]; -}; - -static struct { - struct pool *mem; - struct hash_table *devices; - - int has_scanned; - struct list_head dirs; - -} _cache; - - -#define _alloc(x) pool_alloc(_cache.mem, (x)) -#define _free(x) pool_free(_cache.mem, (x)) - -/* - * return a new path for the destination of the path. - */ -static char *_follow_link(const char *path, struct stat *info) -{ - char buffer[PATH_MAX + 1]; - int n; - n = readlink(path, buffer, sizeof(buffer) - 1); - - if (n <= 0) - return NULL; - - buffer[n] = '\0'; - - if (stat(buffer, info) < 0) { - log_sys_err("stat"); - return NULL; - } - - return pool_strdup(_cache.mem, buffer); -} - -/* - * Get rid of extra slashes in the path string. - */ -static void _collapse_slashes(char *str) -{ - char *ptr; - int was_slash = 0; - - for (ptr = str; *ptr; ptr++) { - if (*ptr == '/') { - if (was_slash) - continue; - - was_slash = 1; - } else - was_slash = 0; - *str++ = *ptr; - } - - *str = *ptr; -} - -static struct device *_create_dev(const char *path) -{ - struct stat info; - struct device *dev; - char *name = pool_strdup(_cache.mem, path); - - if (!name) { - stack; - return NULL; - } - - _collapse_slashes(name); - - if (stat(name, &info) < 0) { - log_sys_err("stat"); - goto bad; - } - - if (S_ISLNK(info.st_mode)) { - log_debug("%s is a symbolic link, following\n", name); - if (!(name = _follow_link(name, &info))) { - stack; - goto bad; - } - } - - if (!S_ISBLK(info.st_mode)) { - log_debug("%s is not a block device\n", name); - goto bad; - } - - if (!(dev = _alloc(sizeof(*dev)))) { - stack; - goto bad; - } - - dev->name = name; - dev->dev = info.st_rdev; - return dev; - - bad: - _free(name); - return NULL; -} - -static struct device *_add(const char *dir, const char *path) -{ - struct device *d; - int len = strlen(dir) + strlen(path) + 2; - char *buffer = dbg_malloc(len); - - snprintf(buffer, len, "%s/%s", dir, path); - d = dev_cache_get(buffer, NULL); - dbg_free(buffer); - - return d; -} - -static int _dir_scan(const char *dir) -{ - int n, dirent_count; - struct dirent **dirent; - - dirent_count = scandir(dir, &dirent, NULL, alphasort); - if (dirent_count > 0) { - for (n = 0; n < dirent_count; n++) { - _add(dir, dirent[n]->d_name); - free(dirent[n]); - } - free(dirent); - } - - return 1; -} - -static void _full_scan(void) -{ - struct list_head *tmp; - - if (_cache.has_scanned) - return; - - list_for_each(tmp, &_cache.dirs) { - struct dir_list *dl = list_entry(tmp, struct dir_list, list); - _dir_scan(dl->dir); - } - - _cache.has_scanned = 1; -} - -int dev_cache_init(void) -{ - if (!(_cache.mem = pool_create(10 * 1024))) { - stack; - return 0; - } - - if (!(_cache.devices = hash_create(128))) { - stack; - pool_destroy(_cache.mem); - _cache.mem = 0; - return 0; - } - - return 1; -} - -void dev_cache_exit(void) -{ - pool_destroy(_cache.mem); - hash_destroy(_cache.devices); -} - -int dev_cache_add_dir(const char *path) -{ - struct dir_list *dl; - - if (!(dl = _alloc(sizeof(*dl) + strlen(path) + 1))) - return 0; - - strcpy(dl->dir, path); - list_add(&dl->list, &_cache.dirs); - return 1; -} - -struct device *_insert_new(const char *name) -{ - struct device *d = _create_dev(name); - if (!d || !hash_insert(_cache.devices, name, d)) - return NULL; - - return d; -} - -struct device *dev_cache_get(const char *name, struct dev_filter *f) -{ - struct device *d = (struct device *) hash_lookup(_cache.devices, name); - return (d && (!f || f->passes_filter(f, d))) ? d : NULL; -} - -struct dev_iter *dev_iter_create(struct dev_filter *f) -{ - struct dev_iter *di = dbg_malloc(sizeof(*di)); - - if (!di) - return NULL; - - _full_scan(); - di->current = hash_get_first(_cache.devices); - di->filter = f; - - return di; -} - -void dev_iter_destroy(struct dev_iter *iter) -{ - dbg_free(iter); -} - -static inline struct device *_iter_next(struct dev_iter *iter) -{ - struct device *d = hash_get_data(_cache.devices, iter->current); - iter->current = hash_get_next(_cache.devices, iter->current); - return d; -} - -struct device *dev_iter_get(struct dev_iter *iter) -{ - while (iter->current) { - struct device *d = _iter_next(iter); - if (!iter->filter || - iter->filter->passes_filter(iter->filter, d)) - return d; - } - - return NULL; -} - - - diff --git a/lib/dev-mgr/dev-cache.h b/lib/dev-mgr/dev-cache.h deleted file mode 100644 index 851405045..000000000 --- a/lib/dev-mgr/dev-cache.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software (UK) Limited. - * - * This file is released under the GPL. - */ - -#ifndef _LVM_DEV_CACHE_H -#define _LVM_DEV_CACHE_H - -#include "lvm-types.h" - -/* - * All devices in LVM will be represented by one of these. - * pointer comparisons are valid. - */ -struct device { - char *name; - dev_t dev; -}; - -struct dev_filter { - int (*passes_filter)(struct dev_filter *f, struct device *dev); - void *private; -}; - - -/* - * The global device cache. - */ -int dev_cache_init(void); -void dev_cache_exit(void); - -int dev_cache_add_dir(const char *path); -struct device *dev_cache_get(const char *name, struct dev_filter *f); - - -/* - * Object for iterating through the cache. - */ -struct dev_iter; -struct dev_iter *dev_iter_create(struct dev_filter *f); -void dev_iter_destroy(struct dev_iter *iter); -struct device *dev_iter_get(struct dev_iter *iter); - - -/* - * All io should use these routines, rather than opening the devices - * by hand. You do not have to call an open routine. ATM all io is - * immediately flushed. - */ -int dev_get_size(struct device *dev, uint64_t *size); /* in k */ -int64_t dev_read(struct device *dev, uint64_t offset, - int64_t len, void *buffer); -int64_t dev_write(struct device *dev, uint64_t offset, - int64_t len, void *buffer); - -#endif diff --git a/lib/dev-mgr/dev-manager.c b/lib/dev-mgr/dev-manager.c deleted file mode 100644 index 2467ceae2..000000000 --- a/lib/dev-mgr/dev-manager.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software - * - * This LVM library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This LVM library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this LVM library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA - */ - -#include -#include -#include -#include -#include -#include -#include "hash.h" -#include "pool.h" -#include "log.h" -#include "dev-manager.h" - -#define DEFAULT_BASE_DIR "/dev" -#define LOCAL_EPARAM 1 -#define LOCAL_CHECK_NAME 2 -#define LOCAL_DEVICE_TYPE_INVALID 3 -#define NUMBER_OF_MAJORS 256 - -static const char *device_names[] = { - "ide", /* IDE disk */ - "sd", /* SCSI disk */ - "md", /* Multiple Disk driver (SoftRAID) */ - "loop", /* Loop device */ - "dasd", /* DASD disk (IBM S/390, zSeries) */ - "dac960", /* DAC960 */ - "nbd", /* Network Block Device */ - "ida", /* Compaq SMART2 */ - "cciss", /* Compaq CCISS array */ - "ubd", /* User-mode virtual block device */ - NULL -}; - -struct dev_i { - struct device d; - - /* Begin internal data */ - struct dev_i *dev_next; - struct dev_i *name_next; - struct dev_i *next; -}; - -struct dev_mgr { - /* everything is allocated from this pool */ - struct pool *pool; - - int has_scanned; - - char valid_majors[NUMBER_OF_MAJORS]; - - /* hash table */ - int num_slots; - int mask; - struct dev_i **dev_slots; - struct dev_i **name_slots; - struct dev_i *all; - - char **devdir; -}; - - -static int _full_dev_scan(struct dev_mgr *dm); -static int _dir_scan(struct dev_mgr *dm, const char *dirname); - -static struct dev_i *_add(struct dev_mgr *dm, const char *directory, - const char *devname); - -static struct dev_i *_add_named_device(struct dev_mgr *dm, const char *name); - -static struct dev_i * -_is_name_present(struct dev_mgr *dm, const char *name); - -static struct dev_i * -_is_device_present(struct dev_mgr *dm, dev_t dev); - -static void _collapse_slashes(char *str); -static int _create_hash_table(struct dev_mgr *dm, unsigned size_hint); -static void _name_insert(struct dev_mgr *dm, struct dev_i *device); -static void _dev_insert(struct dev_mgr *dm, struct dev_i *device); -static void _list_insert(struct dev_mgr *dm, struct dev_i *device); -static unsigned int _hash_dev(dev_t d); -static int _check_dev(struct dev_mgr *dm, struct stat *stat_b); -static int _scan_proc_dev(struct dev_mgr *dm); - -static inline struct device *_get_dev(struct dev_i *di) -{ - return di ? &di->d : 0; -} - -struct dev_mgr *init_dev_manager(struct config_node *cn) -{ - struct pool *pool = create_pool(10 * 1024); - struct dev_mgr *dm = NULL; - const char * base_dir = NULL; - - if (!pool) { - stack; - return 0; - } - - if (!(dm = pool_alloc(pool, sizeof(*dm)))) { - stack; - destroy_pool(pool); - return 0; - } - - memset(dm, 0, sizeof(*dm)); - dm->pool = pool; - - if(cn) - base_dir = find_config_str(cn, "dev-mgr/base_dir", '/', 0); - if(!base_dir) - base_dir = DEFAULT_BASE_DIR; - - dm->devdir = pool_alloc(dm->pool, sizeof(char*)); - dm->devdir[0] = pool_strdup(dm->pool, base_dir); - - if (!_create_hash_table(dm, 128)) { - stack; - destroy_pool(pool); - return 0; - } - - _scan_proc_dev(dm); - - return dm; -} - -void fin_dev_manager(struct dev_mgr *dm) -{ - if(dm) - destroy_pool(dm->pool); -} - -/* Find a matching name in the hash table */ -struct device *dev_by_name(struct dev_mgr *dm, const char *name) -{ - struct dev_i *c; - - if (!(c = _is_name_present(dm, name)) && !dm->has_scanned) - c = _add_named_device(dm, name); - - return _get_dev(c); -} - -/* Find a matching dev_t entry in the hash table - this could potentially - * cause problems when there are symlinks in the cache that match up to - * other entries... */ -struct device *dev_by_dev(struct dev_mgr *dm, dev_t d) -{ - return _get_dev(_is_device_present(dm, d)); -} - -/* Triggers a full scan the first time it is run, and returns a counter - object*/ -dev_counter_t init_dev_scan(struct dev_mgr *dm) -{ - if(!dm->has_scanned) - _full_dev_scan(dm); - - return (dev_counter_t) dm->all; -} - -/* Returns the next item in the device cache */ -struct device *next_device(dev_counter_t *counter) -{ - struct dev_i *di = (struct dev_i *) *counter; - if (di) - *counter = (dev_counter_t) di->next; - - return _get_dev(di); -} - -/* Cleans up the counter object...doesn't need to do anything with the current - implementation */ -void fin_dev_scan(dev_counter_t counter) -{ - /* empty */ -} - -/* Scan through all the directories specified (eventually a var in the config - * file) and add all devices to the cache that we find in them */ -static int _full_dev_scan(struct dev_mgr *dm) -{ - int d, ret = 0; - char *dirname; - - for (d = 0; dm->devdir[d]; d++) { - dirname = dm->devdir[d]; - ret = ret || _dir_scan(dm, dirname); - } - - dm->has_scanned = 1; - return ret; -} - -/* Scan the directory passed in and add the entries found to the hash */ -static int _dir_scan(struct dev_mgr *dm, const char *dirname) -{ - int n, dirent_count; - struct dirent **dirent; - - dirent_count = scandir(dirname, &dirent, NULL, alphasort); - if (dirent_count > 0) { - for (n = 0; n < dirent_count; n++) { - _add(dm, dirname, dirent[n]->d_name); - free(dirent[n]); - } - - free(dirent); - } - - return 1; -} - -/* Add entry found to hash if it is a device; if it is a directory, call - * _dir_scan with it as the argument */ -static struct dev_i *_add(struct dev_mgr *dm, - const char *directory, const char *devname) -{ - char devpath[128]; - - if (!directory || !devname) - return 0; - - snprintf(devpath, sizeof(devpath), "%s/%s", directory, devname); - _collapse_slashes(devpath); - return _add_named_device(dm, devpath); -} - -static struct dev_i *_add_named_device(struct dev_mgr *dm, const char *devpath) -{ - struct dev_i *dev = NULL; - struct stat stat_b; - - if ((stat(devpath, &stat_b) == -1) || _check_dev(dm, &stat_b)) - goto out; - - /* Check for directories and scan them if they aren't this directory - or a parent of the directory */ - if (S_ISDIR(stat_b.st_mode)) { - if(devpath[0] != '.') - _dir_scan(dm, devpath); - - } else { - /* If the device is in the name hash, we just need to update - the device type (and it's already in the device hash and - list */ - if((dev = _is_name_present(dm, devpath))) - dev->d.dev = stat_b.st_rdev; - - /* otherwise we need to add it to the name hash and possibly - the device hash and list */ - else { - if (!(dev = pool_alloc(dm->pool, sizeof(*dev)))) { - stack; - goto out; - } - - if (!(dev->d.name = pool_strdup(dm->pool, devpath))) { - stack; - goto out; - } - - dev->d.dev = stat_b.st_rdev; - - /* We don't care what the name is as long as it is - a valid device - this allows us to deal with - symlinks properly */ - _name_insert(dm, dev); - - /* the device type hash and list have to have unique - entries (based on device type) so we can be assured - of only one hit when searching for a device and - we don't get duplicates when scanning the list */ - if(!_is_device_present(dm, dev->d.dev)) { - _dev_insert(dm, dev); - _list_insert(dm, dev); - } - } - } - - out: - log_info(dev ? "dev-manager added '%s'" : - "dev-manager failed to add '%s'", devpath); - return dev; -} - -/* Check to see if the name is stored in the hash table already */ -static struct dev_i * -_is_name_present(struct dev_mgr *dm, const char *name) -{ - unsigned h = hash(name) & (dm->num_slots - 1); - struct dev_i *c; - - for(c = dm->name_slots[h]; c; c = c->name_next) - if(!strcmp(name, c->d.name)) - break; - - return c; -} - -/* Check to see if dev is stored in the hash table already */ -static struct dev_i * -_is_device_present(struct dev_mgr *dm, dev_t dev) -{ - unsigned h = _hash_dev(dev) & (dm->num_slots - 1); - struct dev_i *c; - - for(c = dm->dev_slots[h]; c; c = c->dev_next) - if(dev == c->d.dev) - break; - - return c; -} - -/* Get rid of extra slashes in the path string */ -static void _collapse_slashes(char *str) -{ - char *ptr; - int was_slash = 0; - - for (ptr = str; *ptr; ptr++) { - if (*ptr == '/') { - if (was_slash) - continue; - - was_slash = 1; - } else - was_slash = 0; - *str++ = *ptr; - } - - *str = *ptr; -} - -static int _create_hash_table(struct dev_mgr *dm, unsigned size_hint) -{ - size_t len; - unsigned new_size = 16u; - - /* round size hint up to a power of two */ - while(new_size < size_hint) - new_size = new_size << 1; - - dm->num_slots = new_size; - dm->mask = new_size - 1; - - len = sizeof(*dm->dev_slots) * new_size; - if (!(dm->dev_slots = pool_zalloc(dm->pool, len))) - return 0; - - if (!(dm->name_slots = pool_zalloc(dm->pool, len))) - return 0; - - return 1; -} - -static void _name_insert(struct dev_mgr *dm, struct dev_i *device) -{ - unsigned h = hash(device->d.name) & dm->mask; - - /* look for this key */ - struct dev_i *c = _is_name_present(dm, device->d.name); - - /*FIXME: We might not want to replace the entry if a duplicate is - found...For now just replace the device type entry - what does - this mean for freeing memory...? */ - if (c) - c->d.dev = device->d.dev; - - else { - device->name_next = dm->name_slots[h]; - dm->name_slots[h] = device; - } -} - -static void _dev_insert(struct dev_mgr *dm, struct dev_i *device) -{ - unsigned h = _hash_dev(device->d.dev) & dm->mask; - - device->dev_next = dm->dev_slots[h]; - dm->dev_slots[h] = device; -} - -static void _list_insert(struct dev_mgr *dm, struct dev_i *device) -{ - /* Handle the list of devices */ - device->next = dm->all; - dm->all = device; -} - -static unsigned int _hash_dev(dev_t d) -{ - /* FIXME: find suitable fn from Knuth */ - return (unsigned int) d; -} - -static int _check_dev(struct dev_mgr *dm, struct stat *stat_b) -{ - int ret = 1; - int seek_major = MAJOR(stat_b->st_rdev); - - if (stat_b == NULL) - ret = -LOCAL_EPARAM; - else if ( ! S_ISBLK(stat_b->st_mode)) - ret = -LOCAL_CHECK_NAME; - else { - if (dm->valid_majors[seek_major]) - ret = 0; - } - - return ret; -} - -/* Caches /proc/device info and returns the number of block devices found - in /proc/devices */ -static int _scan_proc_dev(struct dev_mgr *dm) -{ - char line[80]; - FILE *procdevices = NULL; - int ret = 0; - int i, j = 0; - int line_maj = 0; - int blocksection = 0; - int dev_len = 0; - - if ((procdevices = fopen("/proc/devices", "r")) != NULL) { - while (fgets(line, 80, procdevices) != NULL) { - i = 0; - while (line[i] == ' ' && line[i] != '\0') - i++; - - /* If its not a number it may be name of section */ - line_maj = atoi(((char *) (line + i))); - if (line_maj == 0) { - blocksection = (line[i] == 'B') ? 1 : 0; - continue; - } - /* We only want block devices ... */ - if (!blocksection) - continue; - - /* Find the start of the device major name */ - while (line[i] != ' ' && line[i] != '\0') - i++; - while (line[i] == ' ' && line[i] != '\0') - i++; - - /* Go through the valid device names and if there is a - match, set the array member corresponding to the - major number to !0 */ - for (j = 0; device_names[j] != NULL; j++) { - - dev_len = strlen(device_names[j]); - if (dev_len <= strlen(line + i)) { - if (strncmp (device_names[j], - line + i, - dev_len) == 0) { - - dm->valid_majors[line_maj]='1'; - ret++; - break; - } - } - } - } - fclose(procdevices); - } - return ret; -} - -/* - * Local variables: - * c-file-style: "linux" - * End: - * vim:ai cin ts=8 - */ - diff --git a/lib/dev-mgr/dev-manager.h b/lib/dev-mgr/dev-manager.h deleted file mode 100644 index 427654dc5..000000000 --- a/lib/dev-mgr/dev-manager.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2001 Sistina Software - * - * This LVM library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This LVM library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this LVM library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA - */ - -#ifndef _LVM_DEV_MANAGER_H -#define _LVM_DEV_MANAGER_H - -#include -#include -#include "config.h" - -struct dev_manager; -struct dev_iter; - -struct dev_manager *create_dev_manager(); -void fin_dev_manager(struct dev_mgr *dm); - -struct device *get_dev_by_name(struct dev_mgr *dm, const char *name); -struct device *get_dev_by_dev(struct dev_mgr *dm, dev_t d); -void put_dev(struct dev_mgr *dm, const char *name); - -/* either of these trigger a full scan, the first time they're run */ -dev_counter_t init_dev_scan(struct dev_mgr *dm); -struct device *next_device(dev_counter_t *counter); -void fin_dev_scan(dev_counter_t counter); - -#endif diff --git a/lib/dev-mgr/hash.c b/lib/dev-mgr/hash.c deleted file mode 100644 index adad2e8e8..000000000 --- a/lib/dev-mgr/hash.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * tools/lib/hash.c - * - * Copyright (C) 2001 Sistina Software - * - * This LVM library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This LVM library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this LVM library; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA - */ - -#include "hash.h" - -/* Pseudorandom Permutation of the Integers 0 through 255: */ -unsigned char hash_nums[] = -{ - 1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51, - 87,197,177,107,234,169, 56, 68, 30, 7,173, 73,188, 40, 36, 65, - 49,213,104,190, 57,211,148,223, 48,115, 15, 2, 67,186,210, 28, - 12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144, - 176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254, - 178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221, - 102,218,255,240, 82,106,158,201, 61, 3, 89, 9, 42,155,159, 93, - 166, 80, 50, 34,175,195,100, 99, 26,150, 16,145, 4, 33, 8,189, - 121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194, - 193,239,101,242, 5,171,126, 11, 74, 59,137,228,108,191,232,139, - 6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112, - 84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43, - 249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71, - 230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109, - 44, 38, 31,149,135, 0,216, 52, 63, 23, 37, 69, 39,117,146,184, - 163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209 -}; - -- 2.43.5