/* * xfce4-hdaps, an XFCE4 panel plugin for the HDAPS system. * * Copyright (C) 2019 Michael Orlitzky * * http://michael.orlitzky.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details: * * https://www.gnu.org/licenses/agpl-3.0.html * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include "hdaps.h" /* The most space we expect to need when reading in a file using these hdaps functions. To exceed 32 bytes worth of content in unload_heads you'd have to throw your laptop hard as a motherfucker. */ #define MAX_FILE_CONTENTS_SIZE 32 /* Where the block device names are located. */ #define SYSFS_BLOCK_DEVICE_DIR "/sys/block/" static int hdaps_device_exists(const char* device) { /* Determine whether or not a device (file) exists and has an unload_heads entry in sysfs. */ char path[FILENAME_MAX]; snprintf(path, FILENAME_MAX, UNLOAD_HEADS_FMT, device); return (access(path, F_OK) == 0); } int get_hdaps_device_list(char list[MAX_HDAPS_DEVICES][FILENAME_MAX]) { /* Gets a list of devices which support HDAPS. * We start by getting every device in the sysfs * block device directory, and then eliminate those * which don't have an unload_heads entry. */ int list_idx = 0; DIR *dp; struct dirent *ep; dp = opendir(SYSFS_BLOCK_DEVICE_DIR); if (dp != NULL) { while ((ep = readdir(dp)) && list_idx < MAX_HDAPS_DEVICES) { /* This next test covers "." and ".." too. */ if (hdaps_device_exists(ep->d_name)) { strncpy(list[list_idx], ep->d_name, FILENAME_MAX); list_idx++; } } (void)closedir(dp); /* Explicitly ignore this. */ } return list_idx; } int slurp_file(const char* filename, char* buf, int max_bytes) { /* This function just reads the contents of filename * into buf, and returns the number of bytes read. */ if (filename == NULL || buf == NULL) { /* HDAPS_SUPER_BAD_ERROR */ return HDAPS_ERROR; } /* Return an error value by default. */ int bytes_read = HDAPS_ERROR; int fd = open(filename, O_RDONLY); if (fd < 0) { /* open() didn't work. Report the error, and bail. */ fprintf(stderr, "open(%s): %s\n", filename, strerror(errno)); return HDAPS_ERROR; } bytes_read = read(fd, buf, max_bytes-1); if (bytes_read < 0) { /* Why did we read fewer than 0 bytes? */ fprintf(stderr, "read(%s): %s\n", filename, strerror(errno)); } else { /* Null-terminate buf if read() worked. */ buf[bytes_read] = 0; } if (close(fd)) { /* Oh hey we should be able to close the file, too. */ fprintf(stderr, "close(%s): %s\n", filename, strerror(errno)); } return bytes_read; } int parse_int_from_file(const char* filename) { /* Read an integer from a file. We expect the file to contain an integer (although in string form). */ char buf[MAX_FILE_CONTENTS_SIZE]; int bytes_read = slurp_file(filename, buf, sizeof(buf)); if (bytes_read <= 0) { /* We can't parse what doesn't exist. Note that * reading "0" from a file should result in reading * at least 1 byte. */ return HDAPS_ERROR; } else { /* If we read more than 0 bytes, hopefully we can * count on atoi to succeed. */ return atoi(buf); } }