]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/appl.c
Merge branch 'release-3-0-alpha3'
[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         close(tfd);
340         return AFPERR_PARAM ;
341     }
342
343     mplen =  mpath + AFPOBJ_TMPSIZ - mp;
344     cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
345     close( tfd );
346     close( sa.sdt_fd );
347     sa.sdt_fd = -1;
348
349     if ( cc < 0 ) {
350         unlink( tempfile );
351         return( AFPERR_PARAM );
352     }
353     if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
354         return( AFPERR_PARAM );
355     }
356     return( AFP_OK );
357 }
358
359 int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
360 {
361     struct vol          *vol;
362     char                *p, *q;
363     int                 cc; 
364     size_t              buflen;
365     uint16_t            vid, aindex, bitmap, len;
366     unsigned char               creator[ 4 ];
367     unsigned char               appltag[ 4 ];
368     char                *buf, *cbuf;
369     struct path         *path;
370     
371     ibuf += 2;
372
373     memcpy( &vid, ibuf, sizeof( vid ));
374     ibuf += sizeof( vid );
375     if (NULL == ( vol = getvolbyvid( vid )) ) {
376         *rbuflen = 0;
377         return( AFPERR_PARAM );
378     }
379
380     memcpy( creator, ibuf, sizeof( creator ));
381     ibuf += sizeof( creator );
382
383     memcpy( &aindex, ibuf, sizeof( aindex ));
384     ibuf += sizeof( aindex );
385     aindex = ntohs( aindex );
386     if ( aindex ) { /* index 0 == index 1 */
387         --aindex;
388     }
389
390     memcpy( &bitmap, ibuf, sizeof( bitmap ));
391     bitmap = ntohs( bitmap );
392     ibuf += sizeof( bitmap );
393
394     if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
395         *rbuflen = 0;
396         return( AFPERR_NOITEM );
397     }
398     if ( aindex < sa.sdt_index ) {
399         if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
400             *rbuflen = 0;
401             return( AFPERR_PARAM );
402         }
403         sa.sdt_index = 0;
404     }
405
406     /* position to correct spot within appl file */
407     buf = obj->oldtmp;
408     while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
409                         + sizeof( u_short ))) > 0 ) {
410         p = buf + sizeof( appltag );
411         memcpy( &len, p, sizeof( len ));
412         len = ntohs( len );
413         p += sizeof( u_short );
414         if (( cc = read( sa.sdt_fd, p, len )) < len ) {
415             break;
416         }
417         if ( sa.sdt_index == aindex ) {
418             break;
419         }
420         sa.sdt_index++;
421     }
422     if ( cc <= 0 || sa.sdt_index != aindex ) {
423         *rbuflen = 0;
424         return( AFPERR_NOITEM );
425     }
426     sa.sdt_index++;
427
428 #ifdef APPLCNAME
429     /*
430      * Check to see if this APPL mapping has an mpath or a upath.  If
431      * there are any ':'s in the name, it is a upath and must be converted
432      * to an mpath.  Hopefully, this code will go away.
433      */
434     {
435 #define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
436 #define islxdigit(x)    (!isupper(x)&&isxdigit(x))
437
438         char    utomname[ MAXPATHLEN + 1];
439         char            *u, *m;
440         int             i, h;
441
442         u = p;
443         m = utomname;
444         i = len;
445         while ( i ) {
446             if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
447                     *(u+2) != '\0' && islxdigit( *(u+2))) {
448                 ++u, --i;
449                 h = hextoint( *u ) << 4;
450                 ++u, --i;
451                 h |= hextoint( *u );
452                 *m++ = h;
453             } else {
454                 *m++ = *u;
455             }
456             ++u, --i;
457         }
458
459         len = m - utomname;
460         p = utomname;
461
462         if ( p[ len - 1 ] == '\0' ) {
463             len--;
464         }
465     }
466 #endif /* APPLCNAME */
467
468     /* fake up a cname */
469     cbuf = obj->newtmp;
470     q = cbuf;
471     *q++ = 2;   /* long path type */
472     *q++ = (unsigned char)len;
473     memcpy( q, p, len );
474     q = cbuf;
475
476     if (( path = cname( vol, vol->v_root, &q )) == NULL ) {
477         *rbuflen = 0;
478         return( AFPERR_NOITEM );
479     }
480
481     if ( path_isadir(path) || path->st_errno ) {
482         *rbuflen = 0;
483         return( AFPERR_NOITEM );
484     }
485     buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
486     if ( getfilparams(obj, vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
487                       sizeof( appltag ), &buflen, 0) != AFP_OK ) {
488         *rbuflen = 0;
489         return( AFPERR_BITMAP );
490     }
491
492     *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
493     bitmap = htons( bitmap );
494     memcpy( rbuf, &bitmap, sizeof( bitmap ));
495     rbuf += sizeof( bitmap );
496     memcpy( rbuf, appltag, sizeof( appltag ));
497     rbuf += sizeof( appltag );
498     return( AFP_OK );
499 }
500