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