ccnbx.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <fcntl.h>
00023 #include <stddef.h>
00024 #include <stdio.h>
00025 #include <stdint.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029
00030 #include <ccn/charbuf.h>
00031 #include <ccn/coding.h>
00032 #include <ccn/ccn.h>
00033
00034 #define CCNBX_OPT_UNADORNED 1
00035 #define CCNBX_OPT_VERBOSE 2
00036
00037 static void
00038 usage(const char *progname)
00039 {
00040 fprintf(stderr,
00041 "usage: %s [-h] [-d] [-v] file selector\n"
00042 " Utility to extract a field from ccn binary encoded data.\n"
00043 " selector is an element name\n"
00044 " -h print this message and exit\n"
00045 " -d data only - no element tags\n"
00046 " -v verbose\n"
00047 " use - for file to specify stdin\n"
00048 " result is on stdout\n",
00049 progname);
00050 exit(1);
00051 }
00052
00053
00054 static int
00055 dtag_lookup(const char *key)
00056 {
00057 const struct ccn_dict_entry *dict = ccn_dtag_dict.dict;
00058 int n = ccn_dtag_dict.count;
00059 int i;
00060 for (i = 0; i < n; i++)
00061 if (0 == strcmp(key, dict[i].name))
00062 return (dict[i].index);
00063 return (-1);
00064 }
00065
00066 static int
00067 ccnbx(const char *path, const char *selector, int options) {
00068 struct ccn_skeleton_decoder skel_decoder = {0};
00069 struct ccn_skeleton_decoder *d = &skel_decoder;
00070 struct ccn_charbuf *c = NULL;
00071 int fd = 0;
00072 int status = 1;
00073 int dtag;
00074 ssize_t res;
00075 ssize_t s;
00076 size_t offset = 0;
00077 size_t start = 0;
00078 size_t end = ~0U;
00079 int verbose = (options & CCNBX_OPT_VERBOSE) != 0;
00080
00081 if (0 != strcmp(path, "-")) {
00082 fd = open(path, O_RDONLY);
00083 if (-1 == fd) {
00084 perror(path);
00085 return(1);
00086 }
00087 }
00088 dtag = dtag_lookup(selector);
00089 if (dtag == -1) {
00090 fprintf(stderr, "%s is not a DTAG\n", selector);
00091 goto Finish;
00092 }
00093 c = ccn_charbuf_create();
00094 d->state |= CCN_DSTATE_PAUSE;
00095 do {
00096 ccn_charbuf_reserve(c, 512);
00097 res = read(fd, c->buf + c->length, c->limit - c->length);
00098 if (res < 0) {
00099 perror(path);
00100 goto Finish;
00101 }
00102 if (res == 0) {
00103 fprintf(stderr, "premature end of file on %s\n", path);
00104 goto Finish;
00105 }
00106 c->length += res;
00107 while (d->index < c->length) {
00108 s = ccn_skeleton_decode(d, c->buf + d->index, c->length - d->index);
00109 offset += s;
00110 if (verbose) fprintf(stderr, "%d, ", (int)s);
00111 if (d->state < 0) {
00112 fprintf(stderr, "error state %d after %d chars from %s\n",
00113 (int)d->state, (int)(d->index), path);
00114 goto Finish;
00115 }
00116 if (s == 0 || CCN_FINAL_DSTATE(d->state))
00117 break;
00118 if (CCN_GET_TT_FROM_DSTATE(d->state) == CCN_DTAG &&
00119 d->numval == dtag) {
00120 if (verbose)
00121 fprintf(stderr, "(%s starts at %d, level is %d) ",
00122 selector,
00123 (int)d->token_index,
00124 (int)d->nest);
00125 start = d->token_index;
00126 d->nest = 1;
00127 if ((options & CCNBX_OPT_UNADORNED) == 0)
00128 d->state &= ~CCN_DSTATE_PAUSE;
00129 else
00130 start = end = d->index;
00131 status = 0;
00132 }
00133 else if (status == 0 && d->nest == 1 &&
00134 (CCN_GET_TT_FROM_DSTATE(d->state) == CCN_UDATA ||
00135 CCN_GET_TT_FROM_DSTATE(d->state) == CCN_BLOB)) {
00136
00137 start = d->index;
00138 end = d->index + d->numval;
00139 d->state &= ~CCN_DSTATE_PAUSE;
00140 }
00141 }
00142 } while (!CCN_FINAL_DSTATE(d->state));
00143 if (verbose) fprintf(stderr, "complete element after %lu chars from %s\n",
00144 (unsigned long)offset, path);
00145 if (offset < end)
00146 end = offset;
00147 if (status == 0)
00148 res = write(1, c->buf + start, end - start);
00149 Finish:
00150 ccn_charbuf_destroy(&c);
00151 close(fd);
00152 return(status);
00153 }
00154
00155 int
00156 main(int argc, char **argv)
00157 {
00158 int opt;
00159 int status = 0;
00160 int options = 0;
00161
00162 while ((opt = getopt(argc, argv, "dhv")) != -1) {
00163 switch (opt) {
00164 case 'd':
00165 options |= CCNBX_OPT_UNADORNED;
00166 break;
00167 case 'v':
00168 options |= CCNBX_OPT_VERBOSE;
00169 break;
00170 case 'h':
00171 default:
00172 usage(argv[0]);
00173 break;
00174 }
00175 }
00176 if (argv[optind] == NULL || argv[optind + 1] == NULL) {
00177 fprintf(stderr, "Too few arguments\n");
00178 usage(argv[0]);
00179 }
00180 if (argv[optind + 2] != NULL) {
00181 fprintf(stderr, "Too many arguments\n");
00182 usage(argv[0]);
00183 }
00184 status = ccnbx(argv[optind], argv[optind + 1], options);
00185 return(status);
00186 }
00187