Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 68 additions & 86 deletions brightnessctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ static unsigned long percent_to_val(float, struct device *);
static bool find_devices(struct device **, char *);
static bool save_device_data(struct device *);
static bool restore_device_data(struct device *);
static bool ensure_dir(char *);
static bool ensure_dev_dir(struct device *);
static bool mkdir_parent(const char *);
static bool ensure_dir(const char *);

#ifdef ENABLE_LOGIND
static bool logind_set_brightness(struct device *);
Expand Down Expand Up @@ -266,9 +266,16 @@ int process_device(struct device *dev) {
}
free(file_path);
}
mode_t old = umask(0);
char *sys_run_dir = getenv("XDG_RUNTIME_DIR");
if (sys_run_dir) {
umask(0077);
run_dir = dir_child(sys_run_dir, "brightnessctl");
}
if (p.save)
if (!save_device_data(dev))
fprintf(stderr, "Could not save data for device '%s'.\n", dev->id);
umask(old);
if (p.restore) {
if (restore_device_data(dev))
p.operation = RESTORE;
Expand Down Expand Up @@ -557,104 +564,79 @@ int read_devices(struct device **devs) {
}

bool save_device_data(struct device *dev) {
char c[16];
size_t s = sprintf(c, "%u", dev->curr_brightness);
char *d_path = cat_with('/', run_dir, dev->class, dev->id);
FILE *fp;
mode_t old = 0;
int error = 0;
errno = 0;
if (s <= 0) {
fprintf(stderr, "Error converting device data.");
error++;
goto fail;
}
if (!ensure_dev_dir(dev))
goto fail;
old = umask(0);
fp = fopen(d_path, "w");
umask(old);
if (!fp)
goto fail;
if (fwrite(c, 1, s, fp) < s) {
fprintf(stderr, "Error writing to '%s'.\n", d_path);
error++;
char *c_path = dir_child(run_dir, dev->class);
char *d_path = dir_child(c_path, dev->id);
bool ret = true;
if (ensure_dir(c_path)) {
FILE *fp = fopen(d_path, "wb");
if (fp) {
fwrite(&dev->curr_brightness, sizeof(dev->curr_brightness), 1, fp);
if (ferror(fp)) {
ret = false;
fprintf(stderr, "Error writing to '%s'.\n", d_path);
}
fclose(fp);
} else {
ret = false;
fprintf(stderr, "Error opening '%s': %s\n", d_path, strerror(errno));
}
} else {
fprintf(stderr, "Failed to access or create '%s': %s\n", path, strerror(errno));
}
fclose(fp);
fail:
free(c_path);
free(d_path);
if (errno) {
perror("Error saving device data");
error++;
}
return !error;
return ret;
}

bool restore_device_data(struct device *dev) {
char buf[16];
char *filename = cat_with('/', run_dir, dev->class, dev->id);
char *end;
FILE *fp;
memset(buf, 0, 16);
errno = 0;
if (!(fp = fopen(filename, "r")))
goto fail;
if (!fread(buf, 1, 15, fp))
goto rfail;
dev->curr_brightness = strtol(buf, &end, 10);
if (end == buf)
errno = EINVAL;
rfail:
fclose(fp);
fail:
free(filename);
if (errno) {
bool ret = true;
FILE *fp = fopen(filename, "rb");
if (fp) {
unsigned int val;
fread(&val, sizeof(val), 1, fp);
if (!ferror(fp)) {
dev->curr_brightness = val;
} else {
ret = false;
fprintf(stderr, "Error reading file '%s'\n", filename);
}
fclose(fp);
} else {
ret = false;
perror("Error restoring device data");
return false;
}
return true;
free(filename);
return ret;
}


bool ensure_dir(char *dir) {
struct stat sb;
if (stat(dir, &sb)) {
if (errno != ENOENT)
return false;
errno = 0;
if (mkdir(dir, 0777)) {
return false;
}
if (stat(dir, &sb))
return false;
}
if (!S_ISDIR(sb.st_mode)) {
errno = ENOTDIR;
bool mkdir_parent(const char *path) {
if (!path)
return false;
bool ret = true;
size_t size = strlen(path) + 1;
char *tmp = calloc(1, size);
if (!tmp)
return false;
for (const char *p = path; (p - path) < (long)size; p++) {
if ((*p == '/' || *p == '\0') && (p != path && *(p - 1) != '/')) {
memcpy(tmp, path, p - path);
tmp[p - path] = 0;
if (mkdir(tmp, 0777) && errno != EEXIST) {
ret = false;
perror(tmp);
break;
}
}
}
return true;
}

static bool ensure_run_dir() {
static bool set;
if (!set) {
char *sys_run_dir = getenv("XDG_RUNTIME_DIR");
if (sys_run_dir)
run_dir = dir_child(sys_run_dir, "brightnessctl");
set = true;
}
return ensure_dir(run_dir);
free(tmp);
return ret;
}

bool ensure_dev_dir(struct device *dev) {
char *cpath;
bool ret;
if (!ensure_run_dir())
return false;
cpath = dir_child(run_dir, dev->class);
ret = ensure_dir(cpath);
free(cpath);
return ret;
static bool ensure_dir(const char * path) {
if (!access(path, W_OK))
return true;
return errno == ENOENT ? mkdir_parent(path) : false;
}

char *_cat_with(char c, ...) {
Expand Down