diff options
| author | David M. Syzdek <david@syzdek.net> | 2022-05-31 21:15:24 -0800 |
|---|---|---|
| committer | David M. Syzdek <david@syzdek.net> | 2022-05-31 21:15:24 -0800 |
| commit | 6027ce0f27f61f5b140351f994e4256922c3f10e (patch) | |
| tree | 2201c01d45c99d4c46340213c21ad0a024a8ea35 | |
| parent | 438264cc803f38fa2b448a66df2b77b3a867824f (diff) | |
| download | bindletools-6027ce0f27f61f5b140351f994e4256922c3f10e.tar.gz bindletools-6027ce0f27f61f5b140351f994e4256922c3f10e.tar.bz2 bindletools-6027ce0f27f61f5b140351f994e4256922c3f10e.tar.xz bindletools-6027ce0f27f61f5b140351f994e4256922c3f10e.zip | |
libbindle: adding bindle_basename() and bindle_basename_r()
| -rw-r--r-- | build-aux/makefile-libbindle.am | 11 | ||||
| -rw-r--r-- | checks/bindle-str-basename.c | 238 | ||||
| -rw-r--r-- | include/bindle.h | 12 | ||||
| -rw-r--r-- | lib/libbindle/lstring.c | 57 |
4 files changed, 318 insertions, 0 deletions
diff --git a/build-aux/makefile-libbindle.am b/build-aux/makefile-libbindle.am index 48422e3..19a9089 100644 --- a/build-aux/makefile-libbindle.am +++ b/build-aux/makefile-libbindle.am | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | EXTRA_PROGRAMS += tests/bindle-array-queue \ | 31 | EXTRA_PROGRAMS += tests/bindle-array-queue \ |
| 32 | tests/bindle-array-sorted \ | 32 | tests/bindle-array-sorted \ |
| 33 | tests/bindle-array-stack \ | 33 | tests/bindle-array-stack \ |
| 34 | tests/bindle-str-basename \ | ||
| 34 | tests/bindle-str-expand \ | 35 | tests/bindle-str-expand \ |
| 35 | tests/bindle-str-split \ | 36 | tests/bindle-str-split \ |
| 36 | tests/bindle-url-encoding \ | 37 | tests/bindle-url-encoding \ |
| @@ -38,6 +39,7 @@ EXTRA_PROGRAMS += tests/bindle-array-queue \ | |||
| 38 | LIBBINDLE_TESTS = tests/bindle-array-queue \ | 39 | LIBBINDLE_TESTS = tests/bindle-array-queue \ |
| 39 | tests/bindle-array-sorted \ | 40 | tests/bindle-array-sorted \ |
| 40 | tests/bindle-array-stack \ | 41 | tests/bindle-array-stack \ |
| 42 | tests/bindle-str-basename \ | ||
| 41 | tests/bindle-str-expand \ | 43 | tests/bindle-str-expand \ |
| 42 | tests/bindle-str-split \ | 44 | tests/bindle-str-split \ |
| 43 | tests/bindle-url-encoding \ | 45 | tests/bindle-url-encoding \ |
| @@ -108,6 +110,15 @@ tests_bindle_array_stack_SOURCES = $(bindletools_srcdir)/include/bindle.h \ | |||
| 108 | $(bindletools_srcdir)/checks/bindle-array-stack.c | 110 | $(bindletools_srcdir)/checks/bindle-array-stack.c |
| 109 | 111 | ||
| 110 | 112 | ||
| 113 | # macros for tests/bindle-str-basename | ||
| 114 | tests_bindle_str_basename_DEPENDENCIES = lib/libbindle.a | ||
| 115 | tests_bindle_str_basename_LDADD = lib/libbindle.a | ||
| 116 | tests_bindle_str_basename_SOURCES = $(bindletools_srcdir)/include/bindle.h \ | ||
| 117 | $(bindletools_srcdir)/checks/bindle-tests.h \ | ||
| 118 | $(bindletools_srcdir)/checks/bindle-tests.c \ | ||
| 119 | $(bindletools_srcdir)/checks/bindle-str-basename.c | ||
| 120 | |||
| 121 | |||
| 111 | # macros for tests/bindle-str-expand | 122 | # macros for tests/bindle-str-expand |
| 112 | tests_bindle_str_expand_DEPENDENCIES = lib/libbindle.a | 123 | tests_bindle_str_expand_DEPENDENCIES = lib/libbindle.a |
| 113 | tests_bindle_str_expand_LDADD = lib/libbindle.a | 124 | tests_bindle_str_expand_LDADD = lib/libbindle.a |
diff --git a/checks/bindle-str-basename.c b/checks/bindle-str-basename.c new file mode 100644 index 0000000..849068e --- /dev/null +++ b/checks/bindle-str-basename.c | |||
| @@ -0,0 +1,238 @@ | |||
| 1 | /* | ||
| 2 | * Bindle Binaries Tools | ||
| 3 | * Copyright (C) 2022 David M. Syzdek <david@syzdek.net>. | ||
| 4 | * All rights reserved. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are | ||
| 8 | * met: | ||
| 9 | * | ||
| 10 | * * Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions and the following disclaimer. | ||
| 12 | * * Redistributions in binary form must reproduce the above copyright | ||
| 13 | * notice, this list of conditions and the following disclaimer in the | ||
| 14 | * documentation and/or other materials provided with the distribution. | ||
| 15 | * * Neither the name of David M. Syzdek nor the | ||
| 16 | * names of its contributors may be used to endorse or promote products | ||
| 17 | * derived from this software without specific prior written permission. | ||
| 18 | * | ||
| 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 20 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
| 21 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M. SYZDEK BE LIABLE FOR | ||
| 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
| 25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
| 26 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 29 | * SUCH DAMAGE. | ||
| 30 | */ | ||
| 31 | #define _CHECKS_BINDLE_STR_BASENAME_C 1 | ||
| 32 | |||
| 33 | |||
| 34 | /////////////// | ||
| 35 | // // | ||
| 36 | // Headers // | ||
| 37 | // // | ||
| 38 | /////////////// | ||
| 39 | #pragma mark - Headers | ||
| 40 | |||
| 41 | #include "bindle-tests.h" | ||
| 42 | |||
| 43 | #include <stdio.h> | ||
| 44 | #include <stdarg.h> | ||
| 45 | #include <stdlib.h> | ||
| 46 | #include <string.h> | ||
| 47 | #include <strings.h> | ||
| 48 | #include <unistd.h> | ||
| 49 | #include <getopt.h> | ||
| 50 | #include <assert.h> | ||
| 51 | |||
| 52 | |||
| 53 | /////////////////// | ||
| 54 | // // | ||
| 55 | // Definitions // | ||
| 56 | // // | ||
| 57 | /////////////////// | ||
| 58 | #pragma mark - Definitions | ||
| 59 | |||
| 60 | #undef PROGRAM_NAME | ||
| 61 | #define PROGRAM_NAME "bindle-str-basename" | ||
| 62 | |||
| 63 | |||
| 64 | ///////////////// | ||
| 65 | // // | ||
| 66 | // Datatypes // | ||
| 67 | // // | ||
| 68 | ///////////////// | ||
| 69 | #pragma mark - Datatypes | ||
| 70 | |||
| 71 | typedef struct my_test_strings | ||
| 72 | { | ||
| 73 | const char * origin; | ||
| 74 | const char * result; | ||
| 75 | } my_test_strings_t; | ||
| 76 | |||
| 77 | |||
| 78 | ///////////////// | ||
| 79 | // // | ||
| 80 | // Variables // | ||
| 81 | // // | ||
| 82 | ///////////////// | ||
| 83 | #pragma mark - Variables | ||
| 84 | |||
| 85 | static my_test_strings_t test_strings[] = | ||
| 86 | { | ||
| 87 | { .origin = "/etc/passwd", .result = "passwd" }, | ||
| 88 | { .origin = "passwd", .result = "passwd" }, | ||
| 89 | { .origin = "/passwd", .result = "passwd" }, | ||
| 90 | { .origin = "/passwd/", .result = "passwd" }, | ||
| 91 | { .origin = "//passwd/", .result = "passwd" }, | ||
| 92 | { .origin = "//passwd//", .result = "passwd" }, | ||
| 93 | { .origin = "passwd/", .result = "passwd" }, | ||
| 94 | { .origin = "passwd//", .result = "passwd" }, | ||
| 95 | { .origin = "/////////", .result = "/" }, | ||
| 96 | { .origin = "//", .result = "/" }, | ||
| 97 | { .origin = "", .result = "." }, | ||
| 98 | { .origin = NULL, .result = NULL } | ||
| 99 | }; | ||
| 100 | |||
| 101 | |||
| 102 | ////////////////// | ||
| 103 | // // | ||
| 104 | // Prototypes // | ||
| 105 | // // | ||
| 106 | ////////////////// | ||
| 107 | #pragma mark - Prototypes | ||
| 108 | |||
| 109 | int | ||
| 110 | main( | ||
| 111 | int argc, | ||
| 112 | char * argv[] ); | ||
| 113 | |||
| 114 | |||
| 115 | ///////////////// | ||
| 116 | // // | ||
| 117 | // Functions // | ||
| 118 | // // | ||
| 119 | ///////////////// | ||
| 120 | #pragma mark - Functions | ||
| 121 | |||
| 122 | int | ||
| 123 | main( | ||
| 124 | int argc, | ||
| 125 | char * argv[] ) | ||
| 126 | { | ||
| 127 | int opt; | ||
| 128 | int c; | ||
| 129 | int opt_index; | ||
| 130 | size_t pos; | ||
| 131 | unsigned opts; | ||
| 132 | char * str; | ||
| 133 | |||
| 134 | // getopt options | ||
| 135 | static char short_opt[] = "dhVvq"; | ||
| 136 | static struct option long_opt[] = | ||
| 137 | { | ||
| 138 | {"debug", no_argument, NULL, 'd' }, | ||
| 139 | {"help", no_argument, NULL, 'h' }, | ||
| 140 | {"quiet", no_argument, NULL, 'q' }, | ||
| 141 | {"silent", no_argument, NULL, 'q' }, | ||
| 142 | {"version", no_argument, NULL, 'V' }, | ||
| 143 | {"verbose", no_argument, NULL, 'v' }, | ||
| 144 | { NULL, 0, NULL, 0 } | ||
| 145 | }; | ||
| 146 | |||
| 147 | bindle_tests_initialize(PROGRAM_NAME); | ||
| 148 | |||
| 149 | opts = 0; | ||
| 150 | |||
| 151 | while((c = getopt_long(argc, argv, short_opt, long_opt, &opt_index)) != -1) | ||
| 152 | { | ||
| 153 | switch(c) | ||
| 154 | { | ||
| 155 | case -1: /* no more arguments */ | ||
| 156 | case 0: /* long options toggles */ | ||
| 157 | break; | ||
| 158 | |||
| 159 | case 'd': | ||
| 160 | opt = BNDL_DEBUG_ANY; | ||
| 161 | bindle_set_option(NULL, BNDL_OPT_DEBUG_LEVEL, &opt); | ||
| 162 | break; | ||
| 163 | |||
| 164 | case 'h': | ||
| 165 | printf("Usage: %s [OPTIONS]\n", PROGRAM_NAME); | ||
| 166 | printf(" %s [OPTIONS] str1 [ str2 [ ... [ strN ] ] ]\n", PROGRAM_NAME); | ||
| 167 | printf("OPTIONS:\n"); | ||
| 168 | printf(" -d, --debug print debug messages\n"); | ||
| 169 | printf(" -h, --help print this help and exit\n"); | ||
| 170 | printf(" -q, --quiet, --silent do not print messages\n"); | ||
| 171 | printf(" -V, --version print version number and exit\n"); | ||
| 172 | printf(" -v, --verbose print verbose messages\n"); | ||
| 173 | printf("\n"); | ||
| 174 | return(0); | ||
| 175 | |||
| 176 | case 'q': | ||
| 177 | opts |= BNDLTEST_OPT_QUIET; | ||
| 178 | opts &= ~BNDLTEST_OPT_VERBOSE; | ||
| 179 | break; | ||
| 180 | |||
| 181 | case 'V': | ||
| 182 | bindle_tests_version(); | ||
| 183 | return(0); | ||
| 184 | |||
| 185 | case 'v': | ||
| 186 | opts |= BNDLTEST_OPT_VERBOSE; | ||
| 187 | opts &= ~BNDLTEST_OPT_QUIET; | ||
| 188 | break; | ||
| 189 | |||
| 190 | case '?': | ||
| 191 | fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); | ||
| 192 | return(1); | ||
| 193 | |||
| 194 | default: | ||
| 195 | fprintf(stderr, "%s: unrecognized option `--%c'\n", PROGRAM_NAME, c); | ||
| 196 | fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME); | ||
| 197 | return(1); | ||
| 198 | }; | ||
| 199 | }; | ||
| 200 | |||
| 201 | // expand custom strings | ||
| 202 | if (optind < argc) | ||
| 203 | { | ||
| 204 | while (optind < argc) | ||
| 205 | { | ||
| 206 | bindle_tests_verbose(opts, "test string: %s", argv[optind]); | ||
| 207 | str = bindle_basename(argv[optind]); | ||
| 208 | if (!(opts & BNDLTEST_OPT_VERBOSE)) | ||
| 209 | bindle_tests_print(opts, "%s", str); | ||
| 210 | bindle_tests_verbose(opts, " ==> %s", str); | ||
| 211 | optind++; | ||
| 212 | if (optind < argc) | ||
| 213 | bindle_tests_verbose(opts, ""); | ||
| 214 | }; | ||
| 215 | return(0); | ||
| 216 | }; | ||
| 217 | |||
| 218 | // expand and verify test strings | ||
| 219 | for(pos = 0; ((test_strings[pos].origin)); pos++) | ||
| 220 | { | ||
| 221 | bindle_tests_verbose(opts, "test string: \"%s\"", test_strings[pos].origin); | ||
| 222 | str = bindle_basename(test_strings[pos].origin); | ||
| 223 | bindle_tests_verbose(opts, " expected ==> \"%s\"", test_strings[pos].result); | ||
| 224 | bindle_tests_verbose(opts, " result ==> \"%s\"", str); | ||
| 225 | if ((strcmp(test_strings[pos].result, str))) | ||
| 226 | { | ||
| 227 | bindle_tests_error(opts, NULL, "basename does not match expected result"); | ||
| 228 | return(1); | ||
| 229 | }; | ||
| 230 | bindle_tests_verbose(opts, ""); | ||
| 231 | }; | ||
| 232 | |||
| 233 | return(0); | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | /* end of source */ | ||
| 238 | |||
diff --git a/include/bindle.h b/include/bindle.h index 0c8a9e9..d4e55df 100644 --- a/include/bindle.h +++ b/include/bindle.h | |||
| @@ -405,6 +405,18 @@ bindle_set_option( | |||
| 405 | #pragma mark string prototypes | 405 | #pragma mark string prototypes |
| 406 | 406 | ||
| 407 | _BINDLE_F char * | 407 | _BINDLE_F char * |
| 408 | bindle_basename( | ||
| 409 | const char * path ); | ||
| 410 | |||
| 411 | |||
| 412 | _BINDLE_F char * | ||
| 413 | bindle_basename_r( | ||
| 414 | const char * path, | ||
| 415 | char * bname, | ||
| 416 | size_t bnamelen ); | ||
| 417 | |||
| 418 | |||
| 419 | _BINDLE_F char * | ||
| 408 | bindle_strdup( | 420 | bindle_strdup( |
| 409 | const char * s1 ); | 421 | const char * s1 ); |
| 410 | 422 | ||
diff --git a/lib/libbindle/lstring.c b/lib/libbindle/lstring.c index d34dbc3..a24d46a 100644 --- a/lib/libbindle/lstring.c +++ b/lib/libbindle/lstring.c | |||
| @@ -79,6 +79,63 @@ | |||
| 79 | #pragma mark - Functions | 79 | #pragma mark - Functions |
| 80 | 80 | ||
| 81 | char * | 81 | char * |
| 82 | bindle_basename( | ||
| 83 | const char * path ) | ||
| 84 | { | ||
| 85 | static char bname[512]; | ||
| 86 | return(bindle_basename_r(path, bname, sizeof(bname))); | ||
| 87 | } | ||
| 88 | |||
| 89 | |||
| 90 | char * | ||
| 91 | bindle_basename_r( | ||
| 92 | const char * path, | ||
| 93 | char * bname, | ||
| 94 | size_t bnamelen ) | ||
| 95 | { | ||
| 96 | size_t pos; | ||
| 97 | size_t slash; | ||
| 98 | size_t len; | ||
| 99 | |||
| 100 | assert(bname != NULL); | ||
| 101 | assert(bnamelen > 2); | ||
| 102 | |||
| 103 | // handle empty strings | ||
| 104 | if ( (!(path)) || (path[0] == '\0') ) | ||
| 105 | { | ||
| 106 | bindle_strlcpy(bname, ".", bnamelen); | ||
| 107 | return(bname); | ||
| 108 | }; | ||
| 109 | |||
| 110 | // skip leading '/' chars | ||
| 111 | while (path[0] == '/') | ||
| 112 | path = &path[1]; | ||
| 113 | if (path[0] == '\0') | ||
| 114 | { | ||
| 115 | bindle_strlcpy(bname, "/", bnamelen); | ||
| 116 | return(bname); | ||
| 117 | }; | ||
| 118 | |||
| 119 | // find start of trailing slashes, if any | ||
| 120 | for(pos = strlen(path) - 1; (path[pos] == '/'); pos--); | ||
| 121 | slash = pos + 1; | ||
| 122 | |||
| 123 | // find last slash before basename | ||
| 124 | for(pos = slash - 1; ((pos > 0) && (path[pos] != '/')); pos--); | ||
| 125 | if (path[pos] == '/') | ||
| 126 | pos++; | ||
| 127 | |||
| 128 | // copy string | ||
| 129 | len = slash - pos + 1; | ||
| 130 | bnamelen = (len > bnamelen) ? bnamelen : len; | ||
| 131 | bindle_strlcpy(bname, &path[pos], bnamelen); | ||
| 132 | |||
| 133 | |||
| 134 | return(bname); | ||
| 135 | } | ||
| 136 | |||
| 137 | |||
| 138 | char * | ||
| 82 | bindle_strdup( | 139 | bindle_strdup( |
| 83 | const char * s1 ) | 140 | const char * s1 ) |
| 84 | { | 141 | { |
