1/* 2 * $Id: appl.c,v 1.18.4.1 2010-02-01 10:56:08 franklahm Exp $ 3 * 4 * Copyright (c) 1990,1993 Regents of The University of Michigan. 5 * All Rights Reserved. See COPYRIGHT. 6 */ 7 8#ifdef HAVE_CONFIG_H 9#include "config.h" 10#endif /* HAVE_CONFIG_H */ 11 12#include <stdio.h> 13#include <stdlib.h> 14#include <string.h> 15#include <ctype.h> 16 17#include <sys/param.h> 18#include <atalk/logger.h> 19#include <errno.h> 20 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 27#include "volume.h" 28#include "directory.h" 29#include "file.h" 30#include "desktop.h" 31 32static struct savedt sa = { { 0, 0, 0, 0 }, -1, 0, 0}; 33 34static int pathcmp(char *p, int plen, char *q, int qlen) 35{ 36 return (( plen == qlen && memcmp( p, q, plen ) == 0 ) ? 0 : 1 ); 37} 38 39static int applopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode) 40{ 41 char *dtf, *adt, *adts; 42 43 if ( sa.sdt_fd != -1 ) { 44 if ( !(flags & ( O_RDWR | O_WRONLY )) && 45 memcmp( sa.sdt_creator, creator, sizeof( CreatorType )) == 0 && 46 sa.sdt_vid == vol->v_vid ) { 47 return( AFP_OK ); 48 } 49 close( sa.sdt_fd ); 50 sa.sdt_fd = -1; 51 } 52 53 dtf = dtfile( vol, creator, ".appl" ); 54 55 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { 56 if ( errno == ENOENT && ( flags & O_CREAT )) { 57 if (( adts = strrchr( dtf, '/' )) == NULL ) { 58 return( AFPERR_PARAM ); 59 } 60 *adts = '\0'; 61 if (( adt = strrchr( dtf, '/' )) == NULL ) { 62 return( AFPERR_PARAM ); 63 } 64 *adt = '\0'; 65 (void) ad_mkdir( dtf, DIRBITS | 0777 ); 66 *adt = '/'; 67 (void) ad_mkdir( dtf, DIRBITS | 0777 ); 68 *adts = '/'; 69 70 if (( sa.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) { 71 return( AFPERR_PARAM ); 72 } 73 } else { 74 return( AFPERR_PARAM ); 75 } 76 } 77 memcpy( sa.sdt_creator, creator, sizeof( CreatorType )); 78 sa.sdt_vid = vol->v_vid; 79 sa.sdt_index = 0; 80 return( AFP_OK ); 81} 82 83/* 84 * copy appls to new file, deleting any matching (old) appl entries 85 */ 86static int copyapplfile(int sfd, int dfd, char *mpath, u_short mplen) 87{ 88 int cc; 89 char *p; 90 u_int16_t len; 91 u_char appltag[ 4 ]; 92 char buf[ MAXPATHLEN ]; 93 94 while (( cc = read( sfd, buf, sizeof(appltag) + sizeof( u_short ))) > 0 ) { 95 p = buf + sizeof(appltag); 96 memcpy( &len, p, sizeof(len)); 97 len = ntohs( len ); 98 p += sizeof( len ); 99 if (( cc = read( sa.sdt_fd, p, len )) < len ) { 100 break; 101 } 102 if ( pathcmp( mpath, mplen, p, len ) != 0 ) { 103 p += len; 104 if ( write( dfd, buf, p - buf ) != p - buf ) { 105 cc = -1; 106 break; 107 } 108 } 109 } 110 return( cc ); 111} 112 113/* 114 * build mac. path (backwards) by traversing the directory tree 115 * 116 * The old way: dir and path refer to an app, path is a mac format 117 * pathname. makemacpath() builds something that looks like a cname, 118 * but uses upaths instead of mac format paths. 119 * 120 * The new way: dir and path refer to an app, path is a mac format 121 * pathname. makemacpath() builds a cname. (zero is a path separator 122 * and it's not \0 terminated). 123 * 124 * See afp_getappl() for the backward compatiblity code. 125 */ 126static char * 127makemacpath(const struct vol *vol, char *mpath, int mpathlen, struct dir *dir, char *path) 128{ 129 char *p; 130 131 p = mpath + mpathlen; 132 p -= strlen( path ); 133 memcpy( p, path, strlen( path )); 134 135 while ( dir->d_did != DIRDID_ROOT ) { 136 p -= blength(dir->d_m_name) + 1; 137 if (p < mpath) { 138 /* FIXME: pathname too long */ 139 return NULL; 140 } 141 memcpy(p, cfrombstr(dir->d_m_name), blength(dir->d_m_name) + 1); 142 if ((dir = dirlookup(vol, dir->d_pdid)) == NULL) 143 return NULL; 144 } 145 return( p ); 146 147 148#if 0 149 char buffer[12 + MAXPATHLEN + 1]; 150 int buflen = 12 + MAXPATHLEN + 1; 151 char *ret = mpath; 152 char *path = name; 153 char *uname = NULL; 154 struct bstrList *pathlist = NULL; 155 cnid_t cnid = dir->d_pdid; 156 157 /* Create list for path elements, request 16 list elements for now*/ 158 if ((pathlist = bstListCreateMin(16)) == NULL) { 159 LOG(log_error, logtype_afpd, "makemacpath: OOM: %s", strerror(errno)); 160 return NULL; 161 } 162 163 while ( cnid != DIRDID_ROOT ) { 164 165 /* construct path, copy already found uname to path element list*/ 166 if ((bstrListPush(pathlist, bfromcstr(path))) != BSTR_OK) { 167 afp_errno = AFPERR_MISC; 168 ret = NULL; 169 goto exit; 170 } 171 172 /* next part */ 173 if ((uname = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL ) { 174 afp_errno = AFPERR_NOOBJ; 175 ret = NULL; 176 goto exit; 177 } 178 179 if ((path = utompath(vol, uname, cnid, utf8_encoding())) == NULL) { 180 afp_errno = AFPERR_MISC; 181 ret = NULL; 182 goto exit; 183 } 184 } 185 186 187 188exit: 189 if (pathlist) 190 bstrListDestroy(pathlist); 191 192 return(ret); 193#endif 194} 195 196 197int afp_addappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 198{ 199 struct vol *vol; 200 struct dir *dir; 201 int tfd, cc; 202 u_int32_t did; 203 u_int16_t vid, mplen; 204 struct path *path; 205 char *dtf, *p, *mp; 206 u_char creator[ 4 ]; 207 u_char appltag[ 4 ]; 208 char *mpath, *tempfile; 209 210 *rbuflen = 0; 211 ibuf += 2; 212 213 memcpy( &vid, ibuf, sizeof( vid )); 214 ibuf += sizeof( vid ); 215 if (NULL == ( vol = getvolbyvid( vid ))) { 216 return( AFPERR_PARAM ); 217 } 218 219 memcpy( &did, ibuf, sizeof( did )); 220 ibuf += sizeof( did ); 221 if (NULL == ( dir = dirlookup( vol, did )) ) { 222 return afp_errno; 223 } 224 225 memcpy( creator, ibuf, sizeof( creator )); 226 ibuf += sizeof( creator ); 227 228 memcpy( appltag, ibuf, sizeof( appltag )); 229 ibuf += sizeof( appltag ); 230 231 if (NULL == ( path = cname( vol, dir, &ibuf )) ) { 232 return get_afp_errno(AFPERR_PARAM); 233 } 234 if ( path_isadir(path) ) { 235 return( AFPERR_BADTYPE ); 236 } 237 238 if ( applopen( vol, creator, O_RDWR|O_CREAT, 0666 ) != AFP_OK ) { 239 return( AFPERR_PARAM ); 240 } 241 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { 242 return( AFPERR_PARAM ); 243 } 244 dtf = dtfile( vol, creator, ".appl.temp" ); 245 tempfile = obj->oldtmp; 246 strcpy( tempfile, dtf ); 247 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) { 248 return( AFPERR_PARAM ); 249 } 250 mpath = obj->newtmp; 251 mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name ); 252 if (!mp) { 253 close(tfd); 254 return AFPERR_PARAM; 255 } 256 mplen = mpath + AFPOBJ_TMPSIZ - mp; 257 258 /* write the new appl entry at start of temporary file */ 259 p = mp - sizeof( u_short ); 260 mplen = htons( mplen ); 261 memcpy( p, &mplen, sizeof( mplen )); 262 mplen = ntohs( mplen ); 263 p -= sizeof( appltag ); 264 memcpy(p, appltag, sizeof( appltag )); 265 cc = mpath + AFPOBJ_TMPSIZ - p; 266 if ( write( tfd, p, cc ) != cc ) { 267 close(tfd); 268 unlink( tempfile ); 269 return( AFPERR_PARAM ); 270 } 271 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); 272 close( tfd ); 273 close( sa.sdt_fd ); 274 sa.sdt_fd = -1; 275 276 if ( cc < 0 ) { 277 unlink( tempfile ); 278 return( AFPERR_PARAM ); 279 } 280 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { 281 return( AFPERR_PARAM ); 282 } 283 return( AFP_OK ); 284} 285 286int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 287{ 288 struct vol *vol; 289 struct dir *dir; 290 int tfd, cc; 291 u_int32_t did; 292 u_int16_t vid, mplen; 293 struct path *path; 294 char *dtf, *mp; 295 u_char creator[ 4 ]; 296 char *tempfile, *mpath; 297 298 *rbuflen = 0; 299 ibuf += 2; 300 301 memcpy( &vid, ibuf, sizeof( vid )); 302 ibuf += sizeof( vid ); 303 if (NULL == ( vol = getvolbyvid( vid ))) { 304 return( AFPERR_PARAM ); 305 } 306 307 memcpy( &did, ibuf, sizeof( did )); 308 ibuf += sizeof( did ); 309 if (NULL == ( dir = dirlookup( vol, did )) ) { 310 return afp_errno; 311 } 312 313 memcpy( creator, ibuf, sizeof( creator )); 314 ibuf += sizeof( creator ); 315 316 if (NULL == ( path = cname( vol, dir, &ibuf )) ) { 317 return get_afp_errno(AFPERR_PARAM); 318 } 319 if ( path_isadir(path) ) { 320 return( AFPERR_BADTYPE ); 321 } 322 323 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) { 324 return( AFPERR_NOOBJ ); 325 } 326 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { 327 return( AFPERR_PARAM ); 328 } 329 dtf = dtfile( vol, creator, ".appl.temp" ); 330 tempfile = obj->oldtmp; 331 strcpy( tempfile, dtf ); 332 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) { 333 return( AFPERR_PARAM ); 334 } 335 mpath = obj->newtmp; 336 mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name ); 337 if (!mp) { 338 close(tfd); 339 return AFPERR_PARAM ; 340 } 341 342 mplen = mpath + AFPOBJ_TMPSIZ - mp; 343 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); 344 close( tfd ); 345 close( sa.sdt_fd ); 346 sa.sdt_fd = -1; 347 348 if ( cc < 0 ) { 349 unlink( tempfile ); 350 return( AFPERR_PARAM ); 351 } 352 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { 353 return( AFPERR_PARAM ); 354 } 355 return( AFP_OK ); 356} 357 358int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) 359{ 360 struct vol *vol; 361 char *p, *q; 362 int cc; 363 size_t buflen; 364 u_int16_t vid, aindex, bitmap, len; 365 u_char creator[ 4 ]; 366 u_char appltag[ 4 ]; 367 char *buf, *cbuf; 368 struct path *path; 369 370 ibuf += 2; 371 372 memcpy( &vid, ibuf, sizeof( vid )); 373 ibuf += sizeof( vid ); 374 if (NULL == ( vol = getvolbyvid( vid )) ) { 375 *rbuflen = 0; 376 return( AFPERR_PARAM ); 377 } 378 379 memcpy( creator, ibuf, sizeof( creator )); 380 ibuf += sizeof( creator ); 381 382 memcpy( &aindex, ibuf, sizeof( aindex )); 383 ibuf += sizeof( aindex ); 384 aindex = ntohs( aindex ); 385 if ( aindex ) { /* index 0 == index 1 */ 386 --aindex; 387 } 388 389 memcpy( &bitmap, ibuf, sizeof( bitmap )); 390 bitmap = ntohs( bitmap ); 391 ibuf += sizeof( bitmap ); 392 393 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) { 394 *rbuflen = 0; 395 return( AFPERR_NOITEM ); 396 } 397 if ( aindex < sa.sdt_index ) { 398 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { 399 *rbuflen = 0; 400 return( AFPERR_PARAM ); 401 } 402 sa.sdt_index = 0; 403 } 404 405 /* position to correct spot within appl file */ 406 buf = obj->oldtmp; 407 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag ) 408 + sizeof( u_short ))) > 0 ) { 409 p = buf + sizeof( appltag ); 410 memcpy( &len, p, sizeof( len )); 411 len = ntohs( len ); 412 p += sizeof( u_short ); 413 if (( cc = read( sa.sdt_fd, p, len )) < len ) { 414 break; 415 } 416 if ( sa.sdt_index == aindex ) { 417 break; 418 } 419 sa.sdt_index++; 420 } 421 if ( cc <= 0 || sa.sdt_index != aindex ) { 422 *rbuflen = 0; 423 return( AFPERR_NOITEM ); 424 } 425 sa.sdt_index++; 426 427#ifdef APPLCNAME 428 /* 429 * Check to see if this APPL mapping has an mpath or a upath. If 430 * there are any ':'s in the name, it is a upath and must be converted 431 * to an mpath. Hopefully, this code will go away. 432 */ 433 { 434#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' ) 435#define islxdigit(x) (!isupper(x)&&isxdigit(x)) 436 437 char utomname[ MAXPATHLEN + 1]; 438 char *u, *m; 439 int i, h; 440 441 u = p; 442 m = utomname; 443 i = len; 444 while ( i ) { 445 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) && 446 *(u+2) != '\0' && islxdigit( *(u+2))) { 447 ++u, --i; 448 h = hextoint( *u ) << 4; 449 ++u, --i; 450 h |= hextoint( *u ); 451 *m++ = h; 452 } else { 453 *m++ = *u; 454 } 455 ++u, --i; 456 } 457 458 len = m - utomname; 459 p = utomname; 460 461 if ( p[ len - 1 ] == '\0' ) { 462 len--; 463 } 464 } 465#endif /* APPLCNAME */ 466 467 /* fake up a cname */ 468 cbuf = obj->newtmp; 469 q = cbuf; 470 *q++ = 2; /* long path type */ 471 *q++ = (unsigned char)len; 472 memcpy( q, p, len ); 473 q = cbuf; 474 475 if (( path = cname( vol, vol->v_root, &q )) == NULL ) { 476 *rbuflen = 0; 477 return( AFPERR_NOITEM ); 478 } 479 480 if ( path_isadir(path) || path->st_errno ) { 481 *rbuflen = 0; 482 return( AFPERR_NOITEM ); 483 } 484 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag ); 485 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) + 486 sizeof( appltag ), &buflen ) != AFP_OK ) { 487 *rbuflen = 0; 488 return( AFPERR_BITMAP ); 489 } 490 491 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag ); 492 bitmap = htons( bitmap ); 493 memcpy( rbuf, &bitmap, sizeof( bitmap )); 494 rbuf += sizeof( bitmap ); 495 memcpy( rbuf, appltag, sizeof( appltag )); 496 rbuf += sizeof( appltag ); 497 return( AFP_OK ); 498} 499 500