2 * $Id: appl.c,v 1.18 2009-10-15 10:43:13 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 int pathcmp(char *p, int plen, char *q, int qlen)
34 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
37 static int applopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
39 char *dtf, *adt, *adts;
41 if ( sa.sdt_fd != -1 ) {
42 if ( !(flags & ( O_RDWR | O_WRONLY )) &&
43 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
44 sa.sdt_vid == vol->v_vid ) {
51 dtf = dtfile( vol, creator, ".appl" );
53 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
54 if ( errno == ENOENT && ( flags & O_CREAT )) {
55 if (( adts = strrchr( dtf, '/' )) == NULL ) {
56 return( AFPERR_PARAM );
59 if (( adt = strrchr( dtf, '/' )) == NULL ) {
60 return( AFPERR_PARAM );
63 (void) ad_mkdir( dtf, DIRBITS | 0777 );
65 (void) ad_mkdir( dtf, DIRBITS | 0777 );
68 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
69 return( AFPERR_PARAM );
72 return( AFPERR_PARAM );
75 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
76 sa.sdt_vid = vol->v_vid;
82 * copy appls to new file, deleting any matching (old) appl entries
84 static int copyapplfile(int sfd, int dfd, char *mpath, u_short mplen)
90 char buf[ MAXPATHLEN ];
92 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
93 p = buf + sizeof(appltag);
94 memcpy( &len, p, sizeof(len));
97 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
100 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
102 if ( write( dfd, buf, p - buf ) != p - buf ) {
112 * build mac. path (backwards) by traversing the directory tree
114 * The old way: dir and path refer to an app, path is a mac format
115 * pathname. makemacpath() builds something that looks like a cname,
116 * but uses upaths instead of mac format paths.
118 * The new way: dir and path refer to an app, path is a mac format
119 * pathname. makemacpath() builds a cname. (zero is a path separator
120 * and it's not \0 terminated).
122 * See afp_getappl() for the backward compatiblity code.
125 makemacpath(char *mpath, int mpathlen, struct dir *dir, char *path)
129 p = mpath + mpathlen;
131 memcpy( p, path, strlen( path ));
133 while ( dir->d_parent != NULL ) {
134 p -= strlen( dir->d_m_name ) + 1;
136 /* FIXME: pathname too long */
139 strcpy( p, dir->d_m_name );
146 int afp_addappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
152 u_int16_t vid, mplen;
157 char *mpath, *tempfile;
162 memcpy( &vid, ibuf, sizeof( vid ));
163 ibuf += sizeof( vid );
164 if (NULL == ( vol = getvolbyvid( vid ))) {
165 return( AFPERR_PARAM );
168 memcpy( &did, ibuf, sizeof( did ));
169 ibuf += sizeof( did );
170 if (NULL == ( dir = dirlookup( vol, did )) ) {
174 memcpy( creator, ibuf, sizeof( creator ));
175 ibuf += sizeof( creator );
177 memcpy( appltag, ibuf, sizeof( appltag ));
178 ibuf += sizeof( appltag );
180 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
181 return get_afp_errno(AFPERR_PARAM);
183 if ( path_isadir(path) ) {
184 return( AFPERR_BADTYPE );
187 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
188 return( AFPERR_PARAM );
190 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
191 return( AFPERR_PARAM );
193 dtf = dtfile( vol, creator, ".appl.temp" );
194 tempfile = obj->oldtmp;
195 strcpy( tempfile, dtf );
196 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
197 return( AFPERR_PARAM );
200 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
204 mplen = mpath + AFPOBJ_TMPSIZ - mp;
206 /* write the new appl entry at start of temporary file */
207 p = mp - sizeof( u_short );
208 mplen = htons( mplen );
209 memcpy( p, &mplen, sizeof( mplen ));
210 mplen = ntohs( mplen );
211 p -= sizeof( appltag );
212 memcpy(p, appltag, sizeof( appltag ));
213 cc = mpath + AFPOBJ_TMPSIZ - p;
214 if ( write( tfd, p, cc ) != cc ) {
216 return( AFPERR_PARAM );
218 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
225 return( AFPERR_PARAM );
227 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
228 return( AFPERR_PARAM );
233 int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
239 u_int16_t vid, mplen;
243 char *tempfile, *mpath;
248 memcpy( &vid, ibuf, sizeof( vid ));
249 ibuf += sizeof( vid );
250 if (NULL == ( vol = getvolbyvid( vid ))) {
251 return( AFPERR_PARAM );
254 memcpy( &did, ibuf, sizeof( did ));
255 ibuf += sizeof( did );
256 if (NULL == ( dir = dirlookup( vol, did )) ) {
260 memcpy( creator, ibuf, sizeof( creator ));
261 ibuf += sizeof( creator );
263 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
264 return get_afp_errno(AFPERR_PARAM);
266 if ( path_isadir(path) ) {
267 return( AFPERR_BADTYPE );
270 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
271 return( AFPERR_NOOBJ );
273 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
274 return( AFPERR_PARAM );
276 dtf = dtfile( vol, creator, ".appl.temp" );
277 tempfile = obj->oldtmp;
278 strcpy( tempfile, dtf );
279 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
280 return( AFPERR_PARAM );
283 mp = makemacpath( mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
285 return AFPERR_PARAM ;
288 mplen = mpath + AFPOBJ_TMPSIZ - mp;
289 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
296 return( AFPERR_PARAM );
298 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
299 return( AFPERR_PARAM );
304 int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
310 u_int16_t vid, aindex, bitmap, len;
318 memcpy( &vid, ibuf, sizeof( vid ));
319 ibuf += sizeof( vid );
320 if (NULL == ( vol = getvolbyvid( vid )) ) {
322 return( AFPERR_PARAM );
325 memcpy( creator, ibuf, sizeof( creator ));
326 ibuf += sizeof( creator );
328 memcpy( &aindex, ibuf, sizeof( aindex ));
329 ibuf += sizeof( aindex );
330 aindex = ntohs( aindex );
331 if ( aindex ) { /* index 0 == index 1 */
335 memcpy( &bitmap, ibuf, sizeof( bitmap ));
336 bitmap = ntohs( bitmap );
337 ibuf += sizeof( bitmap );
339 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
341 return( AFPERR_NOITEM );
343 if ( aindex < sa.sdt_index ) {
344 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
346 return( AFPERR_PARAM );
351 /* position to correct spot within appl file */
353 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
354 + sizeof( u_short ))) > 0 ) {
355 p = buf + sizeof( appltag );
356 memcpy( &len, p, sizeof( len ));
358 p += sizeof( u_short );
359 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
362 if ( sa.sdt_index == aindex ) {
367 if ( cc <= 0 || sa.sdt_index != aindex ) {
369 return( AFPERR_NOITEM );
375 * Check to see if this APPL mapping has an mpath or a upath. If
376 * there are any ':'s in the name, it is a upath and must be converted
377 * to an mpath. Hopefully, this code will go away.
380 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
381 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
383 char utomname[ MAXPATHLEN + 1];
391 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
392 *(u+2) != '\0' && islxdigit( *(u+2))) {
394 h = hextoint( *u ) << 4;
407 if ( p[ len - 1 ] == '\0' ) {
411 #endif /* APPLCNAME */
413 /* fake up a cname */
416 *q++ = 2; /* long path type */
417 *q++ = (unsigned char)len;
421 if (( path = cname( vol, vol->v_dir, &q )) == NULL ) {
423 return( AFPERR_NOITEM );
426 if ( path_isadir(path) || path->st_errno ) {
428 return( AFPERR_NOITEM );
430 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
431 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
432 sizeof( appltag ), &buflen ) != AFP_OK ) {
434 return( AFPERR_BITMAP );
437 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
438 bitmap = htons( bitmap );
439 memcpy( rbuf, &bitmap, sizeof( bitmap ));
440 rbuf += sizeof( bitmap );
441 memcpy( rbuf, appltag, sizeof( appltag ));
442 rbuf += sizeof( appltag );