2 * $Id: appl.c,v 1.12.2.1.2.2 2004-02-20 21:22:57 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
17 #include <sys/param.h>
18 #include <atalk/logger.h>
21 #include <atalk/adouble.h>
22 #include <atalk/afp.h>
26 #include "directory.h"
30 static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0 };
32 static __inline__ int pathcmp( p, plen, q, qlen )
38 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
41 static int applopen( vol, creator, flags, mode )
45 char *dtf, *adt, *adts;
47 if ( sa.sdt_fd != -1 ) {
48 if ( !(flags & ( O_RDWR | O_WRONLY )) &&
49 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
50 sa.sdt_vid == vol->v_vid ) {
57 dtf = dtfile( vol, creator, ".appl" );
59 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
60 if ( errno == ENOENT && ( flags & O_CREAT )) {
61 if (( adts = strrchr( dtf, '/' )) == NULL ) {
62 return( AFPERR_PARAM );
65 if (( adt = strrchr( dtf, '/' )) == NULL ) {
66 return( AFPERR_PARAM );
69 (void) ad_mkdir( dtf, DIRBITS | 0777 );
71 (void) ad_mkdir( dtf, DIRBITS | 0777 );
74 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
75 return( AFPERR_PARAM );
78 return( AFPERR_PARAM );
81 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
82 sa.sdt_vid = vol->v_vid;
88 * copy appls to new file, deleting any matching (old) appl entries
90 static int copyapplfile( sfd, dfd, mpath, mplen )
100 char buf[ MAXPATHLEN ];
102 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
103 p = buf + sizeof(appltag);
104 memcpy( &len, p, sizeof(len));
107 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
110 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
112 if ( write( dfd, buf, p - buf ) != p - buf ) {
122 * build mac. path (backwards) by traversing the directory tree
124 * The old way: dir and path refer to an app, path is a mac format
125 * pathname. makemacpath() builds something that looks like a cname,
126 * but uses upaths instead of mac format paths.
128 * The new way: dir and path refer to an app, path is a mac format
129 * pathname. makemacpath() builds a cname. (zero is a path separator
130 * and it's not \0 terminated).
132 * See afp_getappl() for the backward compatiblity code.
135 makemacpath( mpath, mpathlen, dir, path )
143 p = mpath + mpathlen;
145 memcpy( p, path, strlen( path ));
147 while ( dir->d_parent != NULL ) {
148 p -= strlen( dir->d_m_name ) + 1;
150 /* FIXME: pathname too long */
153 strcpy( p, dir->d_m_name );
160 int afp_addappl(obj, ibuf, ibuflen, rbuf, rbuflen )
163 int ibuflen, *rbuflen;
169 u_int16_t vid, mplen;
174 char *mpath, *tempfile;
179 memcpy( &vid, ibuf, sizeof( vid ));
180 ibuf += sizeof( vid );
181 if (NULL == ( vol = getvolbyvid( vid ))) {
182 return( AFPERR_PARAM );
185 memcpy( &did, ibuf, sizeof( did ));
186 ibuf += sizeof( did );
187 if (NULL == ( dir = dirlookup( vol, did )) ) {
191 memcpy( creator, ibuf, sizeof( creator ));
192 ibuf += sizeof( creator );
194 memcpy( appltag, ibuf, sizeof( appltag ));
195 ibuf += sizeof( appltag );
197 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
198 return get_afp_errno(AFPERR_PARAM);
200 if ( path_isadir(path) ) {
201 return( AFPERR_BADTYPE );
204 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
205 return( AFPERR_PARAM );
207 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
208 return( AFPERR_PARAM );
210 dtf = dtfile( vol, creator, ".appl.temp" );
211 tempfile = obj->oldtmp;
212 strcpy( tempfile, dtf );
213 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
214 return( AFPERR_PARAM );
217 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
221 mplen = mpath + AFPOBJ_TMPSIZ - mp;
223 /* write the new appl entry at start of temporary file */
224 p = mp - sizeof( u_short );
225 mplen = htons( mplen );
226 memcpy( p, &mplen, sizeof( mplen ));
227 mplen = ntohs( mplen );
228 p -= sizeof( appltag );
229 memcpy(p, appltag, sizeof( appltag ));
230 cc = mpath + AFPOBJ_TMPSIZ - p;
231 if ( write( tfd, p, cc ) != cc ) {
233 return( AFPERR_PARAM );
235 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
242 return( AFPERR_PARAM );
244 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
245 return( AFPERR_PARAM );
250 int afp_rmvappl(obj, ibuf, ibuflen, rbuf, rbuflen )
253 int ibuflen, *rbuflen;
259 u_int16_t vid, mplen;
263 char *tempfile, *mpath;
268 memcpy( &vid, ibuf, sizeof( vid ));
269 ibuf += sizeof( vid );
270 if (NULL == ( vol = getvolbyvid( vid ))) {
271 return( AFPERR_PARAM );
274 memcpy( &did, ibuf, sizeof( did ));
275 ibuf += sizeof( did );
276 if (NULL == ( dir = dirlookup( vol, did )) ) {
280 memcpy( creator, ibuf, sizeof( creator ));
281 ibuf += sizeof( creator );
283 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
284 return get_afp_errno(AFPERR_PARAM);
286 if ( path_isadir(path) ) {
287 return( AFPERR_BADTYPE );
290 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
291 return( AFPERR_NOOBJ );
293 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
294 return( AFPERR_PARAM );
296 dtf = dtfile( vol, creator, ".appl.temp" );
297 tempfile = obj->oldtmp;
298 strcpy( tempfile, dtf );
299 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
300 return( AFPERR_PARAM );
303 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
305 return AFPERR_PARAM ;
308 mplen = mpath + AFPOBJ_TMPSIZ - mp;
309 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
316 return( AFPERR_PARAM );
318 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
319 return( AFPERR_PARAM );
324 int afp_getappl(obj, ibuf, ibuflen, rbuf, rbuflen )
327 int ibuflen, *rbuflen;
332 u_int16_t vid, aindex, bitmap, len;
340 memcpy( &vid, ibuf, sizeof( vid ));
341 ibuf += sizeof( vid );
342 if (NULL == ( vol = getvolbyvid( vid )) ) {
344 return( AFPERR_PARAM );
347 memcpy( creator, ibuf, sizeof( creator ));
348 ibuf += sizeof( creator );
350 memcpy( &aindex, ibuf, sizeof( aindex ));
351 ibuf += sizeof( aindex );
352 aindex = ntohs( aindex );
353 if ( aindex ) { /* index 0 == index 1 */
357 memcpy( &bitmap, ibuf, sizeof( bitmap ));
358 bitmap = ntohs( bitmap );
359 ibuf += sizeof( bitmap );
361 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
363 return( AFPERR_NOITEM );
365 if ( aindex < sa.sdt_index ) {
366 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
368 return( AFPERR_PARAM );
373 /* position to correct spot within appl file */
375 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
376 + sizeof( u_short ))) > 0 ) {
377 p = buf + sizeof( appltag );
378 memcpy( &len, p, sizeof( len ));
380 p += sizeof( u_short );
381 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
384 if ( sa.sdt_index == aindex ) {
389 if ( cc <= 0 || sa.sdt_index != aindex ) {
391 return( AFPERR_NOITEM );
397 * Check to see if this APPL mapping has an mpath or a upath. If
398 * there are any ':'s in the name, it is a upath and must be converted
399 * to an mpath. Hopefully, this code will go away.
402 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
403 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
405 char utomname[ MAXPATHLEN + 1];
413 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
414 *(u+2) != '\0' && islxdigit( *(u+2))) {
416 h = hextoint( *u ) << 4;
429 if ( p[ len - 1 ] == '\0' ) {
433 #endif /* APPLCNAME */
435 /* fake up a cname */
438 *q++ = 2; /* long path type */
439 *q++ = (unsigned char)len;
443 if (( path = cname( vol, vol->v_dir, &q )) == NULL ) {
445 return( AFPERR_NOITEM );
448 if ( path_isadir(path) || path->st_errno ) {
450 return( AFPERR_NOITEM );
452 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
453 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
454 sizeof( appltag ), &buflen ) != AFP_OK ) {
456 return( AFPERR_BITMAP );
459 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
460 bitmap = htons( bitmap );
461 memcpy( rbuf, &bitmap, sizeof( bitmap ));
462 rbuf += sizeof( bitmap );
463 memcpy( rbuf, appltag, sizeof( appltag ));
464 rbuf += sizeof( appltag );