2 * $Id: appl.c,v 1.18.4.1 2010-02-01 10:56:08 franklahm 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>
23 #include <atalk/bstrlib.h>
24 #include <atalk/bstradd.h>
25 #include <atalk/globals.h>
26 #include <atalk/netatalk_conf.h>
29 #include "directory.h"
33 static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0, 0};
35 static int pathcmp(char *p, int plen, char *q, int qlen)
37 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 );
40 static int applopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
42 char *dtf, *adt, *adts;
44 if ( sa.sdt_fd != -1 ) {
45 if ( !(flags & ( O_RDWR | O_WRONLY )) &&
46 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
47 sa.sdt_vid == vol->v_vid ) {
54 dtf = dtfile( vol, creator, ".appl" );
56 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
57 if ( errno == ENOENT && ( flags & O_CREAT )) {
58 if (( adts = strrchr( dtf, '/' )) == NULL ) {
59 return( AFPERR_PARAM );
62 if (( adt = strrchr( dtf, '/' )) == NULL ) {
63 return( AFPERR_PARAM );
66 (void) ad_mkdir( dtf, DIRBITS | 0777 );
68 (void) ad_mkdir( dtf, DIRBITS | 0777 );
71 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
72 return( AFPERR_PARAM );
75 return( AFPERR_PARAM );
78 memcpy( sa.sdt_creator, creator, sizeof( CreatorType ));
79 sa.sdt_vid = vol->v_vid;
85 * copy appls to new file, deleting any matching (old) appl entries
87 static int copyapplfile(int sfd, int dfd, char *mpath, u_short mplen)
92 unsigned char appltag[ 4 ];
93 char buf[ MAXPATHLEN ];
95 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) {
96 p = buf + sizeof(appltag);
97 memcpy( &len, p, sizeof(len));
100 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
103 if ( pathcmp( mpath, mplen, p, len ) != 0 ) {
105 if ( write( dfd, buf, p - buf ) != p - buf ) {
115 * build mac. path (backwards) by traversing the directory tree
117 * The old way: dir and path refer to an app, path is a mac format
118 * pathname. makemacpath() builds something that looks like a cname,
119 * but uses upaths instead of mac format paths.
121 * The new way: dir and path refer to an app, path is a mac format
122 * pathname. makemacpath() builds a cname. (zero is a path separator
123 * and it's not \0 terminated).
125 * See afp_getappl() for the backward compatiblity code.
128 makemacpath(const struct vol *vol, char *mpath, int mpathlen, struct dir *dir, char *path)
132 p = mpath + mpathlen;
134 memcpy( p, path, strlen( path ));
136 while ( dir->d_did != DIRDID_ROOT ) {
137 p -= blength(dir->d_m_name) + 1;
139 /* FIXME: pathname too long */
142 memcpy(p, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1);
143 if ((dir = dirlookup(vol, dir->d_pdid)) == NULL)
150 char buffer[12 + MAXPATHLEN + 1];
151 int buflen = 12 + MAXPATHLEN + 1;
155 struct bstrList *pathlist = NULL;
156 cnid_t cnid = dir->d_pdid;
158 /* Create list for path elements, request 16 list elements for now*/
159 if ((pathlist = bstListCreateMin(16)) == NULL) {
160 LOG(log_error, logtype_afpd, "makemacpath: OOM: %s", strerror(errno));
164 while ( cnid != DIRDID_ROOT ) {
166 /* construct path, copy already found uname to path element list*/
167 if ((bstrListPush(pathlist, bfromcstr(path))) != BSTR_OK) {
168 afp_errno = AFPERR_MISC;
174 if ((uname = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL ) {
175 afp_errno = AFPERR_NOOBJ;
180 if ((path = utompath(vol, uname, cnid, utf8_encoding())) == NULL) {
181 afp_errno = AFPERR_MISC;
191 bstrListDestroy(pathlist);
198 int afp_addappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
207 unsigned char creator[ 4 ];
208 unsigned char appltag[ 4 ];
209 char *mpath, *tempfile;
214 memcpy( &vid, ibuf, sizeof( vid ));
215 ibuf += sizeof( vid );
216 if (NULL == ( vol = getvolbyvid( vid ))) {
217 return( AFPERR_PARAM );
220 memcpy( &did, ibuf, sizeof( did ));
221 ibuf += sizeof( did );
222 if (NULL == ( dir = dirlookup( vol, did )) ) {
226 memcpy( creator, ibuf, sizeof( creator ));
227 ibuf += sizeof( creator );
229 memcpy( appltag, ibuf, sizeof( appltag ));
230 ibuf += sizeof( appltag );
232 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
233 return get_afp_errno(AFPERR_PARAM);
235 if ( path_isadir(path) ) {
236 return( AFPERR_BADTYPE );
239 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) {
240 return( AFPERR_PARAM );
242 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
243 return( AFPERR_PARAM );
245 dtf = dtfile( vol, creator, ".appl.temp" );
246 tempfile = obj->oldtmp;
247 strcpy( tempfile, dtf );
248 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
249 return( AFPERR_PARAM );
252 mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
257 mplen = mpath + AFPOBJ_TMPSIZ - mp;
259 /* write the new appl entry at start of temporary file */
260 p = mp - sizeof( u_short );
261 mplen = htons( mplen );
262 memcpy( p, &mplen, sizeof( mplen ));
263 mplen = ntohs( mplen );
264 p -= sizeof( appltag );
265 memcpy(p, appltag, sizeof( appltag ));
266 cc = mpath + AFPOBJ_TMPSIZ - p;
267 if ( write( tfd, p, cc ) != cc ) {
270 return( AFPERR_PARAM );
272 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
279 return( AFPERR_PARAM );
281 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
282 return( AFPERR_PARAM );
287 int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
296 unsigned char creator[ 4 ];
297 char *tempfile, *mpath;
302 memcpy( &vid, ibuf, sizeof( vid ));
303 ibuf += sizeof( vid );
304 if (NULL == ( vol = getvolbyvid( vid ))) {
305 return( AFPERR_PARAM );
308 memcpy( &did, ibuf, sizeof( did ));
309 ibuf += sizeof( did );
310 if (NULL == ( dir = dirlookup( vol, did )) ) {
314 memcpy( creator, ibuf, sizeof( creator ));
315 ibuf += sizeof( creator );
317 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
318 return get_afp_errno(AFPERR_PARAM);
320 if ( path_isadir(path) ) {
321 return( AFPERR_BADTYPE );
324 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) {
325 return( AFPERR_NOOBJ );
327 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
328 return( AFPERR_PARAM );
330 dtf = dtfile( vol, creator, ".appl.temp" );
331 tempfile = obj->oldtmp;
332 strcpy( tempfile, dtf );
333 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) {
334 return( AFPERR_PARAM );
337 mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name );
340 return AFPERR_PARAM ;
343 mplen = mpath + AFPOBJ_TMPSIZ - mp;
344 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen );
351 return( AFPERR_PARAM );
353 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) {
354 return( AFPERR_PARAM );
359 int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
365 uint16_t vid, aindex, bitmap, len;
366 unsigned char creator[ 4 ];
367 unsigned char appltag[ 4 ];
373 memcpy( &vid, ibuf, sizeof( vid ));
374 ibuf += sizeof( vid );
375 if (NULL == ( vol = getvolbyvid( vid )) ) {
377 return( AFPERR_PARAM );
380 memcpy( creator, ibuf, sizeof( creator ));
381 ibuf += sizeof( creator );
383 memcpy( &aindex, ibuf, sizeof( aindex ));
384 ibuf += sizeof( aindex );
385 aindex = ntohs( aindex );
386 if ( aindex ) { /* index 0 == index 1 */
390 memcpy( &bitmap, ibuf, sizeof( bitmap ));
391 bitmap = ntohs( bitmap );
392 ibuf += sizeof( bitmap );
394 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) {
396 return( AFPERR_NOITEM );
398 if ( aindex < sa.sdt_index ) {
399 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) {
401 return( AFPERR_PARAM );
406 /* position to correct spot within appl file */
408 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag )
409 + sizeof( u_short ))) > 0 ) {
410 p = buf + sizeof( appltag );
411 memcpy( &len, p, sizeof( len ));
413 p += sizeof( u_short );
414 if (( cc = read( sa.sdt_fd, p, len )) < len ) {
417 if ( sa.sdt_index == aindex ) {
422 if ( cc <= 0 || sa.sdt_index != aindex ) {
424 return( AFPERR_NOITEM );
430 * Check to see if this APPL mapping has an mpath or a upath. If
431 * there are any ':'s in the name, it is a upath and must be converted
432 * to an mpath. Hopefully, this code will go away.
435 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
436 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
438 char utomname[ MAXPATHLEN + 1];
446 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
447 *(u+2) != '\0' && islxdigit( *(u+2))) {
449 h = hextoint( *u ) << 4;
462 if ( p[ len - 1 ] == '\0' ) {
466 #endif /* APPLCNAME */
468 /* fake up a cname */
471 *q++ = 2; /* long path type */
472 *q++ = (unsigned char)len;
476 if (( path = cname( vol, vol->v_root, &q )) == NULL ) {
478 return( AFPERR_NOITEM );
481 if ( path_isadir(path) || path->st_errno ) {
483 return( AFPERR_NOITEM );
485 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag );
486 if ( getfilparams(obj, vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) +
487 sizeof( appltag ), &buflen, 0) != AFP_OK ) {
489 return( AFPERR_BITMAP );
492 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag );
493 bitmap = htons( bitmap );
494 memcpy( rbuf, &bitmap, sizeof( bitmap ));
495 rbuf += sizeof( bitmap );
496 memcpy( rbuf, appltag, sizeof( appltag ));
497 rbuf += sizeof( appltag );