Private
Public Access
2
0

led: Fix and cleanup initialization

The structure returned by readdir is may be statically allocated.
Keeping a pointer to it is broken.

The LED path is generally not a directory, it's a link to a directory.
And even if it were a directory, that would tell nothing about the
caller's access permissions.

And then there is a lot of duplication between mraa_led_init and
mraa_led_init_raw.

This addresses that all.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
This commit is contained in:
Jan Kiszka
2021-02-04 18:12:42 +01:00
committed by Tom Ingleby
parent 13ce6ea446
commit 954b17ded4
2 changed files with 25 additions and 38 deletions

View File

@@ -273,8 +273,7 @@ struct _iio {
struct _led { struct _led {
/*@{*/ /*@{*/
int count; /**< total LED count in a platform */ int count; /**< total LED count in a platform */
char *led_name; /**< LED name */ const char *led_path; /**< sysfs path of the LED */
char led_path[64]; /**< sysfs path of the LED */
int trig_fd; /**< trigger file descriptor */ int trig_fd; /**< trigger file descriptor */
int bright_fd; /**< brightness file descriptor */ int bright_fd; /**< brightness file descriptor */
int max_bright_fd; /**< maximum brightness file descriptor */ int max_bright_fd; /**< maximum brightness file descriptor */

View File

@@ -69,6 +69,10 @@ mraa_led_get_maxbrightfd(mraa_led_context dev)
static mraa_led_context static mraa_led_context
mraa_led_init_internal(const char* led) mraa_led_init_internal(const char* led)
{ {
char brightness_path[MAX_SIZE];
const char *led_name = NULL;
char *led_path;
size_t led_path_len;
DIR* dir; DIR* dir;
struct dirent* entry; struct dirent* entry;
int cnt = 0; int cnt = 0;
@@ -79,7 +83,6 @@ mraa_led_init_internal(const char* led)
return NULL; return NULL;
} }
dev->led_name = NULL;
dev->trig_fd = -1; dev->trig_fd = -1;
dev->bright_fd = -1; dev->bright_fd = -1;
dev->max_bright_fd = -1; dev->max_bright_fd = -1;
@@ -88,13 +91,14 @@ mraa_led_init_internal(const char* led)
/* get the led name from sysfs path */ /* get the led name from sysfs path */
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
if (strstr((const char*) entry->d_name, led)) { if (strstr((const char*) entry->d_name, led)) {
dev->led_name = (char*) entry->d_name; led_name = entry->d_name;
break;
} }
cnt++; cnt++;
} }
} }
dev->count = cnt; dev->count = cnt;
if (dev->led_name == NULL) { if (led_name == NULL) {
syslog(LOG_CRIT, "led: init: unknown device specified"); syslog(LOG_CRIT, "led: init: unknown device specified");
if (dir != NULL) { if (dir != NULL) {
closedir(dir); closedir(dir);
@@ -103,19 +107,28 @@ mraa_led_init_internal(const char* led)
return NULL; return NULL;
} }
if (dir != NULL) { led_path_len = strlen(SYSFS_CLASS_LED) + strlen(led_name) + 3;
led_path = calloc(led_path_len, sizeof(char));
if (led_path == NULL) {
syslog(LOG_CRIT, "led: init: Failed to allocate memory for LED path");
closedir(dir); closedir(dir);
return NULL;
} }
snprintf(led_path, led_path_len, "%s/%s", SYSFS_CLASS_LED, led_name);
dev->led_path = led_path;
snprintf(brightness_path, sizeof(brightness_path), "%s/%s", led_path, "brightness");
if (access(brightness_path, R_OK | W_OK) != 0) {
syslog(LOG_NOTICE, "led: init: current user doesn't have access rights for using LED %s", led_name);
}
closedir(dir);
return dev; return dev;
} }
mraa_led_context mraa_led_context
mraa_led_init(int index) mraa_led_init(int index)
{ {
mraa_led_context dev = NULL;
char directory[MAX_SIZE];
struct stat dir;
if (plat == NULL) { if (plat == NULL) {
syslog(LOG_ERR, "led: init: platform not initialised"); syslog(LOG_ERR, "led: init: platform not initialised");
return NULL; return NULL;
@@ -136,27 +149,12 @@ mraa_led_init(int index)
return NULL; return NULL;
} }
dev = mraa_led_init_internal((char*) plat->led_dev[index].name); return mraa_led_init_internal((char*) plat->led_dev[index].name);
if (dev == NULL) {
return NULL;
}
snprintf(directory, MAX_SIZE, "%s/%s", SYSFS_CLASS_LED, dev->led_name);
if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) {
syslog(LOG_NOTICE, "led: init: current user doesn't have access rights for using LED %s", dev->led_name);
}
strncpy(dev->led_path, (const char*) directory, sizeof(directory));
return dev;
} }
mraa_led_context mraa_led_context
mraa_led_init_raw(const char* led) mraa_led_init_raw(const char* led)
{ {
mraa_led_context dev = NULL;
char directory[MAX_SIZE];
struct stat dir;
if (plat == NULL) { if (plat == NULL) {
syslog(LOG_ERR, "led: init: platform not initialised"); syslog(LOG_ERR, "led: init: platform not initialised");
return NULL; return NULL;
@@ -167,18 +165,7 @@ mraa_led_init_raw(const char* led)
return NULL; return NULL;
} }
dev = mraa_led_init_internal(led); return mraa_led_init_internal(led);
if (dev == NULL) {
return NULL;
}
snprintf(directory, MAX_SIZE, "%s/%s", SYSFS_CLASS_LED, dev->led_name);
if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) {
syslog(LOG_NOTICE, "led: init: current user don't have access rights for using LED %s", dev->led_name);
}
strncpy(dev->led_path, (const char*) directory, sizeof(directory));
return dev;
} }
mraa_result_t mraa_result_t
@@ -402,6 +389,7 @@ mraa_led_close(mraa_led_context dev)
close(dev->max_bright_fd); close(dev->max_bright_fd);
} }
free((void *)dev->led_path);
free(dev); free(dev);
return MRAA_SUCCESS; return MRAA_SUCCESS;