]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/appl.c
Remove CVS keywords
[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         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         close(tfd);
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, 0) != 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