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