@@ -331,37 +331,109 @@ int initialize_globals() {
331331}
332332
333333int initialize_directories () {
334+ int res = -1 ;
335+ int version = 0 ;
336+ FILE * file ;
337+
338+ // Read current filesystem layout version to handle upgrade paths
339+ char version_path [PATH_MAX ];
340+ if (snprintf (version_path , PATH_MAX , "%s.layout_version" , android_data_dir .path ) > PATH_MAX ) {
341+ return -1 ;
342+ }
343+ file = fopen (version_path , "r" );
344+ if (file != NULL ) {
345+ fscanf (file , "%d" , & version );
346+ fclose (file );
347+ }
348+
334349 // /data/user
335350 char * user_data_dir = build_string2 (android_data_dir .path , SECONDARY_USER_PREFIX );
336351 // /data/data
337352 char * legacy_data_dir = build_string2 (android_data_dir .path , PRIMARY_USER_PREFIX );
338353 // /data/user/0
339- char * primary_data_dir = build_string3 (android_data_dir .path , SECONDARY_USER_PREFIX ,
340- "0" );
341- int ret = -1 ;
342- if (user_data_dir != NULL && primary_data_dir != NULL && legacy_data_dir != NULL ) {
343- ret = 0 ;
344- // Make the /data/user directory if necessary
345- if (access (user_data_dir , R_OK ) < 0 ) {
346- if (mkdir (user_data_dir , 0711 ) < 0 ) {
347- return -1 ;
348- }
349- if (chown (user_data_dir , AID_SYSTEM , AID_SYSTEM ) < 0 ) {
350- return -1 ;
351- }
352- if (chmod (user_data_dir , 0711 ) < 0 ) {
353- return -1 ;
354+ char * primary_data_dir = build_string3 (android_data_dir .path , SECONDARY_USER_PREFIX , "0" );
355+ if (!user_data_dir || !legacy_data_dir || !primary_data_dir ) {
356+ goto fail ;
357+ }
358+
359+ // Make the /data/user directory if necessary
360+ if (access (user_data_dir , R_OK ) < 0 ) {
361+ if (mkdir (user_data_dir , 0711 ) < 0 ) {
362+ goto fail ;
363+ }
364+ if (chown (user_data_dir , AID_SYSTEM , AID_SYSTEM ) < 0 ) {
365+ goto fail ;
366+ }
367+ if (chmod (user_data_dir , 0711 ) < 0 ) {
368+ goto fail ;
369+ }
370+ }
371+ // Make the /data/user/0 symlink to /data/data if necessary
372+ if (access (primary_data_dir , R_OK ) < 0 ) {
373+ if (symlink (legacy_data_dir , primary_data_dir )) {
374+ goto fail ;
375+ }
376+ }
377+
378+ // /data/media/0
379+ char owner_media_dir [PATH_MAX ];
380+ create_persona_media_path (owner_media_dir , 0 );
381+
382+ if (version == 0 ) {
383+ // Introducing multi-user, so migrate /data/media contents into /data/media/0
384+ ALOGD ("Migrating /data/media for multi-user" );
385+
386+ // /data/media.tmp
387+ char media_tmp_dir [PATH_MAX ];
388+ snprintf (media_tmp_dir , PATH_MAX , "%smedia.tmp" , android_data_dir .path );
389+
390+ // Only copy when upgrade not already in progress
391+ if (access (media_tmp_dir , F_OK ) == -1 ) {
392+ if (rename (android_media_dir .path , media_tmp_dir ) == -1 ) {
393+ ALOGE ("Failed to move legacy media path: %s" , strerror (errno ));
394+ goto fail ;
354395 }
355396 }
356- // Make the /data/user/0 symlink to /data/data if necessary
357- if (access (primary_data_dir , R_OK ) < 0 ) {
358- ret = symlink (legacy_data_dir , primary_data_dir );
397+
398+ // Create /data/media again
399+ if (ensure_dir (android_media_dir .path , 0770 , AID_MEDIA_RW , AID_MEDIA_RW ) == -1 ) {
400+ goto fail ;
401+ }
402+
403+ // Move any owner data into place
404+ if (access (media_tmp_dir , F_OK ) == 0 ) {
405+ if (rename (media_tmp_dir , owner_media_dir ) == -1 ) {
406+ ALOGE ("Failed to move owner media path: %s" , strerror (errno ));
407+ goto fail ;
408+ }
359409 }
360- free (user_data_dir );
361- free (legacy_data_dir );
362- free (primary_data_dir );
410+ version = 1 ;
363411 }
364- return ret ;
412+
413+ // Ensure /data/media/0 is always ready
414+ if (ensure_dir (owner_media_dir , 0770 , AID_MEDIA_RW , AID_MEDIA_RW ) == -1 ) {
415+ goto fail ;
416+ }
417+
418+ // Persist our current version
419+ file = fopen (version_path , "w" );
420+ if (file != NULL ) {
421+ fprintf (file , "%d" , version );
422+ fsync (fileno (file ));
423+ fclose (file );
424+ } else {
425+ ALOGE ("Failed to save version to %s: %s" , version_path , strerror (errno ));
426+ goto fail ;
427+ }
428+
429+ // Success!
430+ res = 0 ;
431+
432+ fail :
433+ free (user_data_dir );
434+ free (legacy_data_dir );
435+ free (primary_data_dir );
436+ return res ;
365437}
366438
367439int main (const int argc , const char * argv []) {
0 commit comments