]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/appl.c
c5d9ea06c817d360daa367ee133a68c6354a5950
[netatalk.git] / etc / afpd / appl.c
1 /*
2  * Copyright (c) 1990,1993 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/param.h>
19 #include <sys/syslog.h>
20 #include <errno.h>
21
22 #include <netatalk/endian.h>
23 #include <atalk/adouble.h>
24 #include <atalk/afp.h>
25
26 #include "volume.h"
27 #include "globals.h"
28 #include "directory.h"
29 #include "file.h"
30 #include "desktop.h"
31
32 static struct savedt    sa = { { 0, 0, 0, 0 }, -1, 0 };
33
34 static __inline__ int pathcmp( p, plen, q, qlen )
35     char        *p;
36     int plen;
37     char        *q;
38     int qlen;
39 {
40     return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
41 }
42
43 static int applopen( vol, creator, flags, mode )
44     struct vol  *vol;
45     u_char      creator[ 4 ];
46 {
47     char        *dtf, *adt, *adts;
48
49     if ( sa.sdt_fd != -1 ) {
50         if ( !(flags & ( O_RDWR | O_WRONLY )) &&
51                 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
52                 sa.sdt_vid == vol->v_vid ) {
53             return( AFP_OK );
54         }
55         close( sa.sdt_fd );
56         sa.sdt_fd = -1;
57     }
58
59     dtf = dtfile( vol, creator, ".appl" );
60
61     if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
62         if ( errno == ENOENT && ( flags & O_CREAT )) {
63             if (( adts = strrchr( dtf, '/' )) == NULL ) {
64                 return( AFPERR_PARAM );
65             }
66             *adts = '\0';
67             if (( adt = strrchr( dtf, '/' )) == NULL ) {
68                 return( AFPERR_PARAM );
69             }
70             *adt = '\0';
71             (void) ad_mkdir( dtf, DIRBITS | 0777 );
72             *adt = '/';
73             (void) ad_mkdir( dtf, DIRBITS | 0777 );
74             *adts = '/';
75
76             if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
77                 return( AFPERR_PARAM );
78             }
79         } else {
80             return( AFPERR_PARAM );
81         }
82     }
83     memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
84     sa.sdt_vid = vol->v_vid;
85     sa.sdt_index = 0;
86     return( AFP_OK );
87 }
88
89 /*
90  * copy appls to new file, deleting any matching (old) appl entries
91  */
92 static int copyapplfile( sfd, dfd, mpath, mplen )
93     int         sfd;
94     int         dfd;
95     char        *mpath;
96     u_short     mplen;
97 {
98     int         cc;
99     char        *p;
100     u_int16_t   len;
101     u_char      appltag[ 4 ];
102     char        buf[ MAXPATHLEN ];
103
104     while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
105         p = buf + sizeof(appltag);
106         memcpy( &len, p, sizeof(len));
107         len = ntohs( len );
108         p += sizeof( len );
109         if (( cc = read( sa.sdt_fd, p, len )) < len ) {
110             break;
111         }
112         if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
113             p += len;
114             if ( write( dfd, buf, p - buf ) != p - buf ) {
115                 cc = -1;
116                 break;
117             }
118         }
119     }
120     return( cc );
121 }
122
123 /*
124  * build mac. path (backwards) by traversing the directory tree
125  *
126  * The old way: dir and path refer to an app, path is a mac format
127  * pathname.  makemacpath() builds something that looks like a cname,
128  * but uses upaths instead of mac format paths.
129  *
130  * The new way: dir and path refer to an app, path is a mac format
131  * pathname.  makemacpath() builds a cname.
132  *
133  * See afp_getappl() for the backward compatiblity code.
134  */
135 static char *
136 makemacpath( mpath, mpathlen, dir, path )
137     char        *mpath;
138     int         mpathlen;
139     struct dir  *dir;
140     char        *path;
141 {
142     char        *p;
143
144     p = mpath + mpathlen;
145     p -= strlen( path );
146     strncpy( p, path, strlen( path ));
147
148     while ( dir->d_parent != NULL ) {
149         p -= strlen( dir->d_name ) + 1;
150         strcpy( p, dir->d_name );
151         dir = dir->d_parent;
152     }
153     return( p ); 
154 }
155
156
157 int afp_addappl(obj, ibuf, ibuflen, rbuf, rbuflen )
158     AFPObj      *obj;
159     char        *ibuf, *rbuf;
160     int         ibuflen, *rbuflen;
161 {
162     struct vol          *vol;
163     struct dir          *dir;
164     int                 tfd, cc; 
165     u_int32_t           did;
166     u_int16_t           vid, mplen;
167     char                *path, *dtf, *p, *mp;
168     u_char              creator[ 4 ];
169     u_char              appltag[ 4 ];
170     char                *mpath, *tempfile;
171
172     *rbuflen = 0;
173     ibuf += 2;
174
175     memcpy( &vid, ibuf, sizeof( vid ));
176     ibuf += sizeof( vid );
177     if (( vol = getvolbyvid( vid )) == NULL ) {
178         return( AFPERR_PARAM );
179     }
180
181     memcpy( &did, ibuf, sizeof( did ));
182     ibuf += sizeof( did );
183     if (( dir = dirsearch( vol, did )) == NULL ) {
184         return( AFPERR_NOOBJ );
185     }
186
187     memcpy( creator, ibuf, sizeof( creator ));
188     ibuf += sizeof( creator );
189
190     memcpy( appltag, ibuf, sizeof( appltag ));
191     ibuf += sizeof( appltag );
192
193     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
194         return( AFPERR_NOOBJ );
195     }
196     if ( *path == '\0' ) {
197         return( AFPERR_BADTYPE );
198     }
199
200     if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
201         return( AFPERR_PARAM );
202     }
203     if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
204         return( AFPERR_PARAM );
205     }
206     dtf = dtfile( vol, creator, ".appl.temp" );
207     tempfile = obj->oldtmp;
208     strcpy( tempfile, dtf );
209     if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
210         return( AFPERR_PARAM );
211     }
212     mpath = obj->newtmp;
213     mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
214     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
215
216     /* write the new appl entry at start of temporary file */
217     p = mp - sizeof( u_short );
218     mplen = htons( mplen );
219     memcpy( p, &mplen, sizeof( mplen ));
220     mplen = ntohs( mplen );
221     p -= sizeof( appltag );
222     memcpy(p, appltag, sizeof( appltag ));
223     cc = mpath + AFPOBJ_TMPSIZ - p;
224     if ( write( tfd, p, cc ) != cc ) {
225         unlink( tempfile );
226         return( AFPERR_PARAM );
227     }
228     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
229     close( tfd );
230     close( sa.sdt_fd );
231     sa.sdt_fd = -1;
232
233     if ( cc < 0 ) {
234         unlink( tempfile );
235         return( AFPERR_PARAM );
236     }
237     if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
238         return( AFPERR_PARAM );
239     }
240     return( AFP_OK );
241 }
242
243 int afp_rmvappl(obj, ibuf, ibuflen, rbuf, rbuflen )
244     AFPObj      *obj;
245     char        *ibuf, *rbuf;
246     int         ibuflen, *rbuflen;
247 {
248     struct vol          *vol;
249     struct dir          *dir;
250     int                 tfd, cc;
251     u_int32_t           did;
252     u_int16_t           vid, mplen;
253     char                *path, *dtf, *mp;
254     u_char              creator[ 4 ];
255     char                *tempfile, *mpath;
256
257     *rbuflen = 0;
258     ibuf += 2;
259
260     memcpy( &vid, ibuf, sizeof( vid ));
261     ibuf += sizeof( vid );
262     if (( vol = getvolbyvid( vid )) == NULL ) {
263         return( AFPERR_PARAM );
264     }
265
266     memcpy( &did, ibuf, sizeof( did ));
267     ibuf += sizeof( did );
268     if (( dir = dirsearch( vol, did )) == NULL ) {
269         return( AFPERR_NOOBJ );
270     }
271
272     memcpy( creator, ibuf, sizeof( creator ));
273     ibuf += sizeof( creator );
274
275     if (( path = cname( vol, dir, &ibuf )) == NULL ) {
276         return( AFPERR_NOOBJ );
277     }
278     if ( *path == '.' ) {
279         return( AFPERR_BADTYPE );
280     }
281
282     if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
283         return( AFPERR_NOOBJ );
284     }
285     if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
286         return( AFPERR_PARAM );
287     }
288     dtf = dtfile( vol, creator, ".appl.temp" );
289     tempfile = obj->oldtmp;
290     strcpy( tempfile, dtf );
291     if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
292         return( AFPERR_PARAM );
293     }
294     mpath = obj->newtmp;
295     mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
296     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
297     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
298     close( tfd );
299     close( sa.sdt_fd );
300     sa.sdt_fd = -1;
301
302     if ( cc < 0 ) {
303         unlink( tempfile );
304         return( AFPERR_PARAM );
305     }
306     if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
307         return( AFPERR_PARAM );
308     }
309     return( AFP_OK );
310 }
311
312 int afp_getappl(obj, ibuf, ibuflen, rbuf, rbuflen )
313     AFPObj      *obj;
314     char        *ibuf, *rbuf;
315     int         ibuflen, *rbuflen;
316 {
317     struct stat         st;
318     struct vol          *vol;
319     char                *p, *q;
320     int                 cc, buflen;
321     u_int16_t           vid, aindex, bitmap, len;
322     u_char              creator[ 4 ];
323     u_char              appltag[ 4 ];
324     char                *buf, *cbuf;
325
326     ibuf += 2;
327
328     memcpy( &vid, ibuf, sizeof( vid ));
329     ibuf += sizeof( vid );
330     if (( vol = getvolbyvid( vid )) == NULL ) {
331         *rbuflen = 0;
332         return( AFPERR_PARAM );
333     }
334
335     memcpy( creator, ibuf, sizeof( creator ));
336     ibuf += sizeof( creator );
337
338     memcpy( &aindex, ibuf, sizeof( aindex ));
339     ibuf += sizeof( aindex );
340     aindex = ntohs( aindex );
341     if ( aindex ) { /* index 0 == index 1 */
342         --aindex;
343     }
344     
345     memcpy( &bitmap, ibuf, sizeof( bitmap ));
346     bitmap = ntohs( bitmap );
347     ibuf += sizeof( bitmap );
348
349     if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
350         *rbuflen = 0;
351         return( AFPERR_NOITEM );
352     }
353     if ( aindex < sa.sdt_index ) {
354         if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
355             *rbuflen = 0;
356             return( AFPERR_PARAM );
357         }
358         sa.sdt_index = 0;
359     }
360
361     /* position to correct spot within appl file */
362     buf = obj->oldtmp;
363     while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
364             + sizeof( u_short ))) > 0 ) {
365         p = buf + sizeof( appltag );
366         memcpy( &len, p, sizeof( len ));
367         len = ntohs( len );
368         p += sizeof( u_short );
369         if (( cc = read( sa.sdt_fd, p, len )) < len ) {
370             break;
371         }
372         if ( sa.sdt_index == aindex ) {
373             break;
374         }
375         sa.sdt_index++;
376     }
377     if ( cc <= 0 || sa.sdt_index != aindex ) {
378         *rbuflen = 0;
379         return( AFPERR_NOITEM );
380     }
381     sa.sdt_index++;
382
383 #ifdef APPLCNAME
384     /*
385      * Check to see if this APPL mapping has an mpath or a upath.  If
386      * there are any ':'s in the name, it is a upath and must be converted
387      * to an mpath.  Hopefully, this code will go away.
388      */
389     {
390 #define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
391 #define islxdigit(x)    (!isupper(x)&&isxdigit(x))
392
393         char    utomname[ MAXPATHLEN + 1];
394         char            *u, *m;
395         int             i, h;
396
397         u = p;
398         m = utomname;
399         i = len;
400         while ( i ) {
401             if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
402                     *(u+2) != '\0' && islxdigit( *(u+2))) {
403                 ++u, --i;
404                 h = hextoint( *u ) << 4;
405                 ++u, --i;
406                 h |= hextoint( *u );
407                 *m++ = h;
408             } else {
409                 *m++ = *u;
410             }
411             ++u, --i;
412         }
413
414         len = m - utomname;
415         p = utomname;
416
417         if ( p[ len - 1 ] == '\0' ) {
418             len--;
419         }
420     }
421 #endif APPLCNAME
422
423     /* fake up a cname */
424     cbuf = obj->newtmp;
425     q = cbuf;
426     *q++ = 2;   /* long path type */
427     *q++ = (unsigned char)len;
428     memcpy( q, p, len );
429     q = cbuf;
430
431     if (( p = cname( vol, vol->v_dir, &q )) == NULL ) {
432         *rbuflen = 0;
433         return( AFPERR_NOITEM );
434     }
435
436     if ( stat( mtoupath(vol, p), &st ) < 0 ) {
437         *rbuflen = 0;
438         return( AFPERR_NOITEM );
439     }
440     buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
441     if ( getfilparams(vol, bitmap, p, curdir, &st, rbuf + sizeof( bitmap ) +
442             sizeof( appltag ), &buflen ) != AFP_OK ) {
443         *rbuflen = 0;
444         return( AFPERR_BITMAP );
445     }
446
447     *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
448     bitmap = htons( bitmap );
449     memcpy( rbuf, &bitmap, sizeof( bitmap ));
450     rbuf += sizeof( bitmap );
451     memcpy( rbuf, appltag, sizeof( appltag ));
452     rbuf += sizeof( appltag );
453     return( AFP_OK );
454 }
455
456