diff options
Diffstat (limited to 'tests/utils')
| -rw-r--r-- | tests/utils/arequal-checksum.c | 878 | ||||
| -rw-r--r-- | tests/utils/changelog/changelog.h | 125 | ||||
| -rw-r--r-- | tests/utils/changelog/get-history.c | 71 | ||||
| -rw-r--r-- | tests/utils/changelog/test-changelog-api.c | 98 | ||||
| -rw-r--r-- | tests/utils/changelog/test-history-api.c | 111 | ||||
| -rw-r--r-- | tests/utils/changelogparser.py | 236 | ||||
| -rwxr-xr-x | tests/utils/create-files.py | 20 | ||||
| -rw-r--r-- | tests/utils/get-mdata-xattr.c | 152 | ||||
| -rwxr-xr-x | tests/utils/getfattr.py | 22 | ||||
| -rwxr-xr-x | tests/utils/gfid-access.py | 70 | ||||
| -rw-r--r-- | tests/utils/libcxattr.py | 29 | ||||
| -rwxr-xr-x | tests/utils/pidof.py | 12 | ||||
| -rw-r--r-- | tests/utils/py2py3.py | 186 | ||||
| -rwxr-xr-x | tests/utils/setfattr.py | 3 |
14 files changed, 1508 insertions, 505 deletions
diff --git a/tests/utils/arequal-checksum.c b/tests/utils/arequal-checksum.c index d4e8688b9be..b51a054162b 100644 --- a/tests/utils/arequal-checksum.c +++ b/tests/utils/arequal-checksum.c @@ -31,7 +31,7 @@ /* * FTW_ACTIONRETVAL is a GNU libc extension. It is used here to skip - * hiearchies. On other systems we will still walk the tree, ignoring + * hierarchies. On other systems we will still walk the tree, ignoring * entries. */ #ifndef FTW_ACTIONRETVAL @@ -41,605 +41,593 @@ int debug = 0; typedef struct { - char test_directory[4096]; - char **ignored_directory; - unsigned int directories_ignored; + char test_directory[4096]; + char **ignored_directory; + unsigned int directories_ignored; } arequal_config_t; static arequal_config_t arequal_config; static error_t -arequal_parse_opts (int key, char *arg, struct argp_state *_state); +arequal_parse_opts(int key, char *arg, struct argp_state *_state); static struct argp_option arequal_options[] = { - { "ignore", 'i', "IGNORED", 0, - "entry in the given path to be ignored"}, - { "path", 'p', "PATH", 0, "path where arequal has to be run"}, - {0, 0, 0, 0, 0} -}; - -#define DBG(fmt ...) do { \ - if (debug) { \ - fprintf (stderr, "D "); \ - fprintf (stderr, fmt); \ - } \ - } while (0) + {"ignore", 'i', "IGNORED", 0, "entry in the given path to be ignored"}, + {"path", 'p', "PATH", 0, "path where arequal has to be run"}, + {0, 0, 0, 0, 0}}; + +#define DBG(fmt...) \ + do { \ + if (debug) { \ + fprintf(stderr, "D "); \ + fprintf(stderr, fmt); \ + } \ + } while (0) void -add_to_list (char *arg); +add_to_list(char *arg); void -get_absolute_path (char directory[], char *arg); +get_absolute_path(char directory[], char *arg); -static inline int roof(int a, int b) +static int +roof(int a, int b) { - return ((((a)+(b)-1)/((b)?(b):1))*(b)); + return ((((a) + (b)-1) / ((b) ? (b) : 1)) * (b)); } void -add_to_list (char *arg) +add_to_list(char *arg) { - char *string = NULL; - int index = 0; + char *string = NULL; + int index = 0; - index = arequal_config.directories_ignored - 1; - string = strdup (arg); + index = arequal_config.directories_ignored - 1; + string = strdup(arg); - if (!arequal_config.ignored_directory) { - arequal_config.ignored_directory = calloc (1, sizeof (char *)); - } else - arequal_config.ignored_directory = - realloc (arequal_config.ignored_directory, - sizeof (char *) * (index+1)); + if (!arequal_config.ignored_directory) { + arequal_config.ignored_directory = calloc(1, sizeof(char *)); + } else + arequal_config.ignored_directory = realloc( + arequal_config.ignored_directory, sizeof(char *) * (index + 1)); - arequal_config.ignored_directory[index] = string; + arequal_config.ignored_directory[index] = string; } static error_t -arequal_parse_opts (int key, char *arg, struct argp_state *_state) +arequal_parse_opts(int key, char *arg, struct argp_state *_state) { - switch (key) { - case 'i': - { - arequal_config.directories_ignored++; - add_to_list (arg); - } - break; - case 'p': - { - if (arg[0] == '/') - strcpy (arequal_config.test_directory, arg); - else - get_absolute_path (arequal_config.test_directory, arg); - - if (arequal_config.test_directory - [strlen(arequal_config.test_directory) - 1] == '/') - arequal_config.test_directory - [strlen(arequal_config.test_directory) - 1] = '\0'; - } - break; + switch (key) { + case 'i': { + arequal_config.directories_ignored++; + add_to_list(arg); + } break; + case 'p': { + if (arg[0] == '/') + strcpy(arequal_config.test_directory, arg); + else + get_absolute_path(arequal_config.test_directory, arg); + + if (arequal_config + .test_directory[strlen(arequal_config.test_directory) - + 1] == '/') + arequal_config + .test_directory[strlen(arequal_config.test_directory) - 1] = + '\0'; + } break; case ARGP_KEY_NO_ARGS: - break; + break; case ARGP_KEY_ARG: - break; + break; case ARGP_KEY_END: - if (_state->argc == 1) { - argp_usage (_state); - } + if (_state->argc == 1) { + argp_usage(_state); + } + } - } - - return 0; + return 0; } void -get_absolute_path (char directory[], char *arg) +get_absolute_path(char directory[], char *arg) { - char cwd[4096] = {0,}; - - if (getcwd (cwd, sizeof (cwd)) == NULL) - printf ("some error in getting cwd\n"); - - if (strcmp (arg, ".") != 0) { - if (cwd[strlen(cwd)] != '/') - cwd[strlen (cwd)] = '/'; - strcat (cwd, arg); - } - strcpy (directory, cwd); + char cwd[4096] = { + 0, + }; + + if (getcwd(cwd, sizeof(cwd)) == NULL) + printf("some error in getting cwd\n"); + + if (strcmp(arg, ".") != 0) { + if (cwd[strlen(cwd)] != '/') + cwd[strlen(cwd)] = '/'; + strcat(cwd, arg); + } + strcpy(directory, cwd); } static struct argp argp = { - arequal_options, - arequal_parse_opts, - "", - "arequal - Tool which calculates the checksum of all the entries" - "present in a given directory" -}; + arequal_options, arequal_parse_opts, "", + "arequal - Tool which calculates the checksum of all the entries" + "present in a given directory"}; /* All this runs in single thread, hence using 'global' variables */ -unsigned long long avg_uid_file = 0; -unsigned long long avg_uid_dir = 0; -unsigned long long avg_uid_symlink = 0; -unsigned long long avg_uid_other = 0; +unsigned long long avg_uid_file = 0; +unsigned long long avg_uid_dir = 0; +unsigned long long avg_uid_symlink = 0; +unsigned long long avg_uid_other = 0; -unsigned long long avg_gid_file = 0; -unsigned long long avg_gid_dir = 0; -unsigned long long avg_gid_symlink = 0; -unsigned long long avg_gid_other = 0; +unsigned long long avg_gid_file = 0; +unsigned long long avg_gid_dir = 0; +unsigned long long avg_gid_symlink = 0; +unsigned long long avg_gid_other = 0; -unsigned long long avg_mode_file = 0; -unsigned long long avg_mode_dir = 0; -unsigned long long avg_mode_symlink = 0; -unsigned long long avg_mode_other = 0; +unsigned long long avg_mode_file = 0; +unsigned long long avg_mode_dir = 0; +unsigned long long avg_mode_symlink = 0; +unsigned long long avg_mode_other = 0; unsigned long long global_ctime_checksum = 0; +unsigned long long count_dir = 0; +unsigned long long count_file = 0; +unsigned long long count_symlink = 0; +unsigned long long count_other = 0; -unsigned long long count_dir = 0; -unsigned long long count_file = 0; -unsigned long long count_symlink = 0; -unsigned long long count_other = 0; +unsigned long long checksum_file1 = 0; +unsigned long long checksum_file2 = 0; +unsigned long long checksum_dir = 0; +unsigned long long checksum_symlink = 0; +unsigned long long checksum_other = 0; +unsigned long long +checksum_path(const char *path) +{ + unsigned long long csum = 0; + unsigned long long *nums = 0; + int len = 0; + int cnt = 0; -unsigned long long checksum_file1 = 0; -unsigned long long checksum_file2 = 0; -unsigned long long checksum_dir = 0; -unsigned long long checksum_symlink = 0; -unsigned long long checksum_other = 0; + len = roof(strlen(path), sizeof(csum)); + cnt = len / sizeof(csum); + nums = __builtin_alloca(len); + memset(nums, 0, len); + strcpy((char *)nums, path); -unsigned long long -checksum_path (const char *path) -{ - unsigned long long csum = 0; - unsigned long long *nums = 0; - int len = 0; - int cnt = 0; - - len = roof (strlen (path), sizeof (csum)); - cnt = len / sizeof (csum); - - nums = __builtin_alloca (len); - memset (nums, 0, len); - strcpy ((char *)nums, path); - - while (cnt) { - csum ^= *nums; - nums++; - cnt--; - } + while (cnt) { + csum ^= *nums; + nums++; + cnt--; + } - return csum; + return csum; } int -checksum_md5 (const char *path, const struct stat *sb) +checksum_md5(const char *path, const struct stat *sb) { - uint64_t this_data_checksum = 0; - FILE *filep = NULL; - char *cmd = NULL; - char strvalue[17] = {0,}; - int ret = -1; - int len = 0; - const char *pos = NULL; - char *cpos = NULL; - - /* Have to escape single-quotes in filename. - * First, calculate the size of the buffer I'll need. - */ - for (pos = path; *pos; pos++) { - if ( *pos == '\'' ) - len += 4; - else - len += 1; - } - - cmd = malloc(sizeof(char) * (len + 20)); - cmd[0] = '\0'; - - /* Now, build the command with single quotes escaped. */ - - cpos = cmd; + uint64_t this_data_checksum = 0; + FILE *filep = NULL; + char *cmd = NULL; + char strvalue[17] = { + 0, + }; + int ret = -1; + int len = 0; + const char *pos = NULL; + char *cpos = NULL; + + /* Have to escape single-quotes in filename. + * First, calculate the size of the buffer I'll need. + */ + for (pos = path; *pos; pos++) { + if (*pos == '\'') + len += 4; + else + len += 1; + } + + cmd = malloc(sizeof(char) * (len + 20)); + cmd[0] = '\0'; + + /* Now, build the command with single quotes escaped. */ + + cpos = cmd; #if defined(linux) - strcpy(cpos, "md5sum '"); - cpos += 8; + strcpy(cpos, "md5sum '"); + cpos += 8; #elif defined(__NetBSD__) - strcpy(cpos, "md5 -n '"); - cpos += 8; + strcpy(cpos, "md5 -n '"); + cpos += 8; #elif defined(__FreeBSD__) || defined(__APPLE__) - strcpy(cpos, "md5 -q '"); - cpos += 8; + strcpy(cpos, "md5 -q '"); + cpos += 8; #else #error "Please add system-specific md5 command" #endif - /* Add the file path, with every single quotes replaced with this sequence: - * '\'' - */ - - for (pos = path; *pos; pos++) { - if ( *pos == '\'' ) { - strcpy(cpos, "'\\''"); - cpos += 4; - } else { - *cpos = *pos; - cpos++; - } - } - - /* Add on the trailing single-quote and null-terminate. */ - strcpy(cpos, "'"); - - filep = popen (cmd, "r"); - if (!filep) { - perror (path); - goto out; - } - - if (fread (strvalue, sizeof (char), 16, filep) != 16) { - fprintf (stderr, "%s: short read\n", path); - goto out; + /* Add the file path, with every single quotes replaced with this sequence: + * '\'' + */ + + for (pos = path; *pos; pos++) { + if (*pos == '\'') { + strcpy(cpos, "'\\''"); + cpos += 4; + } else { + *cpos = *pos; + cpos++; } - - this_data_checksum = strtoull (strvalue, NULL, 16); - if (-1 == this_data_checksum) { - fprintf (stderr, "%s: %s\n", strvalue, strerror (errno)); - goto out; - } - checksum_file1 ^= this_data_checksum; - - if (fread (strvalue, sizeof (char), 16, filep) != 16) { - fprintf (stderr, "%s: short read\n", path); - goto out; - } - - this_data_checksum = strtoull (strvalue, NULL, 16); - if (-1 == this_data_checksum) { - fprintf (stderr, "%s: %s\n", strvalue, strerror (errno)); - goto out; - } - checksum_file2 ^= this_data_checksum; - - ret = 0; + } + + /* Add on the trailing single-quote and null-terminate. */ + strcpy(cpos, "'"); + + filep = popen(cmd, "r"); + if (!filep) { + perror(path); + goto out; + } + + if (fread(strvalue, sizeof(char), 16, filep) != 16) { + fprintf(stderr, "%s: short read\n", path); + goto out; + } + + this_data_checksum = strtoull(strvalue, NULL, 16); + if (-1 == this_data_checksum) { + fprintf(stderr, "%s: %s\n", strvalue, strerror(errno)); + goto out; + } + checksum_file1 ^= this_data_checksum; + + if (fread(strvalue, sizeof(char), 16, filep) != 16) { + fprintf(stderr, "%s: short read\n", path); + goto out; + } + + this_data_checksum = strtoull(strvalue, NULL, 16); + if (-1 == this_data_checksum) { + fprintf(stderr, "%s: %s\n", strvalue, strerror(errno)); + goto out; + } + checksum_file2 ^= this_data_checksum; + + ret = 0; out: - if (filep) - pclose (filep); + if (filep) + pclose(filep); - if (cmd) - free(cmd); + if (cmd) + free(cmd); - return ret; + return ret; } int -checksum_filenames (const char *path, const struct stat *sb) +checksum_filenames(const char *path, const struct stat *sb) { - DIR *dirp = NULL; - struct dirent *entry = NULL; - unsigned long long csum = 0; - int i = 0; - int found = 0; - - dirp = opendir (path); - if (!dirp) { - perror (path); - goto out; - } - - errno = 0; - while ((entry = readdir (dirp))) { - /* do not calculate the checksum of the entries which user has - told to ignore and proceed to other siblings.*/ - if (arequal_config.ignored_directory) { - for (i = 0;i < arequal_config.directories_ignored;i++) { - if ((strcmp (entry->d_name, - arequal_config.ignored_directory[i]) - == 0)) { - found = 1; - DBG ("ignoring the entry %s\n", - entry->d_name); - break; - } - } - if (found == 1) { - found = 0; - continue; - } + DIR *dirp = NULL; + struct dirent *entry = NULL; + unsigned long long csum = 0; + int i = 0; + int found = 0; + + dirp = opendir(path); + if (!dirp) { + perror(path); + goto out; + } + + errno = 0; + while ((entry = readdir(dirp))) { + /* do not calculate the checksum of the entries which user has + told to ignore and proceed to other siblings.*/ + if (arequal_config.ignored_directory) { + for (i = 0; i < arequal_config.directories_ignored; i++) { + if ((strcmp(entry->d_name, + arequal_config.ignored_directory[i]) == 0)) { + found = 1; + DBG("ignoring the entry %s\n", entry->d_name); + break; } - csum = checksum_path (entry->d_name); - checksum_dir ^= csum; + } + if (found == 1) { + found = 0; + continue; + } } + csum = checksum_path(entry->d_name); + checksum_dir ^= csum; + } - if (errno) { - perror (path); - goto out; - } + if (errno) { + perror(path); + goto out; + } out: - if (dirp) - closedir (dirp); + if (dirp) + closedir(dirp); - return 0; + return 0; } - int -process_file (const char *path, const struct stat *sb) +process_file(const char *path, const struct stat *sb) { - int ret = 0; + int ret = 0; - count_file++; + count_file++; - avg_uid_file ^= sb->st_uid; - avg_gid_file ^= sb->st_gid; - avg_mode_file ^= sb->st_mode; + avg_uid_file ^= sb->st_uid; + avg_gid_file ^= sb->st_gid; + avg_mode_file ^= sb->st_mode; - ret = checksum_md5 (path, sb); + ret = checksum_md5(path, sb); - return ret; + return ret; } - int -process_dir (const char *path, const struct stat *sb) +process_dir(const char *path, const struct stat *sb) { - unsigned long long csum = 0; + unsigned long long csum = 0; - count_dir++; + count_dir++; - avg_uid_dir ^= sb->st_uid; - avg_gid_dir ^= sb->st_gid; - avg_mode_dir ^= sb->st_mode; + avg_uid_dir ^= sb->st_uid; + avg_gid_dir ^= sb->st_gid; + avg_mode_dir ^= sb->st_mode; - csum = checksum_filenames (path, sb); + csum = checksum_filenames(path, sb); - checksum_dir ^= csum; + checksum_dir ^= csum; - return 0; + return 0; } - int -process_symlink (const char *path, const struct stat *sb) +process_symlink(const char *path, const struct stat *sb) { - int ret = 0; - char buf[4096] = {0, }; - unsigned long long csum = 0; + int ret = 0; + char buf[4096] = { + 0, + }; + unsigned long long csum = 0; - count_symlink++; + count_symlink++; - avg_uid_symlink ^= sb->st_uid; - avg_gid_symlink ^= sb->st_gid; - avg_mode_symlink ^= sb->st_mode; + avg_uid_symlink ^= sb->st_uid; + avg_gid_symlink ^= sb->st_gid; + avg_mode_symlink ^= sb->st_mode; - ret = readlink (path, buf, 4096); - if (ret < 0) { - perror (path); - goto out; - } + ret = readlink(path, buf, 4096); + if (ret < 0) { + perror(path); + goto out; + } - DBG ("readlink (%s) => %s\n", path, buf); + DBG("readlink (%s) => %s\n", path, buf); - csum = checksum_path (buf); + csum = checksum_path(buf); - DBG ("checksum_path (%s) => %llx\n", buf, csum); + DBG("checksum_path (%s) => %llx\n", buf, csum); - checksum_symlink ^= csum; + checksum_symlink ^= csum; - ret = 0; + ret = 0; out: - return ret; + return ret; } - int -process_other (const char *path, const struct stat *sb) +process_other(const char *path, const struct stat *sb) { - count_other++; + count_other++; - avg_uid_other ^= sb->st_uid; - avg_gid_other ^= sb->st_gid; - avg_mode_other ^= sb->st_mode; + avg_uid_other ^= sb->st_uid; + avg_gid_other ^= sb->st_gid; + avg_mode_other ^= sb->st_mode; - checksum_other ^= sb->st_rdev; + checksum_other ^= sb->st_rdev; - return 0; + return 0; } static int ignore_entry(const char *bname, const char *dname) { - int i; + int i; - for (i = 0; i < arequal_config.directories_ignored; i++) { - if (strcmp(bname, arequal_config.ignored_directory[i]) == 0 && - strncmp(arequal_config.test_directory, dname, - strlen(arequal_config.test_directory)) == 0) - return 1; - } + for (i = 0; i < arequal_config.directories_ignored; i++) { + if (strcmp(bname, arequal_config.ignored_directory[i]) == 0 && + strncmp(arequal_config.test_directory, dname, + strlen(arequal_config.test_directory)) == 0) + return 1; + } - return 0; + return 0; } int -process_entry (const char *path, const struct stat *sb, - int typeflag, struct FTW *ftwbuf) +process_entry(const char *path, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) { - int ret = 0; - char *name = NULL; - char *bname = NULL; - char *dname = NULL; - int i = 0; - - /* The if condition below helps in ignoring some directories in - the given path. If the name of the entry is one of the directory - names that the user told to ignore, then that directory will not - be processed and will return FTW_SKIP_SUBTREE to nftw which will - not crawl this directory and move on to other siblings. - Note that for nftw to recognize FTW_SKIP_TREE, FTW_ACTIONRETVAL - should be passed as an argument to nftw. - - This mainly helps in calculating the checksum of network filesystems - (client-server), where the server might have some hidden directories - for managing the filesystem. So to calculate the sanity of filesytem - one has to get the checksum of the client and then the export directory - of server by telling arequal to ignore some of the directories which - are not part of the namespace. - */ - - if (arequal_config.ignored_directory) { + int ret = 0; + char *name = NULL; + char *bname = NULL; + char *dname = NULL; + int i = 0; + + /* The if condition below helps in ignoring some directories in + the given path. If the name of the entry is one of the directory + names that the user told to ignore, then that directory will not + be processed and will return FTW_SKIP_SUBTREE to nftw which will + not crawl this directory and move on to other siblings. + Note that for nftw to recognize FTW_SKIP_TREE, FTW_ACTIONRETVAL + should be passed as an argument to nftw. + + This mainly helps in calculating the checksum of network filesystems + (client-server), where the server might have some hidden directories + for managing the filesystem. So to calculate the sanity of filesystem + one has to get the checksum of the client and then the export directory + of server by telling arequal to ignore some of the directories which + are not part of the namespace. + */ + + if (arequal_config.ignored_directory) { #ifndef FTW_SKIP_SUBTREE - char *cp; - - name = strdup (path); - dname = dirname (name); - - for (cp = strtok(name, "/"); cp; cp = strtok(NULL, "/")) { - if (ignore_entry(cp, dname)) { - DBG ("ignoring %s\n", path); - if (name) - free (name); - return 0; - } - } -#else /* FTW_SKIP_SUBTREE */ - name = strdup (path); - - name[strlen(name)] = '\0'; - - bname = strrchr (name, '/'); - if (bname) - bname++; - - dname = dirname (name); - if (ignore_entry(bname, dname)) { - DBG ("ignoring %s\n", bname); - ret = FTW_SKIP_SUBTREE; - if (name) - free (name); - return ret; - } -#endif /* FTW_SKIP_SUBTREE */ + char *cp; + + name = strdup(path); + dname = dirname(name); + + for (cp = strtok(name, "/"); cp; cp = strtok(NULL, "/")) { + if (ignore_entry(cp, dname)) { + DBG("ignoring %s\n", path); + if (name) + free(name); + return 0; + } } +#else /* FTW_SKIP_SUBTREE */ + name = strdup(path); + + name[strlen(name)] = '\0'; + + bname = strrchr(name, '/'); + if (bname) + bname++; + + dname = dirname(name); + if (ignore_entry(bname, dname)) { + DBG("ignoring %s\n", bname); + ret = FTW_SKIP_SUBTREE; + if (name) + free(name); + return ret; + } +#endif /* FTW_SKIP_SUBTREE */ + } - DBG ("processing entry %s\n", path); + DBG("processing entry %s\n", path); - switch ((S_IFMT & sb->st_mode)) { + switch ((S_IFMT & sb->st_mode)) { case S_IFDIR: - ret = process_dir (path, sb); - break; + ret = process_dir(path, sb); + break; case S_IFREG: - ret = process_file (path, sb); - break; + ret = process_file(path, sb); + break; case S_IFLNK: - ret = process_symlink (path, sb); - break; + ret = process_symlink(path, sb); + break; default: - ret = process_other (path, sb); - break; - } + ret = process_other(path, sb); + break; + } - if (name) - free (name); - return ret; + if (name) + free(name); + return ret; } - int -display_counts (FILE *fp) +display_counts(FILE *fp) { - fprintf (fp, "\n"); - fprintf (fp, "Entry counts\n"); - fprintf (fp, "Regular files : %lld\n", count_file); - fprintf (fp, "Directories : %lld\n", count_dir); - fprintf (fp, "Symbolic links : %lld\n", count_symlink); - fprintf (fp, "Other : %lld\n", count_other); - fprintf (fp, "Total : %lld\n", - (count_file + count_dir + count_symlink + count_other)); - - return 0; + fprintf(fp, "\n"); + fprintf(fp, "Entry counts\n"); + fprintf(fp, "Regular files : %lld\n", count_file); + fprintf(fp, "Directories : %lld\n", count_dir); + fprintf(fp, "Symbolic links : %lld\n", count_symlink); + fprintf(fp, "Other : %lld\n", count_other); + fprintf(fp, "Total : %lld\n", + (count_file + count_dir + count_symlink + count_other)); + + return 0; } - int -display_checksums (FILE *fp) +display_checksums(FILE *fp) { - fprintf (fp, "\n"); - fprintf (fp, "Checksums\n"); - fprintf (fp, "Regular files : %llx%llx\n", checksum_file1, checksum_file2); - fprintf (fp, "Directories : %llx\n", checksum_dir); - fprintf (fp, "Symbolic links : %llx\n", checksum_symlink); - fprintf (fp, "Other : %llx\n", checksum_other); - fprintf (fp, "Total : %llx\n", - (checksum_file1 ^ checksum_file2 ^ checksum_dir ^ checksum_symlink ^ checksum_other)); - - return 0; + fprintf(fp, "\n"); + fprintf(fp, "Checksums\n"); + fprintf(fp, "Regular files : %llx%llx\n", checksum_file1, checksum_file2); + fprintf(fp, "Directories : %llx\n", checksum_dir); + fprintf(fp, "Symbolic links : %llx\n", checksum_symlink); + fprintf(fp, "Other : %llx\n", checksum_other); + fprintf(fp, "Total : %llx\n", + (checksum_file1 ^ checksum_file2 ^ checksum_dir ^ checksum_symlink ^ + checksum_other)); + + return 0; } - int -display_metadata (FILE *fp) +display_metadata(FILE *fp) { - fprintf (fp, "\n"); - fprintf (fp, "Metadata checksums\n"); - fprintf (fp, "Regular files : %llx\n", - (avg_uid_file + 13) * (avg_gid_file + 11) * (avg_mode_file + 7)); - fprintf (fp, "Directories : %llx\n", - (avg_uid_dir + 13) * (avg_gid_dir + 11) * (avg_mode_dir + 7)); - fprintf (fp, "Symbolic links : %llx\n", - (avg_uid_symlink + 13) * (avg_gid_symlink + 11) * (avg_mode_symlink + 7)); - fprintf (fp, "Other : %llx\n", - (avg_uid_other + 13) * (avg_gid_other + 11) * (avg_mode_other + 7)); - - return 0; + fprintf(fp, "\n"); + fprintf(fp, "Metadata checksums\n"); + fprintf(fp, "Regular files : %llx\n", + (avg_uid_file + 13) * (avg_gid_file + 11) * (avg_mode_file + 7)); + fprintf(fp, "Directories : %llx\n", + (avg_uid_dir + 13) * (avg_gid_dir + 11) * (avg_mode_dir + 7)); + fprintf(fp, "Symbolic links : %llx\n", + (avg_uid_symlink + 13) * (avg_gid_symlink + 11) * + (avg_mode_symlink + 7)); + fprintf(fp, "Other : %llx\n", + (avg_uid_other + 13) * (avg_gid_other + 11) * (avg_mode_other + 7)); + + return 0; } int -display_stats (FILE *fp) +display_stats(FILE *fp) { - display_counts (fp); + display_counts(fp); - display_metadata (fp); + display_metadata(fp); - display_checksums (fp); + display_checksums(fp); - return 0; + return 0; } - int main(int argc, char *argv[]) { - int ret = 0; - int i = 0; - - ret = argp_parse (&argp, argc, argv, 0, 0, NULL); - if (ret != 0) { - fprintf (stderr, "parsing arguments failed\n"); - return -2; - } - - /* Use FTW_ACTIONRETVAL to take decision on what to do depending upon */ - /* the return value of the callback function */ - /* (process_entry in this case) */ - ret = nftw (arequal_config.test_directory, process_entry, 30, - FTW_ACTIONRETVAL|FTW_PHYS|FTW_MOUNT); - if (ret != 0) { - fprintf (stderr, "ftw (%s) returned %d (%s), terminating\n", - argv[1], ret, strerror (errno)); - return 1; - } - - display_stats (stdout); - - if (arequal_config.ignored_directory) { - for (i = 0; i < arequal_config.directories_ignored; i++) { - if (arequal_config.ignored_directory[i]) - free (arequal_config.ignored_directory[i]); - } - free (arequal_config.ignored_directory); + int ret = 0; + int i = 0; + + ret = argp_parse(&argp, argc, argv, 0, 0, NULL); + if (ret != 0) { + fprintf(stderr, "parsing arguments failed\n"); + return -2; + } + + /* Use FTW_ACTIONRETVAL to take decision on what to do depending upon */ + /* the return value of the callback function */ + /* (process_entry in this case) */ + ret = nftw(arequal_config.test_directory, process_entry, 30, + FTW_ACTIONRETVAL | FTW_PHYS | FTW_MOUNT); + if (ret != 0) { + fprintf(stderr, "ftw (%s) returned %d (%s), terminating\n", argv[1], + ret, strerror(errno)); + return 1; + } + + display_stats(stdout); + + if (arequal_config.ignored_directory) { + for (i = 0; i < arequal_config.directories_ignored; i++) { + if (arequal_config.ignored_directory[i]) + free(arequal_config.ignored_directory[i]); } + free(arequal_config.ignored_directory); + } - return 0; + return 0; } diff --git a/tests/utils/changelog/changelog.h b/tests/utils/changelog/changelog.h new file mode 100644 index 00000000000..1502b689eb4 --- /dev/null +++ b/tests/utils/changelog/changelog.h @@ -0,0 +1,125 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#ifndef _GF_CHANGELOG_H +#define _GF_CHANGELOG_H + +struct gf_brick_spec; + +/** + * Max bit shiter for event selection + */ +#define CHANGELOG_EV_SELECTION_RANGE 5 + +#define CHANGELOG_OP_TYPE_JOURNAL (1 << 0) +#define CHANGELOG_OP_TYPE_OPEN (1 << 1) +#define CHANGELOG_OP_TYPE_CREATE (1 << 2) +#define CHANGELOG_OP_TYPE_RELEASE (1 << 3) +#define CHANGELOG_OP_TYPE_BR_RELEASE \ + (1 << 4) /* logical release (last close()), \ + sent by bitrot stub */ +#define CHANGELOG_OP_TYPE_MAX (1 << CHANGELOG_EV_SELECTION_RANGE) + +struct ev_open { + unsigned char gfid[16]; + int32_t flags; +}; + +struct ev_creat { + unsigned char gfid[16]; + int32_t flags; +}; + +struct ev_release { + unsigned char gfid[16]; +}; + +struct ev_release_br { + unsigned long version; + unsigned char gfid[16]; + int32_t sign_info; +}; + +struct ev_changelog { + char path[PATH_MAX]; +}; + +typedef struct changelog_event { + unsigned int ev_type; + + union { + struct ev_open open; + struct ev_creat create; + struct ev_release release; + struct ev_changelog journal; + struct ev_release_br releasebr; + } u; +} changelog_event_t; + +#define CHANGELOG_EV_SIZE (sizeof(changelog_event_t)) + +/** + * event callback, connected & disconnection defs + */ +typedef void(CALLBACK)(void *, char *, void *, changelog_event_t *); +typedef void *(INIT)(void *, struct gf_brick_spec *); +typedef void(FINI)(void *, char *, void *); +typedef void(CONNECT)(void *, char *, void *); +typedef void(DISCONNECT)(void *, char *, void *); + +struct gf_brick_spec { + char *brick_path; + unsigned int filter; + + INIT *init; + FINI *fini; + CALLBACK *callback; + CONNECT *connected; + DISCONNECT *disconnected; + + void *ptr; +}; + +/* API set */ + +int +gf_changelog_register(char *brick_path, char *scratch_dir, char *log_file, + int log_levl, int max_reconnects); +ssize_t +gf_changelog_scan(); + +int +gf_changelog_start_fresh(); + +ssize_t +gf_changelog_next_change(char *bufptr, size_t maxlen); + +int +gf_changelog_done(char *file); + +/* newer flexible API */ +int +gf_changelog_init(void *xl); + +int +gf_changelog_register_generic(struct gf_brick_spec *bricks, int count, + int ordered, char *logfile, int lvl, void *xl); + +int +gf_history_changelog(char *changelog_dir, unsigned long start, + unsigned long end, int n_parallel, + unsigned long *actual_end); +int +gf_history_changelog_scan(); +ssize_t +gf_history_changelog_next_change(char *bufptr, size_t maxlen); +int +gf_history_changelog_done(char *file); +#endif diff --git a/tests/utils/changelog/get-history.c b/tests/utils/changelog/get-history.c new file mode 100644 index 00000000000..9963ab76958 --- /dev/null +++ b/tests/utils/changelog/get-history.c @@ -0,0 +1,71 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/** + * get set of new changes every 10 seconds (just print the file names) + * + * Compile it using: + * gcc -o gethistory `pkg-config --cflags libgfchangelog` get-history.c \ + * `pkg-config --libs libgfchangelog` + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/un.h> +#include <limits.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "changelog.h" + +int +main(int argc, char **argv) +{ + int ret = 0; + unsigned long end_ts = 0; + int start = 0; + int end = 0; + + ret = gf_changelog_init(NULL); + if (ret) { + printf("-1"); + fflush(stdout); + return -1; + } + + ret = gf_changelog_register("/d/backends/patchy0", "/tmp/scratch_v1", + "/var/log/glusterfs/changes.log", 9, 5); + if (ret) { + printf("-2"); + fflush(stdout); + return -1; + } + + start = atoi(argv[1]); + end = atoi(argv[2]); + + ret = gf_history_changelog("/d/backends/patchy0/.glusterfs/changelogs", + start, end, 3, &end_ts); + if (ret < 0) { + printf("-3"); + fflush(stdout); + return -1; + } else if (ret == 1) { + printf("1"); + fflush(stdout); + return 0; + } + +out: + printf("0"); + fflush(stdout); + return 0; +} diff --git a/tests/utils/changelog/test-changelog-api.c b/tests/utils/changelog/test-changelog-api.c new file mode 100644 index 00000000000..f4eb066b630 --- /dev/null +++ b/tests/utils/changelog/test-changelog-api.c @@ -0,0 +1,98 @@ +/* + Copyright (c) 2019 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/** + * get set of new changes every 5 seconds (just print the file names) + * + * Compile it using: + * gcc -o getchanges `pkg-config --cflags libgfchangelog` get-changes.c \ + * `pkg-config --libs libgfchangelog` + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/un.h> +#include <limits.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <errno.h> + +#include "changelog.h" + +int +main(int argc, char **argv) +{ + int i = 0; + int ret = 0; + ssize_t nr_changes = 0; + ssize_t changes = 0; + char fbuf[PATH_MAX] = { + 0, + }; + + ret = gf_changelog_init(NULL); + if (ret) { + printf("-1"); + fflush(stdout); + return -1; + } + + /* get changes for brick "/d/backends/patchy0" */ + ret = gf_changelog_register("/d/backends/patchy0", "/tmp/scratch_v1", + "/var/log/glusterfs/changes.log", 9, 5); + if (ret) { + printf("-2"); + fflush(stdout); + return -1; + } + + while (1) { + i = 0; + nr_changes = gf_changelog_scan(); + if (nr_changes < 0) { + printf("-4"); + fflush(stdout); + return -1; + } + + if (nr_changes == 0) + goto next; + + while ((changes = gf_changelog_next_change(fbuf, PATH_MAX)) > 0) { + /* process changelog */ + /* ... */ + /* ... */ + /* ... */ + /* done processing */ + + ret = gf_changelog_done(fbuf); + if (ret) { + printf("-5"); + fflush(stdout); + return -1; + } + } + + if (changes == -1) { + printf("-6"); + fflush(stdout); + return -1; + } + + next: + sleep(2); + } + +out: + printf("0"); + fflush(stdout); + return ret; +} diff --git a/tests/utils/changelog/test-history-api.c b/tests/utils/changelog/test-history-api.c new file mode 100644 index 00000000000..d78e387df10 --- /dev/null +++ b/tests/utils/changelog/test-history-api.c @@ -0,0 +1,111 @@ +/* + Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +/** + * get set of new changes every 10 seconds (just print the file names) + * + * Compile it using: + * gcc -o gethistory `pkg-config --cflags libgfchangelog` get-history.c \ + * `pkg-config --libs libgfchangelog` + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/un.h> +#include <limits.h> +#include <sys/socket.h> +#include <sys/types.h> + +#include "changelog.h" + +int +main(int argc, char **argv) +{ + int ret = 0; + int i = 0; + unsigned long end_ts = 0; + ssize_t nr_changes = 0; + ssize_t changes = 0; + int start = 0; + int end = 0; + char fbuf[PATH_MAX] = { + 0, + }; + + ret = gf_changelog_init(NULL); + if (ret) { + printf("-1"); + fflush(stdout); + return -1; + } + + ret = gf_changelog_register("/d/backends/patchy0", "/tmp/scratch_v1", + "/var/log/glusterfs/changes.log", 9, 5); + if (ret) { + printf("-2"); + fflush(stdout); + return -1; + } + + start = atoi(argv[1]); + end = atoi(argv[2]); + + ret = gf_history_changelog("/d/backends/patchy0/.glusterfs/changelogs", + start, end, 3, &end_ts); + if (ret < 0) { + printf("-3"); + fflush(stdout); + return -1; + } else if (ret == 1) { + printf("1"); + fflush(stdout); + return 0; + } + + while (1) { + nr_changes = gf_history_changelog_scan(); + if (nr_changes < 0) { + printf("-4"); + fflush(stdout); + return -1; + } + + if (nr_changes == 0) { + goto out; + } + + while ((changes = gf_history_changelog_next_change(fbuf, PATH_MAX)) > + 0) { + /* process changelog */ + /* ... */ + /* ... */ + /* ... */ + /* done processing */ + + ret = gf_history_changelog_done(fbuf); + if (ret) { + printf("-5"); + fflush(stdout); + return -1; + } + } + if (changes == -1) { + printf("-6"); + fflush(stdout); + return -1; + } + } + +out: + printf("0"); + fflush(stdout); + return 0; +} diff --git a/tests/utils/changelogparser.py b/tests/utils/changelogparser.py new file mode 100644 index 00000000000..3b8f81d1bad --- /dev/null +++ b/tests/utils/changelogparser.py @@ -0,0 +1,236 @@ +# -*- coding: utf-8 -*- +""" +Why? + +Converts this + +GlusterFS Changelog | version: v1.1 | encoding : 2 +E0b99ef11-4b79-4cd0-9730-b5a0e8c4a8c0^@4^@16877^@0^@0^@00000000-0000-0000-0000- +000000000001/dir1^@Ec5250af6-720e-4bfe-b938-827614304f39^@23^@33188^@0^@0^@0b99 +ef11-4b79-4cd0-9730-b5a0e8c4a8c0/hello.txt^@Dc5250af6-720e-4bfe-b938-827614304f +39^@Dc5250af6-720e-4bfe-b938-827614304f39^@ + + +to human readable :) + +E 0b99ef11-4b79-4cd0-9730-b5a0e8c4a8c0 MKDIR 16877 0 000000000-0000-0000-0000 + -000000000001/dir1 +E c5250af6-720e-4bfe-b938-827614304f39 CREATE 33188 0 0 0b99ef11-4b79-4cd0-9730 + -b5a0e8c4a8c0/hello.txt +D c5250af6-720e-4bfe-b938-827614304f39 +D c5250af6-720e-4bfe-b938-827614304f39 + + +""" +import sys +import codecs + +ENTRY = 'E' +META = 'M' +DATA = 'D' +SEP = "\x00" + +GF_FOP = [ + "NULL", "STAT", "READLINK", "MKNOD", "MKDIR", "UNLINK", + "RMDIR", "SYMLINK", "RENAME", "LINK", "TRUNCATE", "OPEN", + "READ", "WRITE", "STATFS", "FLUSH", "FSYNC", "SETXATTR", + "GETXATTR", "REMOVEXATTR", "OPENDIR", "FSYNCDIR", "ACCESS", + "CREATE", "FTRUNCATE", "FSTAT", "LK", "LOOKUP", "READDIR", + "INODELK", "FINODELK", "ENTRYLK", "FENTRYLK", "XATTROP", + "FXATTROP", "FSETXATTR", "FGETXATTR", "RCHECKSUM", "SETATTR", + "FSETATTR", "READDIRP", "GETSPEC", "FORGET", "RELEASE", + "RELEASEDIR", "FREMOVEXATTR", "FALLOCATE", "DISCARD", "ZEROFILL"] + + +class NumTokens_V11(object): + E = 7 + M = 3 + D = 2 + NULL = 3 + MKNOD = 7 + MKDIR = 7 + UNLINK = 4 + RMDIR = 4 + SYMLINK = 4 + RENAME = 5 + LINK = 4 + SETXATTR = 3 + REMOVEXATTR = 3 + CREATE = 7 + SETATTR = 3 + FTRUNCATE = 3 + FXATTROP = 3 + + +class NumTokens_V12(NumTokens_V11): + UNLINK = 5 + RMDIR = 5 + + +class Version: + V11 = "v1.1" + V12 = "v1.2" + + +class Record(object): + def __init__(self, **kwargs): + self.ts = kwargs.get("ts", None) + self.fop_type = kwargs.get("fop_type", None) + self.gfid = kwargs.get("gfid", None) + self.path = kwargs.get("path", None) + self.fop = kwargs.get("fop", None) + self.path1 = kwargs.get("path1", None) + self.path2 = kwargs.get("path2", None) + self.mode = kwargs.get("mode", None) + self.uid = kwargs.get("uid", None) + self.gid = kwargs.get("gid", None) + + def create_mknod_mkdir(self, **kwargs): + self.path = kwargs.get("path", None) + self.fop = kwargs.get("fop", None) + self.mode = kwargs.get("mode", None) + self.uid = kwargs.get("uid", None) + self.gid = kwargs.get("gid", None) + + def metadata(self, **kwargs): + self.fop = kwargs.get("fop", None) + + def rename(self, **kwargs): + self.fop = kwargs.get("fop", None) + self.path1 = kwargs.get("path1", None) + self.path2 = kwargs.get("path2", None) + + def link_symlink_unlink_rmdir(self, **kwargs): + self.path = kwargs.get("path", None) + self.fop = kwargs.get("fop", None) + + def __unicode__(self): + if self.fop_type == "D": + return u"{ts} {fop_type} {gfid}".format(**self.__dict__) + elif self.fop_type == "M": + return u"{ts} {fop_type} {gfid} {fop}".format(**self.__dict__) + elif self.fop_type == "E": + if self.fop in ["CREATE", "MKNOD", "MKDIR"]: + return (u"{ts} {fop_type} {gfid} {fop} " + u"{path} {mode} {uid} {gid}".format(**self.__dict__)) + elif self.fop == "RENAME": + return (u"{ts} {fop_type} {gfid} {fop} " + u"{path1} {path2}".format(**self.__dict__)) + elif self.fop in ["LINK", "SYMLINK", "UNLINK", "RMDIR"]: + return (u"{ts} {fop_type} {gfid} {fop} " + u"{path}".format(**self.__dict__)) + else: + return repr(self.__dict__) + else: + return repr(self.__dict__) + + def __str__(self): + if sys.version_info >= (3,): + return self.__unicode__() + else: + return unicode(self).encode('utf-8') + + +def get_num_tokens(data, tokens, version=Version.V11): + if version == Version.V11: + cls_numtokens = NumTokens_V11 + elif version == Version.V12: + cls_numtokens = NumTokens_V12 + else: + sys.stderr.write("Unknown Changelog Version\n") + sys.exit(1) + + if data[tokens[0]] in [ENTRY, META]: + if len(tokens) >= 3: + return getattr(cls_numtokens, GF_FOP[int(data[tokens[2]])]) + else: + return None + else: + return getattr(cls_numtokens, data[tokens[0]]) + + +def process_record(data, tokens, changelog_ts, callback): + if data[tokens[0]] in [ENTRY, META]: + try: + tokens[2] = GF_FOP[int(data[tokens[2]])] + except ValueError: + tokens[2] = "NULL" + + if not changelog_ts: + ts1 = int(changelog_ts) + else: + ts1="" + record = Record(ts=ts1, fop_type=data[tokens[0]], + gfid=data[tokens[1]]) + if data[tokens[0]] == META: + record.metadata(fop=tokens[2]) + elif data[tokens[0]] == ENTRY: + if tokens[2] in ["CREATE", "MKNOD", "MKDIR"]: + record.create_mknod_mkdir(fop=tokens[2], + path=data[tokens[6]], + mode=int(data[tokens[3]]), + uid=int(data[tokens[4]]), + gid=int(data[tokens[5]])) + elif tokens[2] == "RENAME": + record.rename(fop=tokens[2], + path1=data[tokens[3]], + path2=data[tokens[4]]) + if tokens[2] in ["LINK", "SYMLINK", "UNLINK", "RMDIR"]: + record.link_symlink_unlink_rmdir(fop=tokens[2], + path=data[tokens[3]]) + callback(record) + + +def default_callback(record): + sys.stdout.write(u"{0}\n".format(record)) + + +def parse(filename, callback=default_callback): + data = None + tokens = [] + changelog_ts = filename.rsplit(".")[-1] + with codecs.open(filename, mode="rb", encoding="utf-8") as f: + # GlusterFS Changelog | version: v1.1 | encoding : 2 + header = f.readline() + version = header.split()[4] + + data = f.readline() + + slice_start = 0 + in_record = False + + prev_char = "" + next_char = "" + for i, c in enumerate(data): + next_char = "" + if len(data) >= (i + 2): + next_char = data[i+1] + + if not in_record and c in [ENTRY, META, DATA]: + tokens.append(slice(slice_start, i+1)) + slice_start = i+1 + in_record = True + continue + + if c == SEP and ((prev_char != SEP and next_char == SEP) or + (prev_char == SEP and next_char != SEP) or + (prev_char != SEP and next_char != SEP)): + tokens.append(slice(slice_start, i)) + slice_start = i+1 + + num_tokens = get_num_tokens(data, tokens, version) + + if num_tokens == len(tokens): + process_record(data, tokens, changelog_ts, callback) + in_record = False + tokens = [] + + prev_char = c + + # process last record + if slice_start < (len(data) - 1): + tokens.append(slice(slice_start, len(data))) + process_record(data, tokens, changelog_ts, callback) + tokens = [] + +parse(sys.argv[1]) diff --git a/tests/utils/create-files.py b/tests/utils/create-files.py index bef4201bf1f..04736e9c73b 100755 --- a/tests/utils/create-files.py +++ b/tests/utils/create-files.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2 # This script was developed by Vijaykumar Koppad (vkoppad@redhat.com) # The latest version of this script can found at @@ -20,6 +19,11 @@ import argparse datsiz = 0 timr = 0 +def get_ascii_upper_alpha_digits(): + if sys.version_info > (3,0): + return string.ascii_uppercase+string.digits + else: + return string.uppercase+string.digits def setLogger(filename): global logger @@ -51,7 +55,7 @@ def os_rd(src, size): def os_wr(dest, data): global timr st = time.time() - fd = os.open(dest, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0644) + fd = os.open(dest, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) os.write(fd, data) os.close(fd) ed = time.time() @@ -88,7 +92,7 @@ def create_txt_file(fil, size, mins, maxs, rand): else: data = os_rd("/etc/services", 512*1024) file_size = 0 - fd = os.open(fil, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0644) + fd = os.open(fil, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) while file_size < size: os.write(fd, data) file_size += 500*1024 @@ -112,7 +116,7 @@ def create_tar_file(fil, size, mins, maxs, rand): def get_filename(flen): size = flen - char = string.uppercase+string.digits + char = get_ascii_upper_alpha_digits() st = ''.join(random.choice(char) for i in range(size)) ti = str((hex(int(str(time.time()).split('.')[0])))[2:]) return ti+"%%"+st @@ -176,7 +180,7 @@ def tar_files(files, file_count, inter, size, mins, maxs, def setxattr_files(files, randname, dir_path): - char = string.uppercase+string.digits + char = get_ascii_upper_alpha_digits() if not randname: for k in range(files): v = ''.join(random.choice(char) for i in range(10)) @@ -323,9 +327,9 @@ def human2bytes(size): def bytes2human(byts): abbr = { - 1 << 30L: "GB", - 1 << 20L: "MB", - 1 << 10L: "KB", + 1 << 30: "GB", + 1 << 20: "MB", + 1 << 10: "KB", 1: "bytes" } if byts == 1: diff --git a/tests/utils/get-mdata-xattr.c b/tests/utils/get-mdata-xattr.c new file mode 100644 index 00000000000..e9f54717263 --- /dev/null +++ b/tests/utils/get-mdata-xattr.c @@ -0,0 +1,152 @@ +/* + Copyright (c) 2019 Red Hat, Inc. <http://www.redhat.com> + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + +#include <stdlib.h> +#include <endian.h> +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <inttypes.h> +#include <sys/types.h> +#include <sys/xattr.h> +#include <errno.h> + +typedef struct gf_timespec_disk { + uint64_t tv_sec; + uint64_t tv_nsec; +} gf_timespec_disk_t; + +/* posix_mdata_t on disk structure */ +typedef struct __attribute__((__packed__)) posix_mdata_disk { + /* version of structure, bumped up if any new member is added */ + uint8_t version; + /* flags indicates valid fields in the structure */ + uint64_t flags; + gf_timespec_disk_t ctime; + gf_timespec_disk_t mtime; + gf_timespec_disk_t atime; +} posix_mdata_disk_t; + +/* In memory representation posix metadata xattr */ +typedef struct { + /* version of structure, bumped up if any new member is added */ + uint8_t version; + /* flags indicates valid fields in the structure */ + uint64_t flags; + struct timespec ctime; + struct timespec mtime; + struct timespec atime; +} posix_mdata_t; + +#define GF_XATTR_MDATA_KEY "trusted.glusterfs.mdata" + +/* posix_mdata_from_disk converts posix_mdata_disk_t into host byte order + */ +static inline void +posix_mdata_from_disk(posix_mdata_t *out, posix_mdata_disk_t *in) +{ + out->version = in->version; + out->flags = be64toh(in->flags); + + out->ctime.tv_sec = be64toh(in->ctime.tv_sec); + out->ctime.tv_nsec = be64toh(in->ctime.tv_nsec); + + out->mtime.tv_sec = be64toh(in->mtime.tv_sec); + out->mtime.tv_nsec = be64toh(in->mtime.tv_nsec); + + out->atime.tv_sec = be64toh(in->atime.tv_sec); + out->atime.tv_nsec = be64toh(in->atime.tv_nsec); +} + +/* posix_fetch_mdata_xattr fetches the posix_mdata_t from disk */ +static int +posix_fetch_mdata_xattr(const char *real_path, posix_mdata_t *metadata) +{ + size_t size = -1; + char *value = NULL; + char gfid_str[64] = {0}; + + char *key = GF_XATTR_MDATA_KEY; + + if (!metadata || !real_path) { + goto err; + } + + /* Get size */ + size = lgetxattr(real_path, key, NULL, 0); + if (size == -1) { + goto err; + } + + value = calloc(size + 1, sizeof(char)); + if (!value) { + goto err; + } + + /* Get xattr value */ + size = lgetxattr(real_path, key, value, size); + if (size == -1) { + goto err; + } + posix_mdata_from_disk(metadata, (posix_mdata_disk_t *)value); + +out: + if (value) + free(value); + return 0; +err: + if (value) + free(value); + return -1; +} + +int +main(int argc, char *argv[]) +{ + posix_mdata_t metadata; + uint64_t result; + + if (argc != 3) { + /* + Usage: get_mdata_xattr -c|-m|-a <file-name> + where -c --> ctime + -m --> mtime + -a --> atime + */ + printf("-1"); + goto err; + } + + if (posix_fetch_mdata_xattr(argv[2], &metadata)) { + printf("-1"); + goto err; + } + + switch (argv[1][1]) { + case 'c': + result = metadata.ctime.tv_sec; + break; + case 'm': + result = metadata.mtime.tv_sec; + break; + case 'a': + result = metadata.atime.tv_sec; + break; + default: + printf("-1"); + goto err; + } + printf("%" PRIu64, result); + fflush(stdout); + return 0; +err: + fflush(stdout); + return -1; +} diff --git a/tests/utils/getfattr.py b/tests/utils/getfattr.py index 1a8369af7c4..3eb40e1c887 100755 --- a/tests/utils/getfattr.py +++ b/tests/utils/getfattr.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python2 +from __future__ import print_function import os import sys from optparse import OptionParser @@ -32,22 +32,22 @@ def getfattr(path, option): def print_getfattr (path, option, encoded_attr=None): if encoded_attr: if option.encoding == "hex": - print ("%s=0x%s" % (option.name, encoded_attr)) + print(("%s=0x%s" % (option.name, encoded_attr))) elif option.encoding == "base64": - print ("%s=0s%s" % (option.name, encoded_attr)) + print(("%s=0s%s" % (option.name, encoded_attr))) else: - print ("%s=\"%s\"" % (option.name, encoded_attr)) + print(("%s=\"%s\"" % (option.name, encoded_attr))) else: - print option.name + print(option.name) return def print_header (path, absnames): if absnames: - print ("# file: %s" % path) + print(("# file: %s" % path)) else: print ("getfattr: Removing leading '/' from absolute path names") - print ("# file: %s" % path[1:]) + print(("# file: %s" % path[1:])) if __name__ == '__main__': usage = "usage: %prog [-n name|-d] [-e en] [-m pattern] path...." @@ -64,7 +64,7 @@ if __name__ == '__main__': " them. Valid values of [en] are `text`, `hex`," " and `base64`. Values encoded as text strings are" " enclosed in double quotes (\"), while strings" - " encoded as hexidecimal and base64 are prefixed with" + " encoded as hexadecimal and base64 are prefixed with" " 0x and 0s, respectively.") parser.add_option("-m", action="store", dest="pattern", type="string", help="Only include attributes with names matching the" @@ -99,8 +99,8 @@ if __name__ == '__main__': if (not (option.encoding.strip() == "hex" or option.encoding.strip() == "base64" or option.encoding.strip() == "text")): - print ("unrecognized encoding parameter... %s, please use" - " `text`, `base64` or `hex`" % option.encoding) + print(("unrecognized encoding parameter... %s, please use" + " `text`, `base64` or `hex`" % option.encoding)) sys.exit(1) args[0] = os.path.abspath(args[0]) @@ -110,7 +110,7 @@ if __name__ == '__main__': try: getfattr(args[0], option) except KeyError as err: - print ("Invalid key %s" % err) + print(("Invalid key %s" % err)) sys.exit(1) except IOError as err: print (err) diff --git a/tests/utils/gfid-access.py b/tests/utils/gfid-access.py index 81258073da1..c35c1223df6 100755 --- a/tests/utils/gfid-access.py +++ b/tests/utils/gfid-access.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2 # # Copyright (c) 2011-2014 Red Hat, Inc. <http://www.redhat.com> # This file is part of GlusterFS. @@ -9,6 +8,7 @@ # cases as published by the Free Software Foundation. # +from __future__ import print_function import os import sys import stat @@ -33,28 +33,56 @@ def _fmt_mkdir(l): def _fmt_symlink(l1, l2): return "!II%dsI%ds%ds" % (37, l1+1, l2+1) -def entry_pack_reg(gf, bn, mo, uid, gid): - blen = len(bn) - return struct.pack(_fmt_mknod(blen), - uid, gid, gf, mo, bn, - stat.S_IMODE(mo), 0, umask()) -def entry_pack_dir(gf, bn, mo, uid, gid): - blen = len(bn) - return struct.pack(_fmt_mkdir(blen), - uid, gid, gf, mo, bn, - stat.S_IMODE(mo), umask()) - -def entry_pack_symlink(gf, bn, lnk, mo, uid, gid): - blen = len(bn) - llen = len(lnk) - return struct.pack(_fmt_symlink(blen, llen), - uid, gid, gf, mo, bn, lnk) +if sys.version_info > (3,): + def entry_pack_reg(gf, bn, mo, uid, gid): + bn_encoded = bn.encode() + blen = len(bn_encoded) + return struct.pack(_fmt_mknod(blen), + uid, gid, gf.encode(), mo, bn_encoded, + stat.S_IMODE(mo), 0, umask()) + + # mkdir + def entry_pack_dir(gf, bn, mo, uid, gid): + bn_encoded = bn.encode() + blen = len(bn_encoded) + return struct.pack(_fmt_mkdir(blen), + uid, gid, gf.encode(), mo, bn_encoded, + stat.S_IMODE(mo), umask()) + # symlink + def entry_pack_symlink(gf, bn, lnk, st): + bn_encoded = bn.encode() + blen = len(bn_encoded) + lnk_encoded = lnk.encode() + llen = len(lnk_encoded) + return struct.pack(_fmt_symlink(blen, llen), + st['uid'], st['gid'], + gf.encode(), st['mode'], bn_encoded, + lnk_encoded) + +else: + def entry_pack_reg(gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(_fmt_mknod(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), 0, umask()) + + def entry_pack_dir(gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(_fmt_mkdir(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), umask()) + + def entry_pack_symlink(gf, bn, lnk, mo, uid, gid): + blen = len(bn) + llen = len(lnk) + return struct.pack(_fmt_symlink(blen, llen), + uid, gid, gf, mo, bn, lnk) if __name__ == '__main__': if len(sys.argv) < 9: - print("USAGE: %s <mount> <pargfid|ROOT> <filename> <GFID> <file type>" - " <uid> <gid> <file permission(octal str)>" % (sys.argv[0])) + print(("USAGE: %s <mount> <pargfid|ROOT> <filename> <GFID> <file type>" + " <uid> <gid> <file permission(octal str)>" % (sys.argv[0]))) sys.exit(-1) # nothing to do mtpt = sys.argv[1] pargfid = sys.argv[2] @@ -63,7 +91,7 @@ if __name__ == '__main__': ftype = sys.argv[5] uid = int(sys.argv[6]) gid = int(sys.argv[7]) - perm = int(sys.argv[8],8) + perm = int(sys.argv[8], 8) os.chdir(mtpt) if pargfid == 'ROOT': @@ -92,5 +120,5 @@ if __name__ == '__main__': if not ex.errno in [EEXIST]: raise sys.exit(-1) - print "File creation OK" + print("File creation OK") sys.exit(0) diff --git a/tests/utils/libcxattr.py b/tests/utils/libcxattr.py index 149db72e6ee..3f3ed1fffbb 100644 --- a/tests/utils/libcxattr.py +++ b/tests/utils/libcxattr.py @@ -10,13 +10,14 @@ import os import sys -from ctypes import CDLL, c_int, create_string_buffer -from ctypes.util import find_library +from ctypes import CDLL, c_int +from py2py3 import bytearray_to_str, gr_create_string_buffer +from py2py3 import gr_query_xattr, gr_lsetxattr, gr_lremovexattr class Xattr(object): - """singleton that wraps the extended attribues system + """singleton that wraps the extended attributes system interface for python using ctypes Just implement it to the degree we need it, in particular @@ -28,9 +29,9 @@ class Xattr(object): if sys.hexversion >= 0x02060000: from ctypes import DEFAULT_MODE - libc = CDLL(find_library("libc"), DEFAULT_MODE, None, True) + libc = CDLL("libc.so.6", DEFAULT_MODE, None, True) else: - libc = CDLL(find_library("libc")) + libc = CDLL("libc.so.6") @classmethod def geterrno(cls): @@ -48,20 +49,23 @@ class Xattr(object): @classmethod def _query_xattr(cls, path, siz, syscall, *a): if siz: - buf = create_string_buffer('\0' * siz) + buf = gr_create_string_buffer(siz) else: buf = None ret = getattr(cls.libc, syscall)(*((path,) + a + (buf, siz))) if ret == -1: cls.raise_oserr() if siz: - return buf.raw[:ret] + # py2 and py3 compatibility. Convert bytes array + # to string + result = bytearray_to_str(buf.raw) + return result[:ret] else: return ret @classmethod def lgetxattr(cls, path, attr, siz=0): - return cls._query_xattr(path, siz, 'lgetxattr', attr) + return gr_query_xattr(cls, path, siz, 'lgetxattr', attr) @classmethod def lgetxattr_buf(cls, path, attr): @@ -75,20 +79,21 @@ class Xattr(object): @classmethod def llistxattr(cls, path, siz=0): - ret = cls._query_xattr(path, siz, 'llistxattr') + ret = gr_query_xattr(cls, path, siz, 'llistxattr') if isinstance(ret, str): - ret = ret.split('\0') + ret = ret.strip('\0') + ret = ret.split('\0') if ret else [] return ret @classmethod def lsetxattr(cls, path, attr, val): - ret = cls.libc.lsetxattr(path, attr, val, len(val), 0) + ret = gr_lsetxattr(cls, path, attr, val) if ret == -1: cls.raise_oserr() @classmethod def lremovexattr(cls, path, attr): - ret = cls.libc.lremovexattr(path, attr) + ret = gr_lremovexattr(cls, path, attr) if ret == -1: cls.raise_oserr() diff --git a/tests/utils/pidof.py b/tests/utils/pidof.py index 575b899b6cc..4b7071c0a48 100755 --- a/tests/utils/pidof.py +++ b/tests/utils/pidof.py @@ -1,5 +1,5 @@ -#!/usr/bin/env python +from __future__ import print_function import sys try: @@ -21,14 +21,14 @@ def pidof(processname): continue if "gluster" in processname: if processname == "glusterd" and pmap_find(p, "glusterd"): - print (p.pid) + print((p.pid)) if processname == "glusterfs" and pmap_find(p, "client"): - print (p.pid) + print((p.pid)) if processname == "glusterfsd" and pmap_find(p, "posix-acl"): - print (p.pid) + print((p.pid)) continue if processname.strip() == p.name(): - print (p.pid) + print((p.pid)) def main(argv): if len(argv) < 2: @@ -37,7 +37,7 @@ def main(argv): try: pidof(argv[1]) except Exception as err: - print err + print(err) sys.stderr.write("Please be root - %s\n" % err); sys.exit(1) diff --git a/tests/utils/py2py3.py b/tests/utils/py2py3.py new file mode 100644 index 00000000000..63aca10fd26 --- /dev/null +++ b/tests/utils/py2py3.py @@ -0,0 +1,186 @@ +# +# Copyright (c) 2018 Red Hat, Inc. <http://www.redhat.com> +# This file is part of GlusterFS. + +# This file is licensed to you under your choice of the GNU Lesser +# General Public License, version 3 or any later version (LGPLv3 or +# later), or the GNU General Public License, version 2 (GPLv2), in all +# cases as published by the Free Software Foundation. +# + +# All python2/python3 compatibility routines + +import sys +import os +import stat +import struct +from ctypes import create_string_buffer + +def umask(): + return os.umask(0) + +if sys.version_info >= (3,): + def pipe(): + (r, w) = os.pipe() + os.set_inheritable(r, True) + os.set_inheritable(w, True) + return (r, w) + + # Raw conversion of bytearray to string. Used in the cases where + # buffer is created by create_string_buffer which is a 8-bit char + # array and passed to syscalls to fetch results. Using encode/decode + # doesn't work as it converts to string altering the size. + def bytearray_to_str(byte_arr): + return ''.join([chr(b) for b in byte_arr]) + + # Raw conversion of string to bytes. This is required to convert + # back the string into bytearray(c char array) to use in struc + # pack/unpacking. Again encode/decode can't be used as it + # converts it alters size. + def str_to_bytearray(string): + return bytes([ord(c) for c in string]) + + def gr_create_string_buffer(size): + return create_string_buffer(b'\0', size) + + def gr_query_xattr(cls, path, size, syscall, attr=None): + if attr: + return cls._query_xattr(path.encode(), size, syscall, + attr.encode()) + else: + return cls._query_xattr(path.encode(), size, syscall) + + def gr_lsetxattr(cls, path, attr, val): + return cls.libc.lsetxattr(path.encode(), attr.encode(), val, + len(val), 0) + + def gr_lremovexattr(cls, path, attr): + return cls.libc.lremovexattr(path.encode(), attr.encode()) + + def gr_cl_register(cls, brick, path, log_file, log_level, retries): + return cls._get_api('gf_changelog_register')(brick.encode(), + path.encode(), + log_file.encode(), + log_level, retries) + + def gr_cl_done(cls, clfile): + return cls._get_api('gf_changelog_done')(clfile.encode()) + + def gr_cl_history_changelog(cls, changelog_path, start, end, num_parallel, + actual_end): + return cls._get_api('gf_history_changelog')(changelog_path.encode(), + start, end, num_parallel, + actual_end) + + def gr_cl_history_done(cls, clfile): + return cls._get_api('gf_history_changelog_done')(clfile.encode()) + + # regular file + + def entry_pack_reg(cls, gf, bn, mo, uid, gid): + bn_encoded = bn.encode() + blen = len(bn_encoded) + return struct.pack(cls._fmt_mknod(blen), + uid, gid, gf.encode(), mo, bn_encoded, + stat.S_IMODE(mo), 0, umask()) + + def entry_pack_reg_stat(cls, gf, bn, st): + bn_encoded = bn.encode() + blen = len(bn_encoded) + mo = st['mode'] + return struct.pack(cls._fmt_mknod(blen), + st['uid'], st['gid'], + gf.encode(), mo, bn_encoded, + stat.S_IMODE(mo), 0, umask()) + # mkdir + + def entry_pack_mkdir(cls, gf, bn, mo, uid, gid): + bn_encoded = bn.encode() + blen = len(bn_encoded) + return struct.pack(cls._fmt_mkdir(blen), + uid, gid, gf.encode(), mo, bn_encoded, + stat.S_IMODE(mo), umask()) + # symlink + + def entry_pack_symlink(cls, gf, bn, lnk, st): + bn_encoded = bn.encode() + blen = len(bn_encoded) + lnk_encoded = lnk.encode() + llen = len(lnk_encoded) + return struct.pack(cls._fmt_symlink(blen, llen), + st['uid'], st['gid'], + gf.encode(), st['mode'], bn_encoded, + lnk_encoded) +else: + def pipe(): + (r, w) = os.pipe() + return (r, w) + + # Raw conversion of bytearray to string + def bytearray_to_str(byte_arr): + return byte_arr + + # Raw conversion of string to bytearray + def str_to_bytearray(string): + return string + + def gr_create_string_buffer(size): + return create_string_buffer('\0', size) + + def gr_query_xattr(cls, path, size, syscall, attr=None): + if attr: + return cls._query_xattr(path, size, syscall, attr) + else: + return cls._query_xattr(path, size, syscall) + + def gr_lsetxattr(cls, path, attr, val): + return cls.libc.lsetxattr(path, attr, val, len(val), 0) + + def gr_lremovexattr(cls, path, attr): + return cls.libc.lremovexattr(path, attr) + + def gr_cl_register(cls, brick, path, log_file, log_level, retries): + return cls._get_api('gf_changelog_register')(brick, path, log_file, + log_level, retries) + + def gr_cl_done(cls, clfile): + return cls._get_api('gf_changelog_done')(clfile) + + def gr_cl_history_changelog(cls, changelog_path, start, end, num_parallel, + actual_end): + return cls._get_api('gf_history_changelog')(changelog_path, start, end, + num_parallel, actual_end) + + def gr_cl_history_done(cls, clfile): + return cls._get_api('gf_history_changelog_done')(clfile) + + # regular file + + def entry_pack_reg(cls, gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(cls._fmt_mknod(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), 0, umask()) + + def entry_pack_reg_stat(cls, gf, bn, st): + blen = len(bn) + mo = st['mode'] + return struct.pack(cls._fmt_mknod(blen), + st['uid'], st['gid'], + gf, mo, bn, + stat.S_IMODE(mo), 0, umask()) + # mkdir + + def entry_pack_mkdir(cls, gf, bn, mo, uid, gid): + blen = len(bn) + return struct.pack(cls._fmt_mkdir(blen), + uid, gid, gf, mo, bn, + stat.S_IMODE(mo), umask()) + # symlink + + def entry_pack_symlink(cls, gf, bn, lnk, st): + blen = len(bn) + llen = len(lnk) + return struct.pack(cls._fmt_symlink(blen, llen), + st['uid'], st['gid'], + gf, st['mode'], bn, lnk) diff --git a/tests/utils/setfattr.py b/tests/utils/setfattr.py index d714d05edf3..8b7b6abacc0 100755 --- a/tests/utils/setfattr.py +++ b/tests/utils/setfattr.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2 import os import sys @@ -46,7 +45,7 @@ if __name__ == '__main__': parser.add_option("-x", action="store", dest="xname", type="string", help="Remove the named extended attribute entirely.") - (option,args) = parser.parse_args() + (option, args) = parser.parse_args() if not args: print ("Usage: setfattr {-n name} [-v value] file...") print (" setfattr {-x name} file...") |
