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