]> arthur.barton.de Git - netatalk.git/blob - bin/afile/afile.c
Added afile utilities to bin tree (unmodified package)
[netatalk.git] / bin / afile / afile.c
1 /*
2  * Copyright 1998 The University of Newcastle upon Tyne
3  * 
4  * Permission to use, copy, modify and distribute this software and its
5  * documentation for any purpose other than its commercial exploitation
6  * is hereby granted without fee, provided that the above copyright
7  * notice appear in all copies and that both that copyright notice and
8  * this permission notice appear in supporting documentation, and that
9  * the name of The University of Newcastle upon Tyne not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission. The University of
12  * Newcastle upon Tyne makes no representations about the suitability of
13  * this software for any purpose. It is provided "as is" without express
14  * or implied warranty.
15  * 
16  * THE UNIVERSITY OF NEWCASTLE UPON TYNE DISCLAIMS ALL WARRANTIES WITH
17  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
19  * NEWCASTLE UPON TYNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
21  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  * 
25  * Author:  Gerry Tomlinson (gerry.tomlinson@newcastle.ac.uk)
26  *          Computing Science Department, University of Newcastle upon Tyne, UK
27  */
28
29 /*
30  *
31  * program afile
32  *
33  *
34  * show creator/type of netatalk file
35  *  
36  * usage  afile [-a] file ....
37  * 
38  * looks for MAGIC at start to see if an AppleDouble else assumes it's a
39  * data fork and only reports if corresponding  .AppleDouble exists unless -a option set
40  * in which case report unknown if not a directory (does not look for
41  * extension mappings)
42  *
43  * returns exit status 0 if all files have corresponding readable  valid .AppleDouble or data fork
44  *
45  * if both parts of file don't exist in correct form it returns (for last file): 
46  *
47  *      1  file doesn't exist
48  *      2  file is unreadable
49  *      3  file is directory
50  *      4  file is AppleDouble without data fork
51  *      5  file is AppleDouble with unreadable data fork
52  *      6  file is data fork without AppleDouble
53  *      7  file is data fork with unreadable AppleDouble
54  *      8  file is data for with short  AppleDouble
55  *      9  bad magic in AppleDouble
56  *     99  bad command line options
57  *      
58  * by gerry.tomlinson@ncl.ac.uk
59  * last update 26/2/98
60  *
61  */
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <fcntl.h>
66 #include <strings.h>
67 #include <sys/types.h>
68 #include <netinet/in.h>
69 #include <sys/stat.h>
70
71
72 #include <atalk/adouble.h>
73
74
75 extern char *optarg;
76 extern int optind, opterr;
77
78 #define AD  ".AppleDouble"
79
80 main(int argc, char *argv[])
81
82 {
83     int fdata, fres;
84     struct stat statbuf;
85     int n,i;
86     char adbuf [AD_DATASZ];
87     struct adouble  *ad;
88     int datafork;
89     char *dname;
90     char *rname;
91     mode_t dmode;
92     mode_t rmode;
93     char *slash;
94     char c;
95     char *type = 0;
96     char *creator = 0;
97     char *p;
98     int errflag = 0;
99     int aflag = 0;
100     int status = 0;
101     int gotdata;
102
103     while ((c = getopt(argc, argv, "a")) != -1)
104     switch (c) {
105         case 'a':
106                 aflag = 1; break;
107         case '?' :
108                 errflag = 1; break;
109     }
110
111     if (errflag ||  argc == optind) { 
112           fprintf(stderr,"usage: afile [-a] file ...\n");
113            exit(99);
114     }
115
116     
117     for (; optind < argc; optind++) {
118         close (fdata);
119         close (fres);
120
121         dname = argv[optind];
122         rname = 0;
123         datafork = 1;   /* assume file is a data fork */
124         gotdata = 1;    /* assume data fork ok */
125
126         if (stat(dname, &statbuf)) {
127             fprintf(stderr,"afile: %s does not exist\n",dname);
128             status = 1;
129             continue;
130         }
131
132         if ((fdata = open(dname,O_RDONLY,0)) == -1) {
133             fprintf(stderr,"afile: cannot open %s\n",dname);
134             status = 2;
135             continue;
136         }
137          
138         fstat(fdata, &statbuf);
139         if (S_ISDIR(statbuf.st_mode)) { 
140              if (aflag) 
141                   printf("directory %s\n",dname);
142              status = 3; 
143              continue;
144         }
145         
146         if ( read(fdata,adbuf,AD_DATASZ)  == AD_DATASZ) {
147             ad = (struct adouble*)adbuf;
148             if  (ad->ad_magic == ntohl(AD_MAGIC)) {  /*  AppleDouble Header */
149                 datafork = 0;
150                 rmode = statbuf.st_mode;
151                 rname = dname;
152                 dname = calloc(strlen(rname)+4,1);
153                 slash = rindex(rname,'/');
154                 if (!slash) {
155                     strcpy(dname,"../");
156                     strcat(dname,rname);
157                 }
158                 else {
159                     strncpy(dname, rname, slash + 1 - rname);
160                     strcat(dname,"../");
161                     strcat(dname,slash+1);
162                 }
163                 if (stat(dname, &statbuf)) {
164                     status = 4;         /* data fork doesn't exist */
165                     gotdata = 0;                    
166                 } else if ((fdata = open(dname,O_RDONLY,0)) == -1) {        
167                     status = 5;         /* can't open data fork for reading */
168                     gotdata = 0;
169                 }
170                 dmode = statbuf.st_mode;               
171             }    
172         }
173
174         if (datafork)   {
175             dmode = statbuf.st_mode;
176             rname = calloc(strlen(dname)+strlen(AD)+2, 1);
177             slash = rindex(dname,'/');
178             strncpy(rname,dname,slash ? slash + 1 - dname : 0);
179             strcat(rname,AD);
180             strcat(rname,"/");
181             strcat(rname,slash ? slash+1 : dname);
182         
183             if (stat(rname, &statbuf)) {
184                 if (aflag)
185                      printf("unknown %s\n",dname); 
186                 else
187                     status = 6;
188                 continue;
189             }
190             rmode = statbuf.st_mode;
191             if ((fres = open(rname, O_RDONLY,0)) == -1) {
192                     fprintf(stderr,"afile: cannot read   %s\n",rname);
193                 status = 7;
194                 continue;
195              }
196             if (read(fres,adbuf,AD_DATASZ)  != AD_DATASZ) {
197                  fprintf(stderr,"afile: %s too small\n",rname);
198                  status = 8;
199                  continue;
200             }
201           
202             ad = (struct adouble*)adbuf;
203         }
204         
205         if  (ad->ad_magic != ntohl(AD_MAGIC)) {
206             fprintf(stderr,"afile: bad MAGIC in %s\n",rname);
207             status = 9;
208             continue;
209         }
210
211         printf("%4.4s %4.4s %s\n",adbuf+ADEDOFF_FINDERI, adbuf+ADEDOFF_FINDERI+4, 
212                 datafork ? dname : rname);
213
214         if (!gotdata) {
215             if (status == 4)
216                 fprintf(stderr,"afile: %s does not exist\n",dname);                        
217             if (status == 5)         
218                 fprintf(stderr,"afile: cannot read %s\n",dname);
219         } else if (dmode != rmode) {
220             fprintf(stderr,"afile: %s mode does not match\n",datafork ? rname : dname);
221             status = 0;
222         } 
223
224     }
225     exit (status);
226 }
227
228 /* end of program afile */