Add libmar to build update tools to the repo.
[working/Evergreen.git] / Open-ILS / xul / staff_client / external / libmar / tool / mar.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /*
4  * This file is part of Evergreen.
5  *
6  * Evergreen is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published
8  * by the Free Software Foundation, either version 2 of the License,
9  * or (at your option) any later version.
10  *
11  * Evergreen is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Evergreen.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * This Source Code Form is derived from code that was originally
20  * subject to the terms of the Mozilla Public License, v. 2.0 and
21  * included in Evergreen.  You may, therefore, use this Source Code
22  * Form under the terms of the Mozilla Public License 2.0.  This
23  * licensing option does not affect the larger Evergreen project, only
24  * the Source Code Forms bearing this exception are affected.  If a
25  * copy of the MPL was not distributed with this file, You can obtain
26  * one at http://mozilla.org/MPL/2.0/.
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <config.h>
33 #include "mar.h"
34 #include "mar_cmdline.h"
35
36 #ifdef XP_WIN
37 #include <windows.h>
38 #include <direct.h>
39 #define chdir _chdir
40 #else
41 #include <unistd.h>
42 #endif
43
44 static void print_usage() {
45   printf("usage:\n");
46   printf("Create a MAR file:\n");
47   printf("  mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
48          "{-c|-x|-t|-T} archive.mar [files...]\n");
49   printf("Print information on a MAR file:\n");
50   printf("  mar [-H MARChannelID] [-V ProductVersion] [-C workingDir] "
51          "-i unsigned_archive_to_refresh.mar\n");
52   printf("This program does not handle unicode file paths properly\n");
53 }
54
55 static int mar_test_callback(MarFile *mar, 
56                              const MarItem *item, 
57                              void *unused) {
58   printf("%u\t0%o\t%s\n", item->length, item->flags, item->name);
59   return 0;
60 }
61
62 static int mar_test(const char *path) {
63   MarFile *mar;
64
65   mar = mar_open(path);
66   if (!mar)
67     return -1;
68
69   printf("SIZE\tMODE\tNAME\n");
70   mar_enum_items(mar, mar_test_callback, NULL);
71
72   mar_close(mar);
73   return 0;
74 }
75
76 int main(int argc, char **argv) {
77   char *MARChannelID = MAR_CHANNEL_ID;
78   char *productVersion = MOZ_APP_VERSION;
79   uint32_t i, k;
80   int rv = -1;
81
82   if (argc < 3) {
83     print_usage();
84     return -1;
85   }
86
87   while (argc > 0) {
88     if (argv[1][0] == '-' && (argv[1][1] == 'c' || 
89         argv[1][1] == 't' || argv[1][1] == 'x' || 
90         argv[1][1] == 'i' || argv[1][1] == 'T')) {
91       break;
92     /* -C workingdirectory */
93     } else if (argv[1][0] == '-' && argv[1][1] == 'C') {
94       chdir(argv[2]);
95       argv += 2;
96       argc -= 2;
97     /* MAR channel ID */
98     } else if (argv[1][0] == '-' && argv[1][1] == 'H') {
99       MARChannelID = argv[2];
100       argv += 2;
101       argc -= 2;
102     /* Product Version */
103     } else if (argv[1][0] == '-' && argv[1][1] == 'V') {
104       productVersion = argv[2];
105       argv += 2;
106       argc -= 2;
107     }
108     else {
109       print_usage();
110       return -1;
111     }
112   }
113
114   if (argv[1][0] != '-') {
115     print_usage();
116     return -1;
117   }
118
119   switch (argv[1][1]) {
120   case 'c': {
121     struct ProductInformationBlock infoBlock;
122     infoBlock.MARChannelID = MARChannelID;
123     infoBlock.productVersion = productVersion;
124     return mar_create(argv[2], argc - 3, argv + 3, &infoBlock);
125   }
126   case 'i': {
127     struct ProductInformationBlock infoBlock;
128     infoBlock.MARChannelID = MARChannelID;
129     infoBlock.productVersion = productVersion;
130     return refresh_product_info_block(argv[2], &infoBlock);
131   }
132   case 'T': {
133     struct ProductInformationBlock infoBlock;
134     uint32_t numSignatures, numAdditionalBlocks;
135     int hasSignatureBlock, hasAdditionalBlock;
136     if (!get_mar_file_info(argv[2], 
137                            &hasSignatureBlock,
138                            &numSignatures,
139                            &hasAdditionalBlock, 
140                            NULL, &numAdditionalBlocks)) {
141       if (hasSignatureBlock) {
142         printf("Signature block found with %d signature%s\n", 
143                numSignatures, 
144                numSignatures != 1 ? "s" : "");
145       }
146       if (hasAdditionalBlock) {
147         printf("%d additional block%s found:\n", 
148                numAdditionalBlocks,
149                numAdditionalBlocks != 1 ? "s" : "");
150       }
151
152       rv = read_product_info_block(argv[2], &infoBlock);
153       if (!rv) {
154         printf("  - Product Information Block:\n");
155         printf("    - MAR channel name: %s\n"
156                "    - Product version: %s\n",
157                infoBlock.MARChannelID,
158                infoBlock.productVersion);
159         free((void *)infoBlock.MARChannelID);
160         free((void *)infoBlock.productVersion);
161       }
162      }
163     printf("\n");
164     /* The fall through from 'T' to 't' is intentional */
165   }
166   case 't':
167     return mar_test(argv[2]);
168
169   /* Extract a MAR file */
170   case 'x':
171     return mar_extract(argv[2]);
172
173   default:
174     print_usage();
175     return -1;
176   }
177
178   return 0;
179 }