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 return AFPERR_PARAM; 254 } 255 mplen = mpath + AFPOBJ_TMPSIZ - mp; 256 257 /* write the new appl entry at start of temporary file */ 258 p = mp - sizeof( u_short ); 259 mplen = htons( mplen ); 260 memcpy( p, &mplen, sizeof( mplen )); 261 mplen = ntohs( mplen ); 262 p -= sizeof( appltag ); 263 memcpy(p, appltag, sizeof( appltag )); 264 cc = mpath + AFPOBJ_TMPSIZ - p; 265 if ( write( tfd, p, cc ) != cc ) { 266 unlink( tempfile ); 267 return( AFPERR_PARAM ); 268 } 269 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); 270 close( tfd ); 271 close( sa.sdt_fd ); 272 sa.sdt_fd = -1; 273 274 if ( cc < 0 ) { 275 unlink( tempfile ); 276 return( AFPERR_PARAM ); 277 } 278 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { 279 return( AFPERR_PARAM ); 280 } 281 return( AFP_OK ); 282} 283 284int afp_rmvappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) 285{ 286 struct vol *vol; 287 struct dir *dir; 288 int tfd, cc; 289 u_int32_t did; 290 u_int16_t vid, mplen; 291 struct path *path; 292 char *dtf, *mp; 293 u_char creator[ 4 ]; 294 char *tempfile, *mpath; 295 296 *rbuflen = 0; 297 ibuf += 2; 298 299 memcpy( &vid, ibuf, sizeof( vid )); 300 ibuf += sizeof( vid ); 301 if (NULL == ( vol = getvolbyvid( vid ))) { 302 return( AFPERR_PARAM ); 303 } 304 305 memcpy( &did, ibuf, sizeof( did )); 306 ibuf += sizeof( did ); 307 if (NULL == ( dir = dirlookup( vol, did )) ) { 308 return afp_errno; 309 } 310 311 memcpy( creator, ibuf, sizeof( creator )); 312 ibuf += sizeof( creator ); 313 314 if (NULL == ( path = cname( vol, dir, &ibuf )) ) { 315 return get_afp_errno(AFPERR_PARAM); 316 } 317 if ( path_isadir(path) ) { 318 return( AFPERR_BADTYPE ); 319 } 320 321 if ( applopen( vol, creator, O_RDWR, 0666 ) != AFP_OK ) { 322 return( AFPERR_NOOBJ ); 323 } 324 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { 325 return( AFPERR_PARAM ); 326 } 327 dtf = dtfile( vol, creator, ".appl.temp" ); 328 tempfile = obj->oldtmp; 329 strcpy( tempfile, dtf ); 330 if (( tfd = open( tempfile, O_RDWR|O_CREAT, 0666 )) < 0 ) { 331 return( AFPERR_PARAM ); 332 } 333 mpath = obj->newtmp; 334 mp = makemacpath( vol, mpath, AFPOBJ_TMPSIZ, curdir, path->m_name ); 335 if (!mp) { 336 return AFPERR_PARAM ; 337 } 338 339 mplen = mpath + AFPOBJ_TMPSIZ - mp; 340 cc = copyapplfile( sa.sdt_fd, tfd, mp, mplen ); 341 close( tfd ); 342 close( sa.sdt_fd ); 343 sa.sdt_fd = -1; 344 345 if ( cc < 0 ) { 346 unlink( tempfile ); 347 return( AFPERR_PARAM ); 348 } 349 if ( rename( tempfile, dtfile( vol, creator, ".appl" )) < 0 ) { 350 return( AFPERR_PARAM ); 351 } 352 return( AFP_OK ); 353} 354 355int afp_getappl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) 356{ 357 struct vol *vol; 358 char *p, *q; 359 int cc; 360 size_t buflen; 361 u_int16_t vid, aindex, bitmap, len; 362 u_char creator[ 4 ]; 363 u_char appltag[ 4 ]; 364 char *buf, *cbuf; 365 struct path *path; 366 367 ibuf += 2; 368 369 memcpy( &vid, ibuf, sizeof( vid )); 370 ibuf += sizeof( vid ); 371 if (NULL == ( vol = getvolbyvid( vid )) ) { 372 *rbuflen = 0; 373 return( AFPERR_PARAM ); 374 } 375 376 memcpy( creator, ibuf, sizeof( creator )); 377 ibuf += sizeof( creator ); 378 379 memcpy( &aindex, ibuf, sizeof( aindex )); 380 ibuf += sizeof( aindex ); 381 aindex = ntohs( aindex ); 382 if ( aindex ) { /* index 0 == index 1 */ 383 --aindex; 384 } 385 386 memcpy( &bitmap, ibuf, sizeof( bitmap )); 387 bitmap = ntohs( bitmap ); 388 ibuf += sizeof( bitmap ); 389 390 if ( applopen( vol, creator, O_RDONLY, 0666 ) != AFP_OK ) { 391 *rbuflen = 0; 392 return( AFPERR_NOITEM ); 393 } 394 if ( aindex < sa.sdt_index ) { 395 if ( lseek( sa.sdt_fd, 0L, SEEK_SET ) < 0 ) { 396 *rbuflen = 0; 397 return( AFPERR_PARAM ); 398 } 399 sa.sdt_index = 0; 400 } 401 402 /* position to correct spot within appl file */ 403 buf = obj->oldtmp; 404 while (( cc = read( sa.sdt_fd, buf, sizeof( appltag ) 405 + sizeof( u_short ))) > 0 ) { 406 p = buf + sizeof( appltag ); 407 memcpy( &len, p, sizeof( len )); 408 len = ntohs( len ); 409 p += sizeof( u_short ); 410 if (( cc = read( sa.sdt_fd, p, len )) < len ) { 411 break; 412 } 413 if ( sa.sdt_index == aindex ) { 414 break; 415 } 416 sa.sdt_index++; 417 } 418 if ( cc <= 0 || sa.sdt_index != aindex ) { 419 *rbuflen = 0; 420 return( AFPERR_NOITEM ); 421 } 422 sa.sdt_index++; 423 424#ifdef APPLCNAME 425 /* 426 * Check to see if this APPL mapping has an mpath or a upath. If 427 * there are any ':'s in the name, it is a upath and must be converted 428 * to an mpath. Hopefully, this code will go away. 429 */ 430 { 431#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' ) 432#define islxdigit(x) (!isupper(x)&&isxdigit(x)) 433 434 char utomname[ MAXPATHLEN + 1]; 435 char *u, *m; 436 int i, h; 437 438 u = p; 439 m = utomname; 440 i = len; 441 while ( i ) { 442 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) && 443 *(u+2) != '\0' && islxdigit( *(u+2))) { 444 ++u, --i; 445 h = hextoint( *u ) << 4; 446 ++u, --i; 447 h |= hextoint( *u ); 448 *m++ = h; 449 } else { 450 *m++ = *u; 451 } 452 ++u, --i; 453 } 454 455 len = m - utomname; 456 p = utomname; 457 458 if ( p[ len - 1 ] == '\0' ) { 459 len--; 460 } 461 } 462#endif /* APPLCNAME */ 463 464 /* fake up a cname */ 465 cbuf = obj->newtmp; 466 q = cbuf; 467 *q++ = 2; /* long path type */ 468 *q++ = (unsigned char)len; 469 memcpy( q, p, len ); 470 q = cbuf; 471 472 if (( path = cname( vol, vol->v_root, &q )) == NULL ) { 473 *rbuflen = 0; 474 return( AFPERR_NOITEM ); 475 } 476 477 if ( path_isadir(path) || path->st_errno ) { 478 *rbuflen = 0; 479 return( AFPERR_NOITEM ); 480 } 481 buflen = *rbuflen - sizeof( bitmap ) - sizeof( appltag ); 482 if ( getfilparams(vol, bitmap, path, curdir, rbuf + sizeof( bitmap ) + 483 sizeof( appltag ), &buflen ) != AFP_OK ) { 484 *rbuflen = 0; 485 return( AFPERR_BITMAP ); 486 } 487 488 *rbuflen = buflen + sizeof( bitmap ) + sizeof( appltag ); 489 bitmap = htons( bitmap ); 490 memcpy( rbuf, &bitmap, sizeof( bitmap )); 491 rbuf += sizeof( bitmap ); 492 memcpy( rbuf, appltag, sizeof( appltag )); 493 rbuf += sizeof( appltag ); 494 return( AFP_OK ); 495} 496 497