2 * $Id: appl.c,v 1.9 2003-01-08 15:01:33 didg Exp $
4 * Copyright (c) 1990,1993 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
18 #endif /* HAVE_FCNTL_H */
21 #endif /* HAVE_UNISTD_H */
22 #include <sys/types.h>
24 #include <sys/param.h>
25 #include <atalk/logger.h>
28 #include <netatalk/endian.h>
29 #include <atalk/adouble.h>
30 #include <atalk/afp.h>
34 #include "directory.h"
38 static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0 };
40 static __inline__ int pathcmp( p, plen, q, qlen )
46 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
49 static int applopen( vol, creator, flags, mode )
53 char *dtf, *adt, *adts;
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 ) {
65 dtf = dtfile( vol, creator, ".appl" );
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 );
73 if (( adt = strrchr( dtf, '/' )) == NULL ) {
74 return( AFPERR_PARAM );
77 (void) ad_mkdir( dtf, DIRBITS | 0777 );
79 (void) ad_mkdir( dtf, DIRBITS | 0777 );
82 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
83 return( AFPERR_PARAM );
86 return( AFPERR_PARAM );
89 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
90 sa.sdt_vid = vol->v_vid;
96 * copy appls to new file, deleting any matching (old) appl entries
98 static int copyapplfile( sfd, dfd, mpath, mplen )
108 char buf[ MAXPATHLEN ];
110 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
111 p = buf + sizeof(appltag);
112 memcpy( &len, p, sizeof(len));
115 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
118 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
120 if ( write( dfd, buf, p - buf ) != p - buf ) {
130 * build mac. path (backwards) by traversing the directory tree
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.
136 * The new way: dir and path refer to an app, path is a mac format
137 * pathname. makemacpath() builds a cname.
139 * See afp_getappl() for the backward compatiblity code.
142 makemacpath( mpath, mpathlen, dir, path )
150 p = mpath + mpathlen;
152 strncpy( p, path, strlen( path ));
154 while ( dir->d_parent != NULL ) {
155 p -= strlen( dir->d_m_name ) + 1;
156 strcpy( p, dir->d_m_name );
163 int afp_addappl(obj, ibuf, ibuflen, rbuf, rbuflen )
166 int ibuflen, *rbuflen;
172 u_int16_t vid, mplen;
177 char *mpath, *tempfile;
182 memcpy( &vid, ibuf, sizeof( vid ));
183 ibuf += sizeof( vid );
184 if (( vol = getvolbyvid( vid )) == NULL ) {
185 return( AFPERR_PARAM );
188 memcpy( &did, ibuf, sizeof( did ));
189 ibuf += sizeof( did );
190 if (( dir = dirlookup( vol, did )) == NULL ) {
194 memcpy( creator, ibuf, sizeof( creator ));
195 ibuf += sizeof( creator );
197 memcpy( appltag, ibuf, sizeof( appltag ));
198 ibuf += sizeof( appltag );
200 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
203 if ( *path->m_name == '\0' ) {
204 return( AFPERR_BADTYPE );
207 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
208 return( AFPERR_PARAM );
210 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
211 return( AFPERR_PARAM );
213 dtf = dtfile( vol, creator, ".appl.temp" );
214 tempfile = obj->oldtmp;
215 strcpy( tempfile, dtf );
216 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
217 return( AFPERR_PARAM );
220 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 (( vol = getvolbyvid( vid )) == NULL ) {
271 return( AFPERR_PARAM );
274 memcpy( &did, ibuf, sizeof( did ));
275 ibuf += sizeof( did );
276 if (( dir = dirlookup( vol, did )) == NULL ) {
280 memcpy( creator, ibuf, sizeof( creator ));
281 ibuf += sizeof( creator );
283 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
286 if ( *path->m_name == '\0' ) {
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 );
304 mplen = mpath + AFPOBJ_TMPSIZ - mp;
305 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
312 return( AFPERR_PARAM );
314 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
315 return( AFPERR_PARAM );
320 int afp_getappl(obj, ibuf, ibuflen, rbuf, rbuflen )
323 int ibuflen, *rbuflen;
328 u_int16_t vid, aindex, bitmap, len;
336 memcpy( &vid, ibuf, sizeof( vid ));
337 ibuf += sizeof( vid );
338 if (( vol = getvolbyvid( vid )) == NULL ) {
340 return( AFPERR_PARAM );
343 memcpy( creator, ibuf, sizeof( creator ));
344 ibuf += sizeof( creator );
346 memcpy( &aindex, ibuf, sizeof( aindex ));
347 ibuf += sizeof( aindex );
348 aindex = ntohs( aindex );
349 if ( aindex ) { /* index 0 == index 1 */
353 memcpy( &bitmap, ibuf, sizeof( bitmap ));
354 bitmap = ntohs( bitmap );
355 ibuf += sizeof( bitmap );
357 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
359 return( AFPERR_NOITEM );
361 if ( aindex < sa.sdt_index ) {
362 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
364 return( AFPERR_PARAM );
369 /* position to correct spot within appl file */
371 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
372 + sizeof( u_short ))) > 0 ) {
373 p = buf + sizeof( appltag );
374 memcpy( &len, p, sizeof( len ));
376 p += sizeof( u_short );
377 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
380 if ( sa.sdt_index == aindex ) {
385 if ( cc <= 0 || sa.sdt_index != aindex ) {
387 return( AFPERR_NOITEM );
393 * Check to see if this APPL mapping has an mpath or a upath. If
394 * there are any ':'s in the name, it is a upath and must be converted
395 * to an mpath. Hopefully, this code will go away.
398 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
399 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
401 char utomname[ MAXPATHLEN + 1];
409 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
410 *(u+2) != '\0' && islxdigit( *(u+2))) {
412 h = hextoint( *u ) << 4;
425 if ( p[ len - 1 ] == '\0' ) {
429 #endif /* APPLCNAME */
431 /* fake up a cname */
434 *q++ = 2; /* long path type */
435 *q++ = (unsigned char)len;
439 if (( path = cname( vol, vol->v_dir, &q )) == NULL ) {
441 return( AFPERR_NOITEM );
444 if ( *path->m_name == '\0' || path->st_errno ) {
446 return( AFPERR_NOITEM );
448 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
449 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
450 sizeof( appltag ), &buflen ) != AFP_OK ) {
452 return( AFPERR_BITMAP );
455 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
456 bitmap = htons( bitmap );
457 memcpy( rbuf, &bitmap, sizeof( bitmap ));
458 rbuf += sizeof( bitmap );
459 memcpy( rbuf, appltag, sizeof( appltag ));
460 rbuf += sizeof( appltag );