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