source: abuse/trunk/src/tool/abuse-tool.cpp @ 543

Last change on this file since 543 was 543, checked in by Sam Hocevar, 12 years ago

tool: implement `get' in abuse-tool.

  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1//
2// Abuse Tool - package manager for Abuse format
3//
4// Copyright: (c) 2011 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#include "config.h"
12
13#include <cstring>
14#include <cstdio>
15
16#include "common.h"
17#include "specs.h"
18#include "image.h"
19
20static void Usage();
21
22enum
23{
24    CMD_INVALID,
25    CMD_LIST,
26    CMD_GET,
27    CMD_MOVE,
28    CMD_DEL,
29    CMD_PUT,
30    CMD_RENAME,
31    CMD_GETPCX,
32    CMD_PUTPCX,
33};
34
35int main(int argc, char *argv[])
36{
37    if (argc < 3)
38    {
39        Usage();
40        return EXIT_FAILURE;
41    }
42
43    int cmd = !strcmp(argv[2], "list") ? CMD_LIST
44            : !strcmp(argv[2], "get") ? CMD_GET
45            : !strcmp(argv[2], "del") ? CMD_DEL
46            : !strcmp(argv[2], "put") ? CMD_PUT
47            : !strcmp(argv[2], "move") ? CMD_MOVE
48            : !strcmp(argv[2], "rename") ? CMD_RENAME
49            : !strcmp(argv[2], "getpcx") ? CMD_GETPCX
50            : !strcmp(argv[2], "putpcx") ? CMD_PUTPCX
51            : CMD_INVALID;
52
53    if (cmd == CMD_INVALID)
54    {
55        fprintf(stderr, "abuse-tool: unknown command `%s'\n", argv[2]);
56        return EXIT_FAILURE;
57    }
58
59    /* Check argument count and file access mode */
60    char const *mode = "rwb";
61    int minargc = 3;
62
63    switch (cmd)
64    {
65    case CMD_LIST:
66        mode = "rb"; // Read-only access
67        break;
68    case CMD_GET:
69        minargc = 4;
70        mode = "rb"; // Read-only access
71        break;
72    case CMD_PUT:
73        minargc = 5;
74        break;
75    case CMD_MOVE:
76        minargc = 5;
77        break;
78    case CMD_RENAME:
79        minargc = 5;
80        break;
81    case CMD_DEL:
82        minargc = 4;
83        break;
84    case CMD_GETPCX:
85        minargc = 4;
86        mode = "rb"; // Read-only access
87        break;
88    case CMD_PUTPCX:
89        minargc = 5;
90        break;
91    }
92
93    if (argc < minargc)
94    {
95        fprintf(stderr, "abuse-tool: too few arguments to command `%s'\n",
96                         argv[2]);
97        return EXIT_FAILURE;
98    }
99
100    /* Open the SPEC file */
101    char const *file = argv[1];
102
103    jFILE fp(file, mode);
104    if (fp.open_failure())
105    {
106        fprintf(stderr, "ERROR - could not open %s\n", file);
107        return EXIT_FAILURE;
108    }
109
110    spec_directory dir(&fp);
111
112    /* Now really execute commands */
113    if (cmd == CMD_LIST)
114    {
115        printf("   id  type     size  name & information\n");
116        printf(" ----  ----  -------  ----------------------------\n");
117
118        for (int i = 0; i < dir.total; i++)
119        {
120            spec_entry *se = dir.entries[i];
121
122            /* Print basic information */
123            printf("% 5i   % 3i % 8i  %s",
124                   i, se->type, (int)se->size, se->name);
125
126            /* Is there anything special to say? */
127            switch (se->type)
128            {
129            case SPEC_IMAGE:
130            case SPEC_FORETILE:
131            case SPEC_BACKTILE:
132            case SPEC_CHARACTER:
133            case SPEC_CHARACTER2:
134              {
135                image *im = new image(&fp, se);
136                printf(" (%i x %i pixels)", im->Size().x, im->Size().y);
137                delete im;
138                break;
139              }
140            case SPEC_PALETTE:
141              {
142                palette *pal = new palette(se, &fp);
143                printf(" (%i colors)", pal->pal_size());
144                delete pal;
145                break;
146              }
147            }
148
149            /* Finish line */
150            putchar('\n');
151        }
152
153        return EXIT_SUCCESS;
154    }
155
156    if (cmd == CMD_GET)
157    {
158        int id = atoi(argv[3]);
159
160        if (id < 0 || id >= dir.total)
161        {
162            fprintf(stderr, "abuse-tool: id %i not found in %s\n", id, file);
163            return EXIT_FAILURE;
164        }
165
166        spec_entry *se = dir.entries[id];
167        fp.seek(se->offset, SEEK_SET);
168
169        for (size_t todo = se->size; todo > 0; )
170        {
171            uint8_t buf[1024];
172            int step = Min(todo, 1024);
173            fp.read(buf, step);
174            fwrite(buf, step, 1, stdout);
175            todo -= step;
176        }
177    }
178
179    return EXIT_SUCCESS;
180}
181
182static void Usage()
183{
184    fprintf(stderr, "%s",
185            "Usage: abuse-tool <spec_file> <command> [args...]\n"
186            "List of available commands:\n"
187            "  list          list the contents of a SPEC file\n"
188            "  get <id>      dump entry <id> to stdout\n");
189}
190
Note: See TracBrowser for help on using the repository browser.