00001
00002
00003
00004
00005
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <ctype.h>
00010 #include <assert.h>
00011 #include "ncio.h"
00012 #ifndef ENOERR
00013 #define ENOERR 0
00014 #endif
00015
00016
00017 static void
00018 usage(const char *av0)
00019 {
00020 (void)fprintf(stderr,
00021 "Usage: %s [options] fname\t\nOptions:\n", av0);
00022 (void)fprintf(stderr,
00023 "\t-v Verbose\n") ;
00024 (void)fprintf(stderr,
00025 "\t-w Open Read/Write, default is read only\n") ;
00026 (void)fprintf(stderr,
00027 "\t-c Create, clobber existing\n") ;
00028 (void)fprintf(stderr,
00029 "\t-n Create, error if it already exists\n") ;
00030 (void)fprintf(stderr,
00031 "\t-L Use locking if available\n") ;
00032 (void)fprintf(stderr,
00033 "\t-S Share updates (turn off caching)\n") ;
00034 (void)fprintf(stderr,
00035 "\t-U Delete (unlink) on close\n") ;
00036 (void)fprintf(stderr,
00037 "\t-o igeto Initial get offset\n") ;
00038 (void)fprintf(stderr,
00039 "\t-i igetsz Initial get size\n") ;
00040 (void)fprintf(stderr,
00041 "\t-I initialsz Initial file size for create\n") ;
00042 (void)fprintf(stderr,
00043 "\t-s sizehint Buffer size\n") ;
00044 exit(EXIT_FAILURE);
00045 }
00046
00047
00048 static long
00049 argscale(const char *arg, const char *tag)
00050 {
00051 long value = 0;
00052
00053 const char *cp = arg + strlen(arg) -1;
00054 value = atol(arg);
00055 if(isalpha(*cp))
00056 {
00057 switch(*cp) {
00058 case 'k':
00059 case 'K':
00060 value *= 1024;
00061 break;
00062 case 'm':
00063 case 'M':
00064 value *= (1024*1024);
00065 break;
00066 default:
00067 value = 0;
00068 break;
00069 }
00070 }
00071 if(value == 0)
00072 {
00073 fprintf(stderr,
00074 "Illegal %s \"%s\", ignored\n", tag, arg);
00075 }
00076 return value;
00077 }
00078
00079
00080 static void
00081 modify_ex(off_t offset, size_t extent, void *vp)
00082 {
00083 unsigned char *obuf = vp;
00084 const unsigned char *const end = &obuf[extent];
00085 unsigned char *cp = obuf;
00086
00087 if(cp >= end) return;
00088 *cp++ = (unsigned char)( offset >> 24);
00089 if(cp >= end) return;
00090 *cp++ = (unsigned char)((offset & 0x00ff0000) >> 16);
00091 if(cp >= end) return;
00092 *cp++ = (unsigned char)((offset & 0x0000ff00) >> 8);
00093 if(cp >= end) return;
00094 *cp++ = (unsigned char)( offset & 0x000000ff);
00095 if(cp >= end) return;
00096 *cp++ = (unsigned char)( extent >> 24);
00097 if(cp >= end) return;
00098 *cp++ = (unsigned char)((extent & 0x00ff0000) >> 16);
00099 if(cp >= end) return;
00100 *cp++ = (unsigned char)((extent & 0x0000ff00) >> 8);
00101 if(cp >= end) return;
00102 *cp++ = (unsigned char)( extent & 0x000000ff);
00103
00104 while(cp < end)
00105 {
00106 *cp++ = (unsigned char) (cp - obuf);
00107 }
00108 }
00109
00110
00111 typedef struct riu {
00112 struct riu *next;
00113 struct riu *prev;
00114 off_t offset;
00115 size_t extent;
00116 void *vp;
00117 } riu;
00118
00119 static void
00120 free_riu(riu *riup)
00121 {
00122 if(riup == NULL)
00123 return;
00124 free(riup);
00125 }
00126
00127 static riu *
00128 new_riu(off_t offset, size_t extent, void *vp)
00129 {
00130 riu *riup = (riu *)malloc(sizeof(riu));
00131 if(riup == NULL)
00132 {
00133 fprintf(stderr,
00134 "new_riu: malloc failed\n");
00135 exit(EXIT_FAILURE);
00136 }
00137 riup->next = NULL;
00138 riup->prev = NULL;
00139 riup->offset = offset;
00140 riup->extent = extent;
00141 riup->vp = vp;
00142 return riup;
00143 }
00144
00145 static riu *stack = NULL;
00146
00147 static void
00148 riu_push(off_t offset, size_t extent, void *vp)
00149 {
00150 riu *riup = new_riu(offset, extent, vp);
00151
00152 riup->next = stack;
00153 if(stack != NULL)
00154 stack->prev = riup;
00155 stack = riup;
00156 }
00157
00158 static int
00159 riu_pop(off_t offset, int modify)
00160 {
00161 riu *riup = stack;
00162 while(riup != NULL)
00163 {
00164 if(riup->offset == offset)
00165 {
00166 if(modify)
00167 {
00168 modify_ex(riup->offset, riup->extent, riup->vp);
00169 }
00170 if(riup->next != NULL)
00171 {
00172 riup->next->prev = riup->prev;
00173 }
00174 if(riup == stack)
00175 {
00176 stack = riup->next;
00177 }
00178 else
00179 {
00180 assert(riup->prev != NULL);
00181 riup->prev->next = riup->next;
00182 }
00183 free_riu(riup);
00184 return 1;
00185 }
00186 riup = riup->next;
00187 }
00188
00189 return 0;
00190 }
00191
00192 main(int ac, char *av[])
00193 {
00194 char *path = "";
00195 ncio *nciop;
00196 char linebuf[128];
00197 off_t offset;
00198 size_t extent;
00199 void *vp;
00200 int status = ENOERR;
00201 int verbose = 0;
00202 int flags = 0;
00203 int create = 0;
00204 off_t igeto = 0;
00205 size_t igetsz = 0;
00206 size_t initialsz = 0;
00207 int doUnlink = 0;
00208 size_t sizehint = NC_SIZEHINT_DEFAULT;
00209
00210 {
00211 extern int optind;
00212 extern int opterr;
00213 extern char *optarg;
00214 int ch;
00215
00216 opterr = 1;
00217
00218 while ((ch = getopt(ac, av, "vwcnLSUo:i:I:s:")) != EOF)
00219 switch (ch) {
00220 case 'v':
00221 verbose = 1;
00222 break;
00223 case 'w':
00224 flags |= NC_WRITE;
00225 break;
00226 case 'c':
00227 create = 1;
00228 break;
00229 case 'n':
00230 create = 1;
00231 flags |= NC_NOCLOBBER;
00232 break;
00233 case 'L':
00234 flags |= NC_LOCK;
00235 break;
00236 case 'S':
00237 flags |= NC_SHARE;
00238 break;
00239 case 'U':
00240 doUnlink = 1;
00241 break;
00242 case 'o':
00243 igeto = argscale(optarg, "igeto");
00244 break;
00245 case 'i':
00246 igetsz = argscale(optarg, "igetsz");
00247 break;
00248 case 'I':
00249 initialsz = argscale(optarg, "initialsz");
00250 break;
00251 case 's':
00252 sizehint = argscale(optarg, "sizehint");
00253 break;
00254 case '?':
00255 usage(av[0]);
00256 break;
00257 }
00258
00259
00260 if(ac - optind <= 0)
00261 usage(av[0]) ;
00262 path = av[optind];
00263
00264
00265 }
00266
00267 if(!create)
00268 {
00269 status = ncio_open(path, flags,
00270 igeto, igetsz, &sizehint,
00271 &nciop, &vp);
00272 if(status != ENOERR)
00273 {
00274 fprintf(stderr, "ncio_open: %s: %s\n",
00275 path, strerror(status));
00276 return(EXIT_FAILURE);
00277 }
00278 } else {
00279 status = ncio_create(path, flags, initialsz,
00280 igeto, igetsz, &sizehint,
00281 &nciop, &vp);
00282 if(status != ENOERR)
00283 {
00284 fprintf(stderr, "ncio_create: %s: %s\n",
00285 path, strerror(status));
00286 return(EXIT_FAILURE);
00287 }
00288 }
00289
00290 while(fgets(linebuf, sizeof(linebuf), stdin) != NULL)
00291 {
00292 offset = 0;
00293 extent = 0;
00294
00295 if(*linebuf == '#')
00296 continue;
00297 if(sscanf(linebuf, "rel 0x%lx", &offset) == 1
00298 || sscanf(linebuf, "rel %ld", &offset) == 1)
00299 {
00300 if(verbose)
00301 printf("- rel %8ld\n", offset);
00302 if(!riu_pop(offset, 0))
00303 continue;
00304 status = nciop->rel(nciop, offset, 0);
00305 if(status)
00306 {
00307 fprintf(stderr, "- rel error: %s\n",
00308 strerror(status));
00309 continue;
00310 }
00311 }
00312 else if(sscanf(linebuf, "relm 0x%lx", &offset) == 1
00313 || sscanf(linebuf, "relm %ld", &offset) == 1)
00314 {
00315 if(verbose)
00316 printf("- relm %8ld\n", offset);
00317 if(!riu_pop(offset, 1))
00318 continue;
00319 status = nciop->rel(nciop, offset, RGN_MODIFIED);
00320 if(status)
00321 {
00322 fprintf(stderr, "- relm %8ld error: %s\n",
00323 offset, strerror(status));
00324 continue;
00325 }
00326 }
00327 else if(sscanf(linebuf, "get 0x%lx %ld", &offset, &extent) == 2
00328 || sscanf(linebuf, "get %ld %ld", &offset, &extent) == 2)
00329 {
00330 if(verbose)
00331 printf("- get %10ld %8ld\n", offset, extent);
00332 status = nciop->get(nciop, offset, extent, 0, &vp);
00333 if(status)
00334 {
00335 fprintf(stderr, "- get error: %s\n",
00336 strerror(status));
00337 continue;
00338 }
00339 riu_push(offset, extent, vp);
00340 }
00341 else if(sscanf(linebuf, "getw 0x%lx %ld", &offset, &extent) == 2
00342 || sscanf(linebuf, "getw %ld %ld", &offset, &extent) == 2)
00343 {
00344 if(verbose)
00345 printf("- getw %10ld %8ld\n", offset, extent);
00346 status = nciop->get(nciop, offset, extent, RGN_WRITE, &vp);
00347 if(status)
00348 {
00349 fprintf(stderr, "- getw error: %s\n",
00350 strerror(status));
00351 continue;
00352 }
00353 riu_push(offset, extent, vp);
00354 }
00355 else if(strchr(linebuf, 'q') != NULL)
00356 break;
00357 else
00358 printf("???\n");
00359 }
00360
00361 status = ncio_close(nciop, doUnlink);
00362 if(status != ENOERR)
00363 {
00364 fprintf(stderr, "ncio_close(%s): %s: %s\n",
00365 doUnlink ? "doUnlink" : "",
00366 path, strerror(status));
00367 return(EXIT_FAILURE);
00368 }
00369
00370 return(EXIT_SUCCESS);
00371 }