--- etc/afpd/volume.c.orig Tue Mar 31 02:57:11 1998 +++ etc/afpd/volume.c Wed Nov 24 15:09:21 1999 @@ -16,10 +16,13 @@ #include #include #include +#include #include -#include +#include #include +#include +#include "unix.h" #include "directory.h" #include "file.h" #include "volume.h" @@ -30,6 +33,14 @@ char *Trash = "\02\024Network Trash Folder"; struct extmap *extmap = NULL, *defextmap = NULL; +void creatvol(), setextmap(), freedir(); +int readvolfile(); +int initline(), parseline(); +int getvolparams(); + +int strdiacasecmp(); + +void initvolumes() { struct passwd *pwent; @@ -69,6 +80,7 @@ return; } +int afp_getsrvrparms( ibuf, ibuflen, rbuf, rbuflen ) char *ibuf, *rbuf; int ibuflen, *rbuflen; @@ -76,9 +88,9 @@ struct timeval tv; struct stat st; struct vol *volume; - struct passwd *pwent; char *data; int vcnt, len; + u_int32_t secs; initvolumes(); @@ -91,11 +103,20 @@ if (( st.st_mode & S_IFDIR ) == 0 ) { continue; /* not a dir */ } - + + /* Apple 2 clients running ProDOS-8 expect one volume to have + bit 0 of this byte set. They will not recognize anything + on the server unless this is the case. I have not + completely worked this out, but it's related to booting + from the server. Support for that function is a ways + off.. */ + if ( volume->v_flags & AFPVOL_A2VOL ) + *data++ = (u_char) 1; + else *data++ = 0; len = strlen( volume->v_name ); *data++ = len; - bcopy( volume->v_name, data, len ); + memcpy( data, volume->v_name, len ); data += len; vcnt++; } @@ -106,21 +127,27 @@ syslog( LOG_ERR, "afp_getsrvrparms: gettimeofday: %m" ); exit( 1 ); } - tv.tv_sec = htonl( tv.tv_sec ); - bcopy( &tv.tv_sec, data, sizeof( tv.tv_sec )); - data += sizeof( tv.tv_sec ); + secs = tv.tv_sec; + secs = htonl( secs ); + memcpy( data, &secs, sizeof( secs )); + data += sizeof( secs ); *data = vcnt; return( AFP_OK ); } -creatvol( path, name ) + /* Allow volume-specific flag setting to be passed in on mount. Not + specific to P8; this will be needed for parameter support from the + Applevolumes file. */ +void +creatvol( path, name, flags ) char *path, *name; + int flags; { struct vol *volume; - int vlen; + size_t vlen, len; if ( name == NULL || *name == '\0' ) { - if (( name = rindex( path, '/' )) == NULL ) { + if (( name = strrchr( path, '/' )) == NULL ) { return; /* Obviously not a fully qualified path */ } name++; @@ -147,18 +174,21 @@ syslog( LOG_ERR, "creatvol: malloc: %m" ); exit( 1 ); } + len = (strlen( path ) + 1); if (( volume->v_path = - (char *)malloc( strlen( path ) + 1 )) == NULL ) { + (char *)malloc( len )) == NULL ) { syslog( LOG_ERR, "creatvol: malloc: %m" ); exit( 1 ); } - strcpy( volume->v_name, name ); - strcpy( volume->v_path, path ); + (void)strlcpy( volume->v_name, name, (vlen + 1) ); + (void)strlcpy( volume->v_path, path, len ); volume->v_dir = NULL; volume->v_did = NULL; - volume->v_flags = 0; + + /* Start with flag settings parsed from AppleVolumes */ + volume->v_flags = flags; #ifdef __svr4__ volume->v_qfd = -1; #else __svr4__ @@ -209,6 +239,7 @@ * [ [,...]] * TYPE [CREATOR] */ +int readvolfile( p1, p2, user ) char *p1, *p2; int user; @@ -218,13 +249,13 @@ volname[ 28 ], buf[ BUFSIZ ], type[ 5 ], creator[ 5 ]; char *u, *p; - int quoted = 0; struct passwd *pw; + int flags; - strcpy( path, p1 ); + (void)strlcpy( path, p1, sizeof(path) ); if ( p2 != NULL ) { - strcat( path, "/" ); - strcat( path, p2 ); + (void)strlcat( path, "/", sizeof(path) ); + (void)strlcat( path, p2, sizeof(path) ); } if (( fp = fopen( path, "r" )) == NULL ) { @@ -240,7 +271,7 @@ continue; case '~' : - if (( p = index( path, '/' )) != NULL ) { + if (( p = strchr( path, '/' )) != NULL ) { *p++ = '\0'; } u = path; @@ -251,17 +282,24 @@ if ( u == NULL || ( pw = getpwnam( u )) == NULL ) { continue; } - strcpy( tmp, pw->pw_dir ); + (void)strlcpy( tmp, pw->pw_dir, sizeof(tmp) ); if ( p != NULL && *p != '\0' ) { - strcat( tmp, "/" ); - strcat( tmp, p ); + (void)strlcat( tmp, "/", sizeof(tmp) ); + (void)strlcat( tmp, p, sizeof(tmp) ); } - strcpy( path, tmp ); + (void)strlcpy( path, tmp, sizeof(path) ); /* fall through */ case '/' : parseline( sizeof( volname ) - 1, volname ); - creatvol( path, volname ); + + /* FIXME!! Real crude and quick way to grab a + user-supplied integer in [0..3] and shift it into the + ProDOS bits of the volume flag. Obviously some room + for improvement here. */ + parseline( sizeof( tmp ) - 1, tmp ); + flags = ( atoi ( tmp ) & 3 ) << 5; + creatvol( path, volname, flags ); break; case '.' : @@ -280,6 +318,7 @@ return( 0 ); } +void setextmap( ext, type, creator, user ) char *ext, *type, *creator; int user; @@ -304,17 +343,17 @@ return; } - strcpy( em->em_ext, ext ); + (void)strlcpy( em->em_ext, ext, sizeof(em->em_ext) ); if ( *type == '\0' ) { - bcopy( "????", em->em_type, sizeof( em->em_type )); + memcpy( em->em_type, "????", sizeof( em->em_type )); } else { - bcopy( type, em->em_type, sizeof( em->em_type )); + memcpy( em->em_type, type, sizeof( em->em_type )); } if ( *creator == '\0' ) { - bcopy( "UNIX", em->em_creator, sizeof( em->em_creator )); + memcpy( em->em_creator, "UNIX", sizeof( em->em_creator )); } else { - bcopy( creator, em->em_creator, sizeof( em->em_creator )); + memcpy( em->em_creator, creator, sizeof( em->em_creator )); } if ( strcmp( ext, "." ) == 0 ) { @@ -329,7 +368,7 @@ char *p; struct extmap *em; - if (( p = rindex( path, '.' )) == NULL ) { + if (( p = strrchr( path, '.' )) == NULL ) { return( defextmap ); } @@ -345,6 +384,7 @@ } } +int afp_openvol( ibuf, ibuflen, rbuf, rbuflen ) char *ibuf, *rbuf; int ibuflen, *rbuflen; @@ -354,19 +394,20 @@ struct vol *volume; struct dir *dir; int len, ret, buflen; - u_short bitmap; + u_int16_t bitmap; + size_t dlen; ibuf += 2; - bcopy( ibuf, &bitmap, sizeof( u_short )); + memcpy( &bitmap, ibuf, sizeof( bitmap )); bitmap = ntohs( bitmap ); - ibuf += sizeof( u_short ); + ibuf += sizeof( bitmap ); if (( bitmap & (1<d_balance = 0; dir->d_did = htonl( 2 ); dir->d_flags = 0; - if (( dir->d_name = (char *)malloc( strlen( volume->v_name ) + 1 )) + dlen = (strlen( volume->v_name ) + 1); + if (( dir->d_name = (char *)malloc( dlen )) == NULL ) { syslog( LOG_ERR, "afp_openvol: malloc: %m" ); exit( 1 ); } - strcpy( dir->d_name, volume->v_name ); + (void)strlcpy( dir->d_name, volume->v_name, dlen ); volume->v_dir = dir; volume->v_did = dir; volume->v_flags |= AFPVOL_OPEN; @@ -410,15 +452,15 @@ return( AFPERR_PARAM ); } - buflen = *rbuflen - sizeof( u_short ); + buflen = *rbuflen - sizeof( bitmap ); if (( ret = getvolparams( bitmap, volume, &st, - rbuf + sizeof( u_short ), &buflen )) != AFP_OK ) { + rbuf + sizeof( bitmap ), &buflen )) != AFP_OK ) { *rbuflen = 0; return( ret ); } - *rbuflen = buflen + sizeof( u_short ); + *rbuflen = buflen + sizeof( bitmap ); bitmap = htons( bitmap ); - bcopy( &bitmap, rbuf, sizeof( u_short )); + memcpy( rbuf, &bitmap, sizeof( bitmap )); /* * If you mount a volume twice, the second time the trash appears on @@ -438,16 +480,17 @@ return( AFP_OK ); } +int afp_closevol( ibuf, ibuflen, rbuf, rbuflen ) char *ibuf, *rbuf; int ibuflen, *rbuflen; { struct vol *vol, *ovol; - u_short vid; + u_int16_t vid; *rbuflen = 0; ibuf += 2; - bcopy( ibuf, &vid, sizeof( u_short )); + memcpy( &vid, ibuf, sizeof( vid )); if (( vol = getvolbyvid( vid )) == NULL ) { return( AFPERR_PARAM ); } @@ -471,6 +514,7 @@ return( AFP_OK ); } +void freedir( dir ) struct dir *dir; { @@ -484,6 +528,7 @@ free( dir ); } +int afp_getvolparams( ibuf, ibuflen, rbuf, rbuflen ) char *ibuf, *rbuf; int ibuflen, *rbuflen; @@ -491,12 +536,12 @@ struct stat st; struct vol *vol; int buflen, ret; - u_short vid, bitmap; + u_int16_t vid, bitmap; ibuf += 2; - bcopy( ibuf, &vid, sizeof( u_short )); - ibuf += sizeof( u_short ); - bcopy( ibuf, &bitmap, sizeof( u_short )); + memcpy( &vid, ibuf, sizeof( vid )); + ibuf += sizeof( vid ); + memcpy( &bitmap, ibuf, sizeof( bitmap )); bitmap = ntohs( bitmap ); if (( vol = getvolbyvid( vid )) == NULL ) { @@ -509,24 +554,25 @@ return( AFPERR_PARAM ); } - buflen = *rbuflen - sizeof( u_short ); + buflen = *rbuflen - sizeof( bitmap ); if (( ret = getvolparams( bitmap, vol, &st, - rbuf + sizeof( u_short ), &buflen )) != AFP_OK ) { + rbuf + sizeof( bitmap ), &buflen )) != AFP_OK ) { *rbuflen = 0; return( ret ); } - *rbuflen = buflen + sizeof( u_short ); + *rbuflen = buflen + sizeof( bitmap ); bitmap = htons( bitmap ); - bcopy( &bitmap, rbuf, sizeof( u_short )); + memcpy( rbuf, &bitmap, sizeof( bitmap )); return( AFP_OK ); } +int getvolspace( vol, bfree, btotal ) struct vol *vol; - u_long *bfree, *btotal; + u_int32_t *bfree, *btotal; { int spaceflag, rc; - u_long qfree, qtotal; + u_int32_t qfree, qtotal; spaceflag = AFPVOL_GVSMASK & vol->v_flags; @@ -555,14 +601,26 @@ } #endif linux - *bfree = min( *bfree, 0x7fffffff ); - *btotal = min( *btotal, 0x7fffffff ); + /* If this is designated as a ProDOS-8 volume, make sure to avoid + wrap-around by capping reported free space under 64k blocks. */ + if ( vol->v_flags & AFPVOL_A2VOL ) + { + *bfree = min( *bfree, 0x01fffe00 ); + *btotal = min( *btotal, 0x01fffe00 ); + } + else + { + *bfree = min( *bfree, 0x7fffffff ); + *btotal = min( *btotal, 0x7fffffff ); + } + vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_USTATFS; return( AFP_OK ); } +int getvolparams( bitmap, vol, st, buf, buflen ) - u_short bitmap; + u_int16_t bitmap; struct vol *vol; struct stat *st; char *buf; @@ -570,15 +628,44 @@ { struct adouble ad; int bit = 0, aint, isad = 1; - u_short ashort; - u_long bfree, btotal; + u_int16_t ashort; + u_int32_t bfree, btotal; char *data, *nameoff = 0; + char *fi, *slash; + + /* + * For MacOS8.x support we need to create the + * .Parent file here if it doesn't exists - we + * need to set the FILERINFO bit that says + * we have a custom icon before MacOS8.x sees it. + */ if ( ad_open( vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, - O_RDONLY, 0, &ad ) < 0 ) { + O_RDWR|O_CREAT, 0666, &ad ) < 0 ) { isad = 0; } + /* + * If we did create the .Parent file here then we need to + * set the pathname and filerinfo bit to say we have a + * custom icon for MacOS8.x. + */ + + if ( isad && (ad_getoflags( &ad, ADFLAGS_HF ) & O_CREAT )) { + fi = ad_entry(&ad, ADEID_FINDERI); + slash = strrchr( vol->v_path, '/' ); + if(slash) + slash++; + else + slash = vol->v_path; + + ad_setentrylen( &ad, ADEID_NAME, strlen( slash )); + memcpy( ad_entry( &ad, ADEID_NAME ), + slash, ad_getentrylen( &ad, ADEID_NAME )); + + fi[8] |= FINDERINFO_CUSTOMICON; + } + if (( bitmap & ( (1<st_mtime ); } } else { aint = htonl( st->st_mtime ); } - bcopy( &aint, data, sizeof( int )); - data += sizeof( int ); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); break; case VOLPBIT_MDATE : @@ -629,41 +716,41 @@ } else { aint = htonl( vol->v_time ); } - bcopy( &aint, data, sizeof( int )); - data += sizeof( int ); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); break; case VOLPBIT_BDATE : if ( isad ) { - bcopy( ad_entry( &ad, ADEID_FILEI ) + FILEIOFF_BACKUP, &aint, - sizeof( int )); + memcpy( &aint, ad_entry( &ad, ADEID_FILEI ) + FILEIOFF_BACKUP, + sizeof( aint )); } else { aint = 0; } - bcopy( &aint, data, sizeof( int )); - data += sizeof( int ); + memcpy( data, &aint, sizeof( aint )); + data += sizeof( aint ); break; case VOLPBIT_VID : - bcopy( &vol->v_vid, data, sizeof( vol->v_vid )); + memcpy( data, &vol->v_vid, sizeof( vol->v_vid )); data += sizeof( vol->v_vid ); break; case VOLPBIT_BFREE : bfree = htonl( bfree ); - bcopy( &bfree, data, sizeof( int )); + memcpy( data, &bfree, sizeof( int )); data += sizeof( int ); break; case VOLPBIT_BTOTAL : btotal = htonl( btotal ); - bcopy( &btotal, data, sizeof( int )); + memcpy( data, &btotal, sizeof( int )); data += sizeof( int ); break; case VOLPBIT_NAME : nameoff = data; - data += sizeof( u_short ); + data += sizeof( u_int16_t ); break; default : @@ -677,13 +764,14 @@ } if ( nameoff != 0 ) { ashort = htons( data - buf ); - bcopy( &ashort, nameoff, sizeof( u_short )); + memcpy( nameoff, &ashort, sizeof( ashort )); aint = strlen( vol->v_name ); *data++ = aint; - bcopy( vol->v_name, data, aint ); + memcpy( data, vol->v_name, aint ); data += aint; } if ( isad ) { + ad_flush( &ad, ADFLAGS_HF ); ad_close( &ad, ADFLAGS_HF ); } *buflen = data - buf; @@ -708,6 +796,7 @@ return( vol ); } +void setvoltime( vol ) struct vol *vol; {