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