2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
12 #include <sys/types.h>
14 #include <sys/param.h>
15 #include <sys/syslog.h>
18 #include <netatalk/endian.h>
19 #include <atalk/adouble.h>
20 #include <atalk/afp.h>
24 #include "directory.h"
28 static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0 };
30 static __inline__ int pathcmp( p, plen, q, qlen )
36 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
39 static int applopen( vol, creator, flags, mode )
43 char *dtf, *adt, *adts;
45 if ( sa.sdt_fd != -1 ) {
46 if ( !(flags & ( O_RDWR | O_WRONLY )) &&
47 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
48 sa.sdt_vid == vol->v_vid ) {
55 dtf = dtfile( vol, creator, ".appl" );
57 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
58 if ( errno == ENOENT && ( flags & O_CREAT )) {
59 if (( adts = strrchr( dtf, '/' )) == NULL ) {
60 return( AFPERR_PARAM );
63 if (( adt = strrchr( dtf, '/' )) == NULL ) {
64 return( AFPERR_PARAM );
67 (void) ad_mkdir( dtf, DIRBITS | 0777 );
69 (void) ad_mkdir( dtf, DIRBITS | 0777 );
72 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
73 return( AFPERR_PARAM );
76 return( AFPERR_PARAM );
79 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
80 sa.sdt_vid = vol->v_vid;
86 * copy appls to new file, deleting any matching (old) appl entries
88 static int copyapplfile( sfd, dfd, mpath, mplen )
98 char buf[ MAXPATHLEN ];
100 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
101 p = buf + sizeof(appltag);
102 memcpy( &len, p, sizeof(len));
105 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
108 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
110 if ( write( dfd, buf, p - buf ) != p - buf ) {
120 * build mac. path (backwards) by traversing the directory tree
122 * The old way: dir and path refer to an app, path is a mac format
123 * pathname. makemacpath() builds something that looks like a cname,
124 * but uses upaths instead of mac format paths.
126 * The new way: dir and path refer to an app, path is a mac format
127 * pathname. makemacpath() builds a cname.
129 * See afp_getappl() for the backward compatiblity code.
132 makemacpath( mpath, mpathlen, dir, path )
140 p = mpath + mpathlen;
142 strncpy( p, path, strlen( path ));
144 while ( dir->d_parent != NULL ) {
145 p -= strlen( dir->d_name ) + 1;
146 strcpy( p, dir->d_name );
153 int afp_addappl(obj, ibuf, ibuflen, rbuf, rbuflen )
156 int ibuflen, *rbuflen;
162 u_int16_t vid, mplen;
163 char *path, *dtf, *p, *mp;
166 char *mpath, *tempfile;
171 memcpy( &vid, ibuf, sizeof( vid ));
172 ibuf += sizeof( vid );
173 if (( vol = getvolbyvid( vid )) == NULL ) {
174 return( AFPERR_PARAM );
177 memcpy( &did, ibuf, sizeof( did ));
178 ibuf += sizeof( did );
179 if (( dir = dirsearch( vol, did )) == NULL ) {
180 return( AFPERR_NOOBJ );
183 memcpy( creator, ibuf, sizeof( creator ));
184 ibuf += sizeof( creator );
186 memcpy( appltag, ibuf, sizeof( appltag ));
187 ibuf += sizeof( appltag );
189 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
190 return( AFPERR_NOOBJ );
192 if ( *path == '\0' ) {
193 return( AFPERR_BADTYPE );
196 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
197 return( AFPERR_PARAM );
199 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
200 return( AFPERR_PARAM );
202 dtf = dtfile( vol, creator, ".appl.temp" );
203 tempfile = obj->oldtmp;
204 strcpy( tempfile, dtf );
205 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
206 return( AFPERR_PARAM );
209 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
210 mplen = mpath + AFPOBJ_TMPSIZ - mp;
212 /* write the new appl entry at start of temporary file */
213 p = mp - sizeof( u_short );
214 mplen = htons( mplen );
215 memcpy( p, &mplen, sizeof( mplen ));
216 mplen = ntohs( mplen );
217 p -= sizeof( appltag );
218 memcpy(p, appltag, sizeof( appltag ));
219 cc = mpath + AFPOBJ_TMPSIZ - p;
220 if ( write( tfd, p, cc ) != cc ) {
222 return( AFPERR_PARAM );
224 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
231 return( AFPERR_PARAM );
233 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
234 return( AFPERR_PARAM );
239 int afp_rmvappl(obj, ibuf, ibuflen, rbuf, rbuflen )
242 int ibuflen, *rbuflen;
248 u_int16_t vid, mplen;
249 char *path, *dtf, *mp;
251 char *tempfile, *mpath;
256 memcpy( &vid, ibuf, sizeof( vid ));
257 ibuf += sizeof( vid );
258 if (( vol = getvolbyvid( vid )) == NULL ) {
259 return( AFPERR_PARAM );
262 memcpy( &did, ibuf, sizeof( did ));
263 ibuf += sizeof( did );
264 if (( dir = dirsearch( vol, did )) == NULL ) {
265 return( AFPERR_NOOBJ );
268 memcpy( creator, ibuf, sizeof( creator ));
269 ibuf += sizeof( creator );
271 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
272 return( AFPERR_NOOBJ );
274 if ( *path == '.' ) {
275 return( AFPERR_BADTYPE );
278 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
279 return( AFPERR_NOOBJ );
281 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
282 return( AFPERR_PARAM );
284 dtf = dtfile( vol, creator, ".appl.temp" );
285 tempfile = obj->oldtmp;
286 strcpy( tempfile, dtf );
287 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
288 return( AFPERR_PARAM );
291 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path );
292 mplen = mpath + AFPOBJ_TMPSIZ - mp;
293 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
300 return( AFPERR_PARAM );
302 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
303 return( AFPERR_PARAM );
308 int afp_getappl(obj, ibuf, ibuflen, rbuf, rbuflen )
311 int ibuflen, *rbuflen;
317 u_int16_t vid, aindex, bitmap, len;
324 memcpy( &vid, ibuf, sizeof( vid ));
325 ibuf += sizeof( vid );
326 if (( vol = getvolbyvid( vid )) == NULL ) {
328 return( AFPERR_PARAM );
331 memcpy( creator, ibuf, sizeof( creator ));
332 ibuf += sizeof( creator );
334 memcpy( &aindex, ibuf, sizeof( aindex ));
335 ibuf += sizeof( aindex );
336 aindex = ntohs( aindex );
337 if ( aindex ) { /* index 0 == index 1 */
341 memcpy( &bitmap, ibuf, sizeof( bitmap ));
342 bitmap = ntohs( bitmap );
343 ibuf += sizeof( bitmap );
345 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
347 return( AFPERR_NOITEM );
349 if ( aindex < sa.sdt_index ) {
350 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
352 return( AFPERR_PARAM );
357 /* position to correct spot within appl file */
359 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
360 + sizeof( u_short ))) > 0 ) {
361 p = buf + sizeof( appltag );
362 memcpy( &len, p, sizeof( len ));
364 p += sizeof( u_short );
365 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
368 if ( sa.sdt_index == aindex ) {
373 if ( cc <= 0 || sa.sdt_index != aindex ) {
375 return( AFPERR_NOITEM );
381 * Check to see if this APPL mapping has an mpath or a upath. If
382 * there are any ':'s in the name, it is a upath and must be converted
383 * to an mpath. Hopefully, this code will go away.
386 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
387 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
389 char utomname[ MAXPATHLEN + 1];
397 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
398 *(u+2) != '\0' && islxdigit( *(u+2))) {
400 h = hextoint( *u ) << 4;
413 if ( p[ len - 1 ] == '\0' ) {
419 /* fake up a cname */
422 *q++ = 2; /* long path type */
423 *q++ = (unsigned char)len;
427 if (( p = cname( vol, vol->v_dir, &q )) == NULL ) {
429 return( AFPERR_NOITEM );
432 if ( stat( mtoupath(vol, p), &st ) < 0 ) {
434 return( AFPERR_NOITEM );
436 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
437 if ( getfilparams(vol, bitmap, p, curdir, &st, rbuf + sizeof( bitmap ) +
438 sizeof( appltag ), &buflen ) != AFP_OK ) {
440 return( AFPERR_BITMAP );
443 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
444 bitmap = htons( bitmap );
445 memcpy( rbuf, &bitmap, sizeof( bitmap ));
446 rbuf += sizeof( bitmap );
447 memcpy( rbuf, appltag, sizeof( appltag ));
448 rbuf += sizeof( appltag );