ccnnamelist.c

Go to the documentation of this file.
00001 /**
00002  * @file ccn_splitccnb.c
00003  * Utility to break up a file filled with ccnb-encoded data items into
00004  * one data item per file.
00005  *
00006  * A CCNx command-line utility.
00007  *
00008  * Copyright (C) 2008, 2009 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 <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <sys/mman.h>
00026 #include <limits.h>
00027 #include <stddef.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 
00033 #include <ccn/coding.h>
00034 #include <ccn/uri.h>
00035 
00036 /* returns
00037  *  res >= 0    res characters remaining to be processed from data
00038  *  decoder state will be set appropriately   
00039  */
00040 static size_t
00041 process_data(struct ccn_skeleton_decoder *d, unsigned char *data, size_t n, struct ccn_charbuf *c)
00042 {
00043     size_t s;
00044     
00045 retry:
00046     s = ccn_skeleton_decode(d, data, n);
00047     if (d->state < 0)
00048         return (0);
00049     if (CCN_FINAL_DSTATE(d->state)) {
00050         c->length = 0;
00051         ccn_uri_append(c, data, s, 1);
00052         printf("%s\n", ccn_charbuf_as_string(c));
00053         data += s;
00054         n -= s;
00055         if (n > 0) goto retry;
00056     }
00057     return(n);
00058 }
00059 
00060 static int
00061 process_fd(int fd, struct ccn_charbuf *c)
00062 {
00063     struct ccn_skeleton_decoder skel_decoder = {0};
00064     struct ccn_skeleton_decoder *d = &skel_decoder;
00065     unsigned char *bufp;
00066     unsigned char buf[1024 * 1024];
00067     ssize_t len;
00068     struct stat s;
00069     size_t res = 0;
00070     
00071     if (0 != fstat(fd, &s)) {
00072         perror("fstat");
00073         return(1);
00074     }
00075     
00076     if (S_ISREG(s.st_mode)) {
00077         res = s.st_size;
00078         bufp = (unsigned char *)mmap((void *)NULL, res,
00079                                      PROT_READ, MAP_PRIVATE, fd, 0);
00080         if (bufp != (void *)-1) {
00081             res = process_data(d, bufp, res, c);
00082             if (!CCN_FINAL_DSTATE(d->state)) {
00083                 fprintf(stderr, "%s state %d after %lu bytes\n",
00084                         (d->state < 0) ? "error" : "incomplete",
00085                         (int)d->state,
00086                         (unsigned long)d->index);
00087                 return(1);
00088             }
00089             return(0);
00090         }
00091     }
00092     
00093     /* either not a regular file amenable to mapping, or the map failed */
00094     bufp = &buf[0];
00095     res = 0;
00096     while ((len = read(fd, bufp + res, sizeof(buf) - res)) > 0) {
00097         len += res;
00098         res = process_data(d, bufp, len, c);
00099         if (d->state < 0) {
00100             fprintf(stderr, "error state %d\n", (int)d->state);
00101             return(1);
00102         }
00103         /* move any remaining data back to the start, refresh the buffer,
00104          * reset the decoder state so we can reparse
00105          */
00106         if (res != 0) 
00107             memmove(bufp, bufp + (len - res), res);
00108         memset(d, 0, sizeof(*d));
00109     }
00110     if (!CCN_FINAL_DSTATE(d->state)) {
00111         fprintf(stderr, "%s state %d\n",
00112                 (d->state < 0) ? "error" : "incomplete", d->state);
00113         return(1);
00114     }  
00115     return(0);
00116 }
00117 
00118 
00119 static int
00120 process_file(char *path, struct ccn_charbuf *c)
00121 {
00122     int fd = -1;
00123     int res = 0;
00124     if (strcmp(path, "-") == 0) {
00125         fd = STDIN_FILENO;
00126     } else {
00127         fd = open(path, O_RDONLY);
00128         if (-1 == fd) {
00129             perror(path);
00130             return(1);
00131         }
00132         
00133     }
00134     res = process_fd(fd, c);
00135     close(fd);
00136     return(res);
00137 }
00138 
00139 static void
00140 usage(const char *progname)
00141 {
00142     fprintf(stderr,
00143             "%s [-h] [file1 ... fileN]\n"
00144             "   Produces a list of names from the ccnb encoded"
00145             " objects in the given file(s), or from stdin if no files or \"-\"\n",
00146             progname);
00147     exit(1);
00148 }
00149 
00150 int
00151 main(int argc, char *argv[])
00152 {
00153     int i;
00154     int res = 0;
00155     struct ccn_charbuf *c = ccn_charbuf_create();
00156     int opt;
00157     
00158     while ((opt = getopt(argc, argv, "h")) != -1) {
00159         switch (opt) {
00160             case 'h':
00161             default:
00162                 usage(argv[0]);
00163         }
00164     }
00165     
00166     if (argv[optind] == NULL)
00167         return (process_fd(STDIN_FILENO, c));
00168     
00169     for (i = optind; argv[i] != 0; i++) {
00170         res |= process_file(argv[i], c);
00171     }
00172     return(res);
00173 }
00174 

Generated on Thu Feb 16 00:43:59 2012 for Content-Centric Networking in C by  doxygen 1.5.6