return 1;
}
+static void unlock_dir(int fd)
+{
+ if (flock(fd, LOCK_UN) < 0)
+ _E("Failed to unlock file descriptor: %m");
+ close(fd);
+}
+
static bool make_dump_dir(void)
{
const char *dirs[] = {crash_dump_path, crash_temp_path};
}
}
+static int dump_filter(const struct dirent *de)
+{
+ assert(de);
+
+ if (de->d_name[0] == '.')
+ return 0;
+ return 1;
+}
+
+/* We treat all errors as if the file was locked. This function is used to check
+ * if we can remove the temporary directory. We don't want to remove that
+ * directory if an error has occurred, because the deletion will probably also
+ * fail */
+static bool is_locked(const char *dir_name)
+{
+ assert(dir_name);
+
+ char lock_file[PATH_MAX];
+ if (snprintf(lock_file, sizeof(lock_file), "%s", dir_name) == -1) {
+ _E("Unable to check locking status for %s: %m", dir_name);
+ return true;
+ }
+
+ int fd = open(lock_file, O_RDONLY | O_DIRECTORY);
+ if (fd == -1) {
+ _E("Unable to open file %s to check if it's blocked: %m", lock_file);
+ return true;
+ }
+
+ bool result = flock(fd, LOCK_EX | LOCK_NB) == -1;
+
+ close(fd);
+ return result;
+}
+
+static bool clean_temp(const char *temp_dir)
+{
+ bool result = true;
+ assert(temp_dir);
+
+ struct dirent **scan_list = NULL;
+ int scan_num;
+
+ if ((scan_num = scandir(temp_dir, &scan_list, &dump_filter, NULL)) < 0)
+ return false;
+
+ for (int i = 0; i < scan_num; i++) {
+ char dir_name[PATH_MAX];
+
+ if (snprintf(dir_name, sizeof(dir_name), "%s/%s", temp_dir, scan_list[i]->d_name) == -1) {
+ _E("Unable to clean temp for %s: %m", dir_name);
+ result = false;
+ continue;
+ }
+
+ if (is_locked(dir_name))
+ _D("Temporary directory %s is locked", dir_name);
+ else if (remove_dir(dir_name, 1) == -1)
+ _W("Can not remove temporary directory: %s", dir_name);
+ else
+ _D("Temporary directory %s removed", dir_name);
+ }
+
+ return result;
+}
+
/* Note: caller of this function is responsible for cleaning up the cinfo on failure */
bool set_crash_info(struct crash_info *cinfo)
{
return true;
out_rm_temp:
+ unlock_dir(cinfo->lock_fd);
remove_dir(cinfo->temp_dir, 1);
+ clean_temp(crash_temp_path);
return false;
out_oom:
return true;
}
-static int lock_dumpdir(void)
+static int lock_dir(const char *path, bool block)
{
+ assert(path);
+
int fd;
- if ((fd = open(crash_dump_path, O_RDONLY | O_DIRECTORY)) < 0) {
- _E("Failed to open %s: %m", crash_dump_path);
+ if ((fd = open(path, O_RDONLY | O_DIRECTORY)) == -1) {
+ _E("Failed to open %s: %m", path);
return -1;
}
- if (flock(fd, LOCK_EX) < 0) {
- _E("Failed to lock %s for exclusive access: %m", crash_dump_path);
+ int flock_flags = LOCK_EX;
+
+ if (!block)
+ flock_flags |= LOCK_NB;
+
+ if (flock(fd, flock_flags) == -1) {
+ _E("Failed to lock %s for exclusive access: %m", path);
close(fd);
return -1;
}
return fd;
}
-static void unlock_dumpdir(int fd)
-{
- if (flock(fd, LOCK_UN) < 0)
- _E("Failed to unlock file descriptor: %m");
- close(fd);
-}
-
-static int dump_filter(const struct dirent *de)
-{
- if (de->d_name[0] == '.')
- return 0;
- return 1;
-}
-
static int mtime_cmp(const void *_a, const void *_b)
{
const struct file_info *a = _a;
int lock_fd;
bool is_ok = true;
- if ((lock_fd = lock_dumpdir()) < 0)
+ if ((lock_fd = lock_dir(crash_dump_path, false)) < 0)
return false;
if (!rename(from_path, cinfo->result_path))
clean_dump();
_E("Failed to move %s to %s", from_path, cinfo->result_path);
is_ok = false;
}
- unlock_dumpdir(lock_fd);
+ unlock_dir(lock_fd);
+ unlock_dir(cinfo->lock_fd);
if (remove_dir(cinfo->temp_dir, 1) < 0)
_E("Failed to delete temp directory");
+ clean_temp(crash_temp_path);
+
return is_ok;
}
cinfo->zip_path = NULL;
cinfo->appid = NULL;
cinfo->pkgid = NULL;
+ cinfo->lock_fd = -1;
}
static bool run(struct crash_info *cinfo)
if (!set_crash_info(cinfo))
return false;
+ cinfo->lock_fd = lock_dir(cinfo->temp_dir, true);
+ if (cinfo->lock_fd == -1)
+ return false;
+
return true;
}