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