9207999ade5ea653292b570cf2620288c5285a3b
[debian/gzip] / amiga / tailor.c
1 /* tailor.c -- target dependent functions
2  * Copyright (C) 1993 Carsten Steger (carsten.steger@informatik.tu-muenchen.de)
3  * This is free software; you can redistribute it and/or modify it under the
4  * terms of the GNU General Public License, see the file COPYING.
5  */
6
7 /*
8  * This file contains Amiga specific functions for gzip.
9  */
10
11 #include <config.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <error.h>
16 #include <time.h>
17 #include <utime.h>
18 #include <exec/types.h>
19 #include <dos/dos.h>
20 #include <dos/dosextens.h>
21 #include <dos/dosasl.h>
22 #include <proto/dos.h>
23
24 #define MAXPATH 1024
25 #define MAXARGS 512
26
27 extern struct DosLibrary *DOSBase;
28
29 extern void *xmalloc(unsigned int size);
30
31 static char *expand_next_file (char *pattern);
32 static int in_prev_args (char *arg, char **argv, int argc);
33 extern void _expand_args (int *oargc, char ***oargv);
34
35
36 static char *expand_next_file (pattern)
37      char *pattern;
38 {
39   long err;
40   char *pathname;
41   static struct AnchorPath *an = NULL;
42
43   pathname = NULL;
44   if (pattern == NULL)
45     err = -1;
46   else
47     do
48       {
49         if (an == NULL)
50           {
51             an = xmalloc (sizeof (struct AnchorPath) + MAXPATH);
52             memset (an, 0, sizeof (struct AnchorPath) + MAXPATH);
53             an->ap_BreakBits = SIGBREAKF_CTRL_C;
54             an->ap_Strlen = MAXPATH;
55             an->ap_Flags = APF_DOWILD;
56             err = MatchFirst (pattern, an);
57           }
58         else
59           err = MatchNext (an);
60
61         pathname = an->ap_Buf;
62       } while (err == 0 && pathname == NULL);
63
64   if (err)
65     {
66       MatchEnd (an);
67       free (an);
68       an = NULL;
69       return NULL;
70     }
71   else
72     return pathname;
73 }
74
75
76 static int in_prev_args (arg, argv, argc)
77      char *arg, **argv;
78      int argc;
79 {
80   int i, is_in_args;
81
82   is_in_args = 0;
83   for (i = 1; i < argc - 1; i++)
84     if (stricmp (arg, argv[i]) == 0)
85       is_in_args = 1;
86   return is_in_args;
87 }
88
89
90 void _expand_args (oargc, oargv)
91      int *oargc;
92      char ***oargv;
93 {
94   int i;
95   char *str, **argv;
96   static char buf[MAXPATH];
97   int argc, no_match_at_all, num_matches, contains_wildcards;
98
99   /* With Kickstart 1.3 wildcards can't be expanded. */
100   if (DOSBase->dl_lib.lib_Version < 37) return;
101
102   no_match_at_all = 1;
103   contains_wildcards = 0;
104   argc = 0;
105   argv = xmalloc (MAXARGS * sizeof (char *));
106
107   argv[argc++] = (*oargv)[0];
108   for (i = 1; i < *oargc; i++)
109     {
110       if (ParsePattern ((*oargv)[i], buf, MAXPATH))
111         {
112           contains_wildcards = 1;
113           num_matches = 0;
114           while (str = expand_next_file ((*oargv)[i]))
115             if (argc >= MAXARGS)
116               {
117                 expand_next_file (NULL);
118                 fprintf (stderr,"Too many files.\n");
119                 exit (EXIT_FAILURE);
120               }
121             else
122               {
123                 /* Avoid duplicate entries */
124                 if (!in_prev_args (str, argv, argc))
125                   {
126                     argv[argc++] = strdup (str);
127                     num_matches++;
128                   }
129               }
130           if (num_matches != 0)
131             no_match_at_all = 0;
132         }
133       else
134         if (argc >= MAXARGS)
135           {
136             fprintf (stderr,"Too many files.\n");
137             exit (EXIT_FAILURE);
138           }
139         else
140           {
141             if (!in_prev_args ((*oargv)[i], argv, argc))
142               argv[argc++] = (*oargv)[i];
143           }
144     }
145   *oargc = argc;
146   *oargv = argv;
147   if (no_match_at_all && contains_wildcards) {
148     fprintf (stderr,"No match.\n");
149     exit (EXIT_FAILURE);
150   }
151 }
152
153
154 int utime (path, times)
155      char *path;
156      struct utimbuf *times;
157 {
158   struct DateStamp date;
159   LONG error;
160   time_t modtime;
161
162   /* With Kickstart 1.3 setting the filedate could be done, I guess.
163    * Maybe someone else will implement and test the code for this
164    * case (I don't have Kickstart 1.3). */
165   if (DOSBase->dl_lib.lib_Version < 37) return 0;
166
167   /* Amiga dates are counted from 1. Jan 1978 as opposed to 1. Jan 1970
168    * on Unix. Therefore we have to subtract 2922 days (8*365+2). We also
169    * have to subtract the value of __timezone since SAS/C uses "CST+06"
170    * as the default value. */
171   modtime = times->modtime - __timezone;
172   date.ds_Days = (modtime / 86400) - 2922;
173   modtime %= 86400;
174   date.ds_Minute = modtime / 60;
175   modtime %= 60;
176   date.ds_Tick = modtime * TICKS_PER_SECOND;
177   error = SetFileDate (path, &date);
178   if (error == DOSFALSE)
179     {
180       errno = EOSERR;
181       return -1;
182     }
183   return 0;
184 }