]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/appl.c
Merge remote-tracking branch 'remotes/origin/branch-netatalk-2-1'
[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
26 #include "volume.h"
27 #include "globals.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     u_int16_t   len;
91     u_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         if ((uname = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL ) {
174             afp_errno = AFPERR_NOOBJ;
175             ret = NULL;
176             goto exit;
177         }
178
179         if ((path = utompath(vol, uname, cnid, utf8_encoding())) == NULL) {
180             afp_errno = AFPERR_MISC;
181             ret = NULL;
182             goto exit;
183         }
184     }
185
186
187
188 exit:
189     if (pathlist)
190         bstrListDestroy(pathlist);
191
192     return(ret);
193 #endif
194 }
195
196
197 int afp_addappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
198 {
199     struct vol          *vol;
200     struct dir          *dir;
201     int                 tfd, cc;
202     u_int32_t           did;
203     u_int16_t           vid, mplen;
204     struct path         *path;
205     char                *dtf, *p, *mp;
206     u_char              creator[ 4 ];
207     u_char              appltag[ 4 ];
208     char                *mpath, *tempfile;
209
210     *rbuflen = 0;
211     ibuf += 2;
212
213     memcpy( &vid, ibuf, sizeof( vid ));
214     ibuf += sizeof( vid );
215     if (NULL == ( vol = getvolbyvid( vid ))) {
216         return( AFPERR_PARAM );
217     }
218
219     memcpy( &did, ibuf, sizeof( did ));
220     ibuf += sizeof( did );
221     if (NULL == ( dir = dirlookup( vol, did )) ) {
222         return afp_errno;
223     }
224
225     memcpy( creator, ibuf, sizeof( creator ));
226     ibuf += sizeof( creator );
227
228     memcpy( appltag, ibuf, sizeof( appltag ));
229     ibuf += sizeof( appltag );
230
231     if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
232         return get_afp_errno(AFPERR_PARAM);
233     }
234     if ( path_isadir(path) ) {
235         return( AFPERR_BADTYPE );
236     }
237
238     if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
239         return( AFPERR_PARAM );
240     }
241     if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
242         return( AFPERR_PARAM );
243     }
244     dtf = dtfile( vol, creator, ".appl.temp" );
245     tempfile = obj->oldtmp;
246     strcpy( tempfile, dtf );
247     if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
248         return( AFPERR_PARAM );
249     }
250     mpath = obj->newtmp;
251     mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
252     if (!mp) {
253         return AFPERR_PARAM;
254     }
255     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
256
257     /* write the new appl entry at start of temporary file */
258     p = mp - sizeof( u_short );
259     mplen = htons( mplen );
260     memcpy( p, &mplen, sizeof( mplen ));
261     mplen = ntohs( mplen );
262     p -= sizeof( appltag );
263     memcpy(p, appltag, sizeof( appltag ));
264     cc = mpath + AFPOBJ_TMPSIZ - p;
265     if ( write( tfd, p, cc ) != cc ) {
266         unlink( tempfile );
267         return( AFPERR_PARAM );
268     }
269     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
270     close( tfd );
271     close( sa.sdt_fd );
272     sa.sdt_fd = -1;
273
274     if ( cc < 0 ) {
275         unlink( tempfile );
276         return( AFPERR_PARAM );
277     }
278     if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
279         return( AFPERR_PARAM );
280     }
281     return( AFP_OK );
282 }
283
284 int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
285 {
286     struct vol          *vol;
287     struct dir          *dir;
288     int                 tfd, cc;
289     u_int32_t           did;
290     u_int16_t           vid, mplen;
291     struct path         *path;
292     char                *dtf, *mp;
293     u_char              creator[ 4 ];
294     char                *tempfile, *mpath;
295
296     *rbuflen = 0;
297     ibuf += 2;
298
299     memcpy( &vid, ibuf, sizeof( vid ));
300     ibuf += sizeof( vid );
301     if (NULL == ( vol = getvolbyvid( vid ))) {
302         return( AFPERR_PARAM );
303     }
304
305     memcpy( &did, ibuf, sizeof( did ));
306     ibuf += sizeof( did );
307     if (NULL == ( dir = dirlookup( vol, did )) ) {
308         return afp_errno;
309     }
310
311     memcpy( creator, ibuf, sizeof( creator ));
312     ibuf += sizeof( creator );
313
314     if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
315         return get_afp_errno(AFPERR_PARAM);
316     }
317     if ( path_isadir(path) ) {
318         return( AFPERR_BADTYPE );
319     }
320
321     if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
322         return( AFPERR_NOOBJ );
323     }
324     if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
325         return( AFPERR_PARAM );
326     }
327     dtf = dtfile( vol, creator, ".appl.temp" );
328     tempfile = obj->oldtmp;
329     strcpy( tempfile, dtf );
330     if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
331         return( AFPERR_PARAM );
332     }
333     mpath = obj->newtmp;
334     mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
335     if (!mp) {
336         return AFPERR_PARAM ;
337     }
338
339     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
340     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
341     close( tfd );
342     close( sa.sdt_fd );
343     sa.sdt_fd = -1;
344
345     if ( cc < 0 ) {
346         unlink( tempfile );
347         return( AFPERR_PARAM );
348     }
349     if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
350         return( AFPERR_PARAM );
351     }
352     return( AFP_OK );
353 }
354
355 int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
356 {
357     struct vol          *vol;
358     char                *p, *q;
359     int                 cc; 
360     size_t              buflen;
361     u_int16_t           vid, aindex, bitmap, len;
362     u_char              creator[ 4 ];
363     u_char              appltag[ 4 ];
364     char                *buf, *cbuf;
365     struct path         *path;
366     
367     ibuf += 2;
368
369     memcpy( &vid, ibuf, sizeof( vid ));
370     ibuf += sizeof( vid );
371     if (NULL == ( vol = getvolbyvid( vid )) ) {
372         *rbuflen = 0;
373         return( AFPERR_PARAM );
374     }
375
376     memcpy( creator, ibuf, sizeof( creator ));
377     ibuf += sizeof( creator );
378
379     memcpy( &aindex, ibuf, sizeof( aindex ));
380     ibuf += sizeof( aindex );
381     aindex = ntohs( aindex );
382     if ( aindex ) { /* index 0 == index 1 */
383         --aindex;
384     }
385
386     memcpy( &bitmap, ibuf, sizeof( bitmap ));
387     bitmap = ntohs( bitmap );
388     ibuf += sizeof( bitmap );
389
390     if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
391         *rbuflen = 0;
392         return( AFPERR_NOITEM );
393     }
394     if ( aindex < sa.sdt_index ) {
395         if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
396             *rbuflen = 0;
397             return( AFPERR_PARAM );
398         }
399         sa.sdt_index = 0;
400     }
401
402     /* position to correct spot within appl file */
403     buf = obj->oldtmp;
404     while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
405                         + sizeof( u_short ))) > 0 ) {
406         p = buf + sizeof( appltag );
407         memcpy( &len, p, sizeof( len ));
408         len = ntohs( len );
409         p += sizeof( u_short );
410         if (( cc = read( sa.sdt_fd, p, len )) < len ) {
411             break;
412         }
413         if ( sa.sdt_index == aindex ) {
414             break;
415         }
416         sa.sdt_index++;
417     }
418     if ( cc <= 0 || sa.sdt_index != aindex ) {
419         *rbuflen = 0;
420         return( AFPERR_NOITEM );
421     }
422     sa.sdt_index++;
423
424 #ifdef APPLCNAME
425     /*
426      * Check to see if this APPL mapping has an mpath or a upath.  If
427      * there are any ':'s in the name, it is a upath and must be converted
428      * to an mpath.  Hopefully, this code will go away.
429      */
430     {
431 #define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
432 #define islxdigit(x)    (!isupper(x)&&isxdigit(x))
433
434         char    utomname[ MAXPATHLEN + 1];
435         char            *u, *m;
436         int             i, h;
437
438         u = p;
439         m = utomname;
440         i = len;
441         while ( i ) {
442             if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
443                     *(u+2) != '\0' && islxdigit( *(u+2))) {
444                 ++u, --i;
445                 h = hextoint( *u ) << 4;
446                 ++u, --i;
447                 h |= hextoint( *u );
448                 *m++ = h;
449             } else {
450                 *m++ = *u;
451             }
452             ++u, --i;
453         }
454
455         len = m - utomname;
456         p = utomname;
457
458         if ( p[ len - 1 ] == '\0' ) {
459             len--;
460         }
461     }
462 #endif /* APPLCNAME */
463
464     /* fake up a cname */
465     cbuf = obj->newtmp;
466     q = cbuf;
467     *q++ = 2;   /* long path type */
468     *q++ = (unsigned char)len;
469     memcpy( q, p, len );
470     q = cbuf;
471
472     if (( path = cname( vol, vol->v_root, &q )) == NULL ) {
473         *rbuflen = 0;
474         return( AFPERR_NOITEM );
475     }
476
477     if ( path_isadir(path) || path->st_errno ) {
478         *rbuflen = 0;
479         return( AFPERR_NOITEM );
480     }
481     buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
482     if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
483                       sizeof( appltag ), &buflen ) != AFP_OK ) {
484         *rbuflen = 0;
485         return( AFPERR_BITMAP );
486     }
487
488     *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
489     bitmap = htons( bitmap );
490     memcpy( rbuf, &bitmap, sizeof( bitmap ));
491     rbuf += sizeof( bitmap );
492     memcpy( rbuf, appltag, sizeof( appltag ));
493     rbuf += sizeof( appltag );
494     return( AFP_OK );
495 }
496