2 * $Id: appl.c,v 1.12.2.1.2.2.2.1 2005-02-06 10:16:00 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, 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 )
47 char *dtf, *adt, *adts;
49 if ( sa.sdt_fd != -1 ) {
50 if ( !(flags & ( O_RDWR | O_WRONLY )) &&
51 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
52 sa.sdt_vid == vol->v_vid ) {
59 dtf = dtfile( vol, creator, ".appl" );
61 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
62 if ( errno == ENOENT && ( flags & O_CREAT )) {
63 if (( adts = strrchr( dtf, '/' )) == NULL ) {
64 return( AFPERR_PARAM );
67 if (( adt = strrchr( dtf, '/' )) == NULL ) {
68 return( AFPERR_PARAM );
71 (void) ad_mkdir( dtf, DIRBITS | 0777 );
73 (void) ad_mkdir( dtf, DIRBITS | 0777 );
76 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
77 return( AFPERR_PARAM );
80 return( AFPERR_PARAM );
83 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
84 sa.sdt_vid = vol->v_vid;
90 * copy appls to new file, deleting any matching (old) appl entries
92 static int copyapplfile( sfd, dfd, mpath, mplen )
102 char buf[ MAXPATHLEN ];
104 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
105 p = buf + sizeof(appltag);
106 memcpy( &len, p, sizeof(len));
109 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
112 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
114 if ( write( dfd, buf, p - buf ) != p - buf ) {
124 * build mac. path (backwards) by traversing the directory tree
126 * The old way: dir and path refer to an app, path is a mac format
127 * pathname. makemacpath() builds something that looks like a cname,
128 * but uses upaths instead of mac format paths.
130 * The new way: dir and path refer to an app, path is a mac format
131 * pathname. makemacpath() builds a cname. (zero is a path separator
132 * and it's not \0 terminated).
134 * See afp_getappl() for the backward compatiblity code.
137 makemacpath( mpath, mpathlen, dir, path )
145 p = mpath + mpathlen;
147 memcpy( p, path, strlen( path ));
149 while ( dir->d_parent != NULL ) {
150 p -= strlen( dir->d_m_name ) + 1;
152 /* FIXME: pathname too long */
155 strcpy( p, dir->d_m_name );
162 int afp_addappl(obj, ibuf, ibuflen, rbuf, rbuflen )
165 int ibuflen, *rbuflen;
171 u_int16_t vid, mplen;
176 char *mpath, *tempfile;
181 memcpy( &vid, ibuf, sizeof( vid ));
182 ibuf += sizeof( vid );
183 if (NULL == ( vol = getvolbyvid( vid ))) {
184 return( AFPERR_PARAM );
187 memcpy( &did, ibuf, sizeof( did ));
188 ibuf += sizeof( did );
189 if (NULL == ( dir = dirlookup( vol, did )) ) {
193 memcpy( creator, ibuf, sizeof( creator ));
194 ibuf += sizeof( creator );
196 memcpy( appltag, ibuf, sizeof( appltag ));
197 ibuf += sizeof( appltag );
199 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
200 return get_afp_errno(AFPERR_PARAM);
202 if ( path_isadir(path) ) {
203 return( AFPERR_BADTYPE );
206 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
207 return( AFPERR_PARAM );
209 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
210 return( AFPERR_PARAM );
212 dtf = dtfile( vol, creator, ".appl.temp" );
213 tempfile = obj->oldtmp;
214 strcpy( tempfile, dtf );
215 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
216 return( AFPERR_PARAM );
219 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
223 mplen = mpath + AFPOBJ_TMPSIZ - mp;
225 /* write the new appl entry at start of temporary file */
226 p = mp - sizeof( u_short );
227 mplen = htons( mplen );
228 memcpy( p, &mplen, sizeof( mplen ));
229 mplen = ntohs( mplen );
230 p -= sizeof( appltag );
231 memcpy(p, appltag, sizeof( appltag ));
232 cc = mpath + AFPOBJ_TMPSIZ - p;
233 if ( write( tfd, p, cc ) != cc ) {
235 return( AFPERR_PARAM );
237 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
244 return( AFPERR_PARAM );
246 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
247 return( AFPERR_PARAM );
252 int afp_rmvappl(obj, ibuf, ibuflen, rbuf, rbuflen )
255 int ibuflen, *rbuflen;
261 u_int16_t vid, mplen;
265 char *tempfile, *mpath;
270 memcpy( &vid, ibuf, sizeof( vid ));
271 ibuf += sizeof( vid );
272 if (NULL == ( vol = getvolbyvid( vid ))) {
273 return( AFPERR_PARAM );
276 memcpy( &did, ibuf, sizeof( did ));
277 ibuf += sizeof( did );
278 if (NULL == ( dir = dirlookup( vol, did )) ) {
282 memcpy( creator, ibuf, sizeof( creator ));
283 ibuf += sizeof( creator );
285 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
286 return get_afp_errno(AFPERR_PARAM);
288 if ( path_isadir(path) ) {
289 return( AFPERR_BADTYPE );
292 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
293 return( AFPERR_NOOBJ );
295 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
296 return( AFPERR_PARAM );
298 dtf = dtfile( vol, creator, ".appl.temp" );
299 tempfile = obj->oldtmp;
300 strcpy( tempfile, dtf );
301 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
302 return( AFPERR_PARAM );
305 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
307 return AFPERR_PARAM ;
310 mplen = mpath + AFPOBJ_TMPSIZ - mp;
311 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
318 return( AFPERR_PARAM );
320 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
321 return( AFPERR_PARAM );
326 int afp_getappl(obj, ibuf, ibuflen, rbuf, rbuflen )
329 int ibuflen, *rbuflen;
334 u_int16_t vid, aindex, bitmap, len;
342 memcpy( &vid, ibuf, sizeof( vid ));
343 ibuf += sizeof( vid );
344 if (NULL == ( vol = getvolbyvid( vid )) ) {
346 return( AFPERR_PARAM );
349 memcpy( creator, ibuf, sizeof( creator ));
350 ibuf += sizeof( creator );
352 memcpy( &aindex, ibuf, sizeof( aindex ));
353 ibuf += sizeof( aindex );
354 aindex = ntohs( aindex );
355 if ( aindex ) { /* index 0 == index 1 */
359 memcpy( &bitmap, ibuf, sizeof( bitmap ));
360 bitmap = ntohs( bitmap );
361 ibuf += sizeof( bitmap );
363 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
365 return( AFPERR_NOITEM );
367 if ( aindex < sa.sdt_index ) {
368 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
370 return( AFPERR_PARAM );
375 /* position to correct spot within appl file */
377 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
378 + sizeof( u_short ))) > 0 ) {
379 p = buf + sizeof( appltag );
380 memcpy( &len, p, sizeof( len ));
382 p += sizeof( u_short );
383 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
386 if ( sa.sdt_index == aindex ) {
391 if ( cc <= 0 || sa.sdt_index != aindex ) {
393 return( AFPERR_NOITEM );
399 * Check to see if this APPL mapping has an mpath or a upath. If
400 * there are any ':'s in the name, it is a upath and must be converted
401 * to an mpath. Hopefully, this code will go away.
404 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
405 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
407 char utomname[ MAXPATHLEN + 1];
415 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
416 *(u+2) != '\0' && islxdigit( *(u+2))) {
418 h = hextoint( *u ) << 4;
431 if ( p[ len - 1 ] == '\0' ) {
435 #endif /* APPLCNAME */
437 /* fake up a cname */
440 *q++ = 2; /* long path type */
441 *q++ = (unsigned char)len;
445 if (( path = cname( vol, vol->v_dir, &q )) == NULL ) {
447 return( AFPERR_NOITEM );
450 if ( path_isadir(path) || path->st_errno ) {
452 return( AFPERR_NOITEM );
454 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
455 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
456 sizeof( appltag ), &buflen ) != AFP_OK ) {
458 return( AFPERR_BITMAP );
461 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
462 bitmap = htons( bitmap );
463 memcpy( rbuf, &bitmap, sizeof( bitmap ));
464 rbuf += sizeof( bitmap );
465 memcpy( rbuf, appltag, sizeof( appltag ));
466 rbuf += sizeof( appltag );