static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir) { if (dir->parent != NULL) { create_dir_path(path, dir); ALOGI("DEL DIR %s\n", path); if (dir->hiddenCount <= 0) { if (rmdir(path)) { ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno)); return; } } else { // The directory contains hidden files so we need to delete // them along with the directory itself. if (delete_dir_contents(path, 1, NULL)) { return; } } dir->parent->childCount--; dir->deleted = 1; if (dir->parent->childCount <= 0) { delete_cache_dir(path, dir->parent); } } else if (dir->hiddenCount > 0) { // This is a root directory, but it has hidden files. Get rid of // all of those files, but not the directory itself. create_dir_path(path, dir); ALOGI("DEL CONTENTS %s\n", path); delete_dir_contents(path, 0, NULL); } }
int delete_persona(uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_persona_path(pkgdir, persona)) return -1; return delete_dir_contents(pkgdir, 1, NULL); }
int uninstall(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, NULL); }
int delete_user_data(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); }
int delete_cache(const char *pkgname, uid_t persona) { char cachedir[PKG_PATH_MAX]; if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, persona)) return -1; /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, 0); }
int delete_user(userid_t userid) { char data_path[PKG_PATH_MAX]; if (create_user_path(data_path, userid)) { return -1; } if (delete_dir_contents(data_path, 1, NULL)) { return -1; } char media_path[PATH_MAX]; if (create_user_media_path(media_path, userid) == -1) { return -1; } if (delete_dir_contents(media_path, 1, NULL) == -1) { return -1; } return 0; }
int delete_persona(uid_t persona) { char data_path[PKG_PATH_MAX]; if (create_persona_path(data_path, persona)) { return -1; } if (delete_dir_contents(data_path, 1, NULL)) { return -1; } char media_path[PATH_MAX]; if (create_persona_media_path(media_path, (userid_t) persona) == -1) { return -1; } if (delete_dir_contents(media_path, 1, NULL) == -1) { return -1; } return 0; }
int main(void) { setup_test(); /* Delete the contents of temp before testing. If we don't clear the contents some test may fail. */ delete_dir_contents("/tmp"); test_check_root(); test_get_file_size(); test_get_core_count(); test_generate_file_name(); test_get_extension(); test_ascii_to_binary(); test_delete_directory(); test_create_random_directory(); delete_dir_contents("/tmp"); test_create_random_file(); _exit(0); }
int delete_cache(const char *pkgname, int encrypted_fs_flag) { char cachedir[PKG_PATH_MAX]; if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) return -1; } else { if (create_pkg_path(cachedir, CACHE_SEC_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX)) return -1; } /* delete contents, not the directory, no exceptions */ return delete_dir_contents(cachedir, 0, 0); }
int uninstall(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) return -1; } else { if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) return -1; } /* delete contents AND directory, no exceptions */ return delete_dir_contents(pkgdir, 1, 0); }
int delete_user_data(const char *pkgname, int encrypted_fs_flag) { char pkgdir[PKG_PATH_MAX]; if (encrypted_fs_flag == USE_UNENCRYPTED_FS) { if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) return -1; } else { if (create_pkg_path(pkgdir, PKG_SEC_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) return -1; } /* delete contents, excluding "lib", but not the directory itself */ return delete_dir_contents(pkgdir, 0, "lib"); }
int32_t delete_directory(char *path) { /* Check for a NULL pointer being passed to us. */ if(path == NULL) { output->write(ERROR, "Path pointer is NULL\n"); return (-1); } struct stat sb; int32_t rtrn = 0; /* Get filesystem stats for the path supplied. */ rtrn = stat(path, &sb); if(rtrn < 0) { output->write(ERROR, "Can't get stats: %s\n", strerror(errno)); return(-1); } /* Make sure path is a directory. */ if(sb.st_mode & S_IFDIR) { /* Delete the contents of the directory before we try deleting the directory it's self. */ rtrn = delete_dir_contents(path); if(rtrn < 0) { output->write(ERROR, "Can't delete dir contents\n"); return (-1); } } else { output->write(ERROR, "Input path is not a directory\n"); return (-1); } rtrn = rmdir(path); if(rtrn < 0) { output->write(ERROR, "Can't remove directory: %s\n", strerror(errno)); return (-1); } return (0); }
/* The directory is about to be deleted: if DEL_RECURSE is given, delete all * its contents, otherwise just checks for content. Returns DR_SUCCESS or * DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The * buffer is used for recursion, but returned unchanged.) */ static enum delret delete_dir_contents(char *fname, uint16 flags) { struct file_list *dirlist; enum delret ret; unsigned remainder; void *save_filters; int j, dlen; char *p; if (DEBUG_GTE(DEL, 3)) { rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n", fname, flags); } dlen = strlen(fname); save_filters = push_local_filters(fname, dlen); non_perishable_cnt = 0; dirlist = get_dirlist(fname, dlen, 0); ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS; if (!dirlist->used) goto done; if (!(flags & DEL_RECURSE)) { ret = DR_NOT_EMPTY; goto done; } p = fname + dlen; if (dlen != 1 || *fname != '/') *p++ = '/'; remainder = MAXPATHLEN - (p - fname); /* We do our own recursion, so make delete_item() non-recursive. */ flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM|DEL_NO_UID_WRITE)) | DEL_DIR_IS_EMPTY; for (j = dirlist->used; j--; ) { struct file_struct *fp = dirlist->files[j]; if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) { if (DEBUG_GTE(DEL, 1)) { rprintf(FINFO, "mount point, %s, pins parent directory\n", f_name(fp, NULL)); } ret = DR_NOT_EMPTY; continue; } strlcpy(p, fp->basename, remainder); if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US) do_chmod(fname, fp->mode | S_IWUSR); /* Save stack by recursing to ourself directly. */ if (S_ISDIR(fp->mode)) { if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS) ret = DR_NOT_EMPTY; } if (delete_item(fname, fp->mode, flags) != DR_SUCCESS) ret = DR_NOT_EMPTY; } fname[dlen] = '\0'; done: flist_free(dirlist); pop_local_filters(save_filters); if (ret == DR_NOT_EMPTY) { rprintf(FINFO, "cannot delete non-empty directory: %s\n", fname); } return ret; }
int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) { char pkgdir[PKG_PATH_MAX]; char libsymlink[PKG_PATH_MAX]; char applibdir[PKG_PATH_MAX]; struct stat libStat; if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %d\n", uid, gid); return -1; } if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { ALOGE("cannot create package path\n"); return -1; } if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) { ALOGE("cannot create package lib symlink origin path\n"); return -1; } if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { ALOGE("cannot create package lib symlink dest path\n"); return -1; } if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); return -1; } if (chmod(pkgdir, 0751) < 0) { ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } if (lstat(libsymlink, &libStat) < 0) { if (errno != ENOENT) { ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); return -1; } } else { if (S_ISDIR(libStat.st_mode)) { if (delete_dir_contents(libsymlink, 1, 0) < 0) { ALOGE("couldn't delete lib directory during install for: %s", libsymlink); return -1; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libsymlink) < 0) { ALOGE("couldn't unlink lib directory during install for: %s", libsymlink); return -1; } } } if (symlink(applibdir, libsymlink) < 0) { ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir, strerror(errno)); unlink(pkgdir); return -1; } if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -errno; } if (chown(pkgdir, uid, gid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -1; } return 0; }
int linklib(const char* dataDir, const char* asecLibDir) { char libdir[PKG_PATH_MAX]; struct stat s, libStat; int rc = 0; const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX); if (libdirLen >= PKG_PATH_MAX) { ALOGE("library dir len too large"); return -1; } if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) { ALOGE("library dir not written successfully: %s\n", strerror(errno)); return -1; } if (stat(dataDir, &s) < 0) return -1; if (chown(dataDir, 0, 0) < 0) { ALOGE("failed to chown '%s': %s\n", dataDir, strerror(errno)); return -1; } if (chmod(dataDir, 0700) < 0) { ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -1; goto out; } if (lstat(libdir, &libStat) < 0) { ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); rc = -1; goto out; } if (S_ISDIR(libStat.st_mode)) { if (delete_dir_contents(libdir, 1, 0) < 0) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libdir) < 0) { rc = -1; goto out; } } if (symlink(asecLibDir, libdir) < 0) { ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libdir, asecLibDir, strerror(errno)); rc = -errno; goto out; } if (lchown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) { ALOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno)); unlink(libdir); rc = -errno; goto out; } out: if (chmod(dataDir, s.st_mode) < 0) { ALOGE("failed to chmod '%s': %s\n", dataDir, strerror(errno)); rc = -errno; } if (chown(dataDir, s.st_uid, s.st_gid) < 0) { ALOGE("failed to chown '%s' : %s\n", dataDir, strerror(errno)); return -errno; } return rc; }
int make_user_data(const char *pkgname, uid_t uid, uid_t persona, const char* seinfo) { char pkgdir[PKG_PATH_MAX]; char applibdir[PKG_PATH_MAX]; char libsymlink[PKG_PATH_MAX]; struct stat libStat; // Create the data dir for the package if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) { return -1; } if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) { ALOGE("cannot create package lib symlink origin path\n"); return -1; } if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { ALOGE("cannot create package lib symlink dest path\n"); return -1; } if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); return -errno; } if (chmod(pkgdir, 0751) < 0) { ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); unlink(pkgdir); return -errno; } if (lstat(libsymlink, &libStat) < 0) { if (errno != ENOENT) { ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno)); unlink(pkgdir); return -1; } } else { if (S_ISDIR(libStat.st_mode)) { if (delete_dir_contents(libsymlink, 1, 0) < 0) { ALOGE("couldn't delete lib directory during install for non-primary: %s", libsymlink); unlink(pkgdir); return -1; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libsymlink) < 0) { ALOGE("couldn't unlink lib directory during install for non-primary: %s", libsymlink); unlink(pkgdir); return -1; } } } if (symlink(applibdir, libsymlink) < 0) { ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink, applibdir, strerror(errno)); unlink(pkgdir); return -1; } if (selinux_android_setfilecon2(pkgdir, pkgname, seinfo, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -errno; } if (chown(pkgdir, uid, uid) < 0) { ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -errno; } return 0; }
static int initialize_directories() { int res = -1; // Read current filesystem layout version to handle upgrade paths char version_path[PATH_MAX]; snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.c_str()); int oldVersion; if (fs_read_atomic_int(version_path, &oldVersion) == -1) { oldVersion = 0; } int version = oldVersion; if (version < 2) { SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported"); version = 2; } if (ensure_config_user_dirs(0) == -1) { SLOGE("Failed to setup misc for user 0"); goto fail; } if (version == 2) { SLOGD("Upgrading to /data/misc/user directories"); char misc_dir[PATH_MAX]; snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.c_str()); char keychain_added_dir[PATH_MAX]; snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir); char keychain_removed_dir[PATH_MAX]; snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir); DIR *dir; struct dirent *dirent; dir = opendir("/data/user"); if (dir != NULL) { while ((dirent = readdir(dir))) { const char *name = dirent->d_name; // skip "." and ".." if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; } uint32_t user_id = std::stoi(name); // /data/misc/user/<user_id> if (ensure_config_user_dirs(user_id) == -1) { goto fail; } char misc_added_dir[PATH_MAX]; snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name); char misc_removed_dir[PATH_MAX]; snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name); uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM); gid_t gid = uid; if (access(keychain_added_dir, F_OK) == 0) { if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) { SLOGE("Some files failed to copy"); } } if (access(keychain_removed_dir, F_OK) == 0) { if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) { SLOGE("Some files failed to copy"); } } } closedir(dir); if (access(keychain_added_dir, F_OK) == 0) { delete_dir_contents(keychain_added_dir, 1, 0); } if (access(keychain_removed_dir, F_OK) == 0) { delete_dir_contents(keychain_removed_dir, 1, 0); } } version = 3; } // Persist layout version if changed if (version != oldVersion) { if (fs_write_atomic_int(version_path, version) == -1) { SLOGE("Failed to save version to %s: %s", version_path, strerror(errno)); goto fail; } } // Success! res = 0; fail: return res; }
int linklib(const char* pkgname, const char* asecLibDir, int userId) { char pkgdir[PKG_PATH_MAX]; char libsymlink[PKG_PATH_MAX]; struct stat s, libStat; int rc = 0; if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) { ALOGE("cannot create package path\n"); return -1; } if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) { ALOGE("cannot create package lib symlink origin path\n"); return -1; } if (stat(pkgdir, &s) < 0) return -1; if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno)); return -1; } if (chmod(pkgdir, 0700) < 0) { ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); rc = -1; goto out; } if (lstat(libsymlink, &libStat) < 0) { if (errno != ENOENT) { ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); rc = -1; goto out; } } else { if (S_ISDIR(libStat.st_mode)) { if (delete_dir_contents(libsymlink, 1, 0) < 0) { rc = -1; goto out; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libsymlink) < 0) { ALOGE("couldn't unlink lib dir: %s\n", strerror(errno)); rc = -1; goto out; } } } if (symlink(asecLibDir, libsymlink) < 0) { ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir, strerror(errno)); rc = -errno; goto out; } out: if (chmod(pkgdir, s.st_mode) < 0) { ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); rc = -errno; } if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno)); return -errno; } return rc; }
/* Delete a file or directory. If DEL_RECURSE is set in the flags, this will * delete recursively. * * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's * a directory! (The buffer is used for recursion, but returned unchanged.) */ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags) { enum delret ret; char *what; int ok; if (DEBUG_GTE(DEL, 2)) { rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n", fbuf, (int)mode, (int)flags); } if (flags & DEL_NO_UID_WRITE) do_chmod(fbuf, mode | S_IWUSR); if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) { /* This only happens on the first call to delete_item() since * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */ ignore_perishable = 1; /* If DEL_RECURSE is not set, this just reports emptiness. */ ret = delete_dir_contents(fbuf, flags); ignore_perishable = 0; if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT) goto check_ret; /* OK: try to delete the directory. */ } if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && stats.deleted_files >= max_delete) { skipped_deletes++; return DR_AT_LIMIT; } if (S_ISDIR(mode)) { what = "rmdir"; ok = do_rmdir(fbuf) == 0; } else { if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir || !is_backup_file(fbuf))) { what = "make_backup"; ok = make_backup(fbuf, True); if (ok == 2) { what = "unlink"; ok = robust_unlink(fbuf) == 0; } } else { what = "unlink"; ok = robust_unlink(fbuf) == 0; } } if (ok) { if (!(flags & DEL_MAKE_ROOM)) { log_delete(fbuf, mode); stats.deleted_files++; if (S_ISREG(mode)) { /* Nothing more to count */ } else if (S_ISDIR(mode)) stats.deleted_dirs++; #ifdef SUPPORT_LINKS else if (S_ISLNK(mode)) stats.deleted_symlinks++; #endif else if (IS_DEVICE(mode)) stats.deleted_symlinks++; else stats.deleted_specials++; } ret = DR_SUCCESS; } else { if (S_ISDIR(mode) && errno == ENOTEMPTY) { rprintf(FINFO, "cannot delete non-empty directory: %s\n", fbuf); ret = DR_NOT_EMPTY; } else if (errno != ENOENT) { rsyserr(FERROR, errno, "delete_file: %s(%s) failed", what, fbuf); ret = DR_FAILURE; } else ret = DR_SUCCESS; } check_ret: if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) { const char *desc; switch (flags & DEL_MAKE_ROOM) { case DEL_FOR_FILE: desc = "regular file"; break; case DEL_FOR_DIR: desc = "directory"; break; case DEL_FOR_SYMLINK: desc = "symlink"; break; case DEL_FOR_DEVICE: desc = "device file"; break; case DEL_FOR_SPECIAL: desc = "special file"; break; default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */ } rprintf(FERROR_XFER, "could not make way for %s %s: %s\n", flags & DEL_FOR_BACKUP ? "backup" : "new", desc, fbuf); } return ret; }