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