Test applets containing numbers in their name. Thanks to Larry Doolittle.
[oweals/busybox.git] / dpkg_deb.c
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU Library General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include "busybox.h"
24
25 typedef struct ar_headers_s {
26         char *name;
27         size_t size;
28         uid_t uid;
29         gid_t gid;
30         mode_t mode;
31         time_t mtime;
32         off_t offset;
33         struct ar_headers_s *next;
34 } ar_headers_t;
35
36 extern ar_headers_t get_headers(int srcFd);
37 extern int tar_unzip_init(int tarFd);
38 extern int readTarFile(int tarFd, int extractFlag, int listFlag, 
39                 int tostdoutFlag, int verboseFlag, char** extractList,
40                 char** excludeList);
41
42 extern int dpkg_deb_main(int argc, char **argv)
43 {
44         const int dpkg_deb_contents = 1;
45         const int dpkg_deb_control = 2;
46 //      const int dpkg_deb_info = 4;
47         const int dpkg_deb_extract = 8;
48         const int dpkg_deb_verbose_extract = 16;
49         int opt=0;
50         int optflag=0;  
51         int extract_flag = FALSE;
52         int list_flag = FALSE;
53         int verbose_flag = FALSE;
54         int extract_to_stdout = FALSE;
55         char ar_filename[15];
56         int srcFd=0;
57         int status=0;
58         ar_headers_t *ar_headers = NULL;
59         char **extract_list=NULL;
60         char *target_dir=NULL;
61         
62         while ((opt = getopt(argc, argv, "cexX")) != -1) {
63                 switch (opt) {
64                         case 'c':
65                                 optflag |= dpkg_deb_contents;
66                                 break;
67                         case 'e':
68                                 optflag |= dpkg_deb_control;
69                                 break;
70 /*                      case 'I':
71                                 optflag |= dpkg_deb_info;
72                                 break;
73 */
74                         case 'x':
75                                 optflag |= dpkg_deb_extract;
76                                 break;
77                         case 'X':
78                                 optflag |= dpkg_deb_verbose_extract;
79                                 break;
80                         default:
81                                 usage(dpkg_deb_usage);
82                                 return EXIT_FAILURE;
83                 }
84         }
85
86         if (((optind + 1 ) > argc) || (optflag == 0))  {
87                 usage(dpkg_deb_usage);
88                 return(EXIT_FAILURE);
89         }
90         
91         if (optflag & dpkg_deb_contents) {
92                 list_flag = TRUE;
93                 verbose_flag = TRUE;
94                 strcpy(ar_filename, "data.tar.gz");
95         }
96         else if (optflag & dpkg_deb_control) {
97                 extract_flag = TRUE;
98                 strcpy(ar_filename, "control.tar.gz");          
99                 if ( (optind + 1) == argc ) {
100                         target_dir = (char *) xmalloc(7);
101                         strcpy(target_dir, "DEBIAN");
102                }
103                 else {
104                         target_dir = (char *) xmalloc(strlen(argv[optind+1]));
105
106                         strcpy(target_dir, argv[optind+1]);
107                 }
108         }
109 /*      else if (optflag & dpkg_deb_info) {
110                 extract_flag = TRUE;
111                 extract_to_stdout = TRUE;
112                 strcpy(ar_filename, "control.tar.gz");
113                 extract_list = argv+optind+1;
114                 printf("list one is [%s]\n",extract_list[0]);
115         }
116 */
117         else if (optflag & dpkg_deb_extract) {
118                 extract_flag = TRUE;
119                 strcpy(ar_filename, "data.tar.gz");
120                 if ( (optind + 2) > argc ) {
121                         error_msg_and_die("No directory specified\n");
122                 }
123                 target_dir = (char *) xmalloc(strlen(argv[optind+1]));                  
124                 strcpy(target_dir, argv[optind+1]);
125         }       
126         else if (optflag & dpkg_deb_verbose_extract) {
127                 extract_flag = TRUE;
128                 list_flag = TRUE;
129                 strcpy(ar_filename, "data.tar.gz");
130                 if ( (optind + 2) > argc ) {
131                         error_msg_and_die("No directory specified\n");
132                 }
133                 target_dir = (char *) xmalloc(strlen(argv[optind+1]));                  
134                 strcpy(target_dir, argv[optind+1]);
135         }
136                 
137         ar_headers = (ar_headers_t *) xmalloc(sizeof(ar_headers_t));    
138         srcFd = open(argv[optind], O_RDONLY);
139         
140         *ar_headers = get_headers(srcFd);
141         if (ar_headers->next==NULL)
142                 error_msg_and_die("Couldnt find %s in %s\n",ar_filename, argv[optind]);
143
144         while (ar_headers->next != NULL) {
145                 if (strcmp(ar_headers->name, ar_filename)==0)
146                         break;
147                 ar_headers = ar_headers->next;
148         }
149
150         lseek(srcFd, ar_headers->offset, SEEK_SET);
151         srcFd = tar_unzip_init(srcFd);
152         if ( target_dir != NULL) { 
153                 if (is_directory(target_dir, TRUE, NULL)==FALSE) {
154                         mkdir(target_dir, 0755);
155                 }
156                 if (chdir(target_dir)==-1) {
157                         error_msg_and_die("Cannot change to dir %s\n",argv[optind+1]);
158                 }
159         }
160         status = readTarFile(srcFd, extract_flag, list_flag, extract_to_stdout, verbose_flag, NULL, extract_list);
161         close (srcFd);
162         return(EXIT_SUCCESS);
163 }