ccnbx.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnbx.c
00003  *
00004  * Utility to extract a field from ccn binary encoded data.
00005  *
00006  * A CCNx command-line utility.
00007  *
00008  * Copyright (C) 2009-2011 Palo Alto Research Center, Inc.
00009  *
00010  * This work is free software; you can redistribute it and/or modify it under
00011  * the terms of the GNU General Public License version 2 as published by the
00012  * Free Software Foundation.
00013  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00016  * for more details. You should have received a copy of the GNU General Public
00017  * License along with this program; if not, write to the
00018  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
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; /* full speed to the end */                   
00129                 else
00130                     start = end = d->index; /* in case of no data */
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                 /** @bug This would be confused by attributes */
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 
Generated on Fri May 13 16:27:01 2011 for Content-Centric Networking in C by  doxygen 1.6.3