summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-10-15 12:22:43 +0000
committermananth <mananth>2003-10-15 12:22:43 +0000
commit86c5b90a76fe07731224d3b47c08721c30b41f29 (patch)
tree1e6c0934c3f3d8a013b710770463536aab8f1d47
parent7838df3254db021c96f1c53593c1753cb4315057 (diff)
downloadsysfsutils-86c5b90a76fe07731224d3b47c08721c30b41f29.tar.gz
Added sysfs_block.c
-rw-r--r--ChangeLog4
-rw-r--r--cmd/systool.c125
-rw-r--r--include/libsysfs.h36
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/Makefile.in10
-rw-r--r--lib/sysfs_block.c309
-rw-r--r--lib/sysfs_class.c2
-rw-r--r--lib/sysfs_dir.c3
8 files changed, 474 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index a944955..8a8a97e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
+09/29/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com>
+ * Added "block" subsystem support
+ * Modified systool to use sysfs_root_device
+
09/24/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com>
* Added "write" attribute functions specific to device,
driver and class device.
diff --git a/cmd/systool.c b/cmd/systool.c
index fe5e903..6ebbe3a 100644
--- a/cmd/systool.c
+++ b/cmd/systool.c
@@ -45,7 +45,7 @@ static unsigned char *device_to_show = NULL; /* show only this bus device */
#define SHOW_ALL 0xff
-static unsigned char cmd_options[] = "aA:b:c:dDhr:v";
+static unsigned char cmd_options[] = "aA:b:B:c:dDhr:v";
/*
* binary_files - defines existing sysfs binary files. These files will be
@@ -73,6 +73,7 @@ void usage(void)
"\t-r <root_device>\tShow a specific root device tree\n");
fprintf(stdout, "\t-v\t\t\tShow all attributes with values\n");
fprintf(stdout, "\t-A <attribute_name>\tShow attribute value\n");
+ fprintf(stdout, "\t-B <block_name>\t Show specific block device\n");
fprintf(stdout, "\t-D\t\t\tShow only drivers\n");
}
@@ -456,7 +457,8 @@ int show_sysfs_class(unsigned char *classname)
*/
int show_sysfs_root(unsigned char *rootname)
{
- struct sysfs_device *root = NULL;
+ struct sysfs_root_device *root = NULL;
+ struct sysfs_device *device = NULL;
unsigned char path[SYSFS_PATH_MAX];
if (rootname == NULL) {
@@ -472,18 +474,103 @@ int show_sysfs_root(unsigned char *rootname)
strcat(path, SYSFS_DEVICES_DIR);
strcat(path, "/");
strcat(path, rootname);
- root = sysfs_open_device_tree(path);
+
+ root = sysfs_open_root_device(rootname);
if (root == NULL) {
fprintf(stderr, "Error opening root device %s\n", rootname);
return 1;
}
- fprintf(stdout, "Root Device Tree: %s\n", rootname);
- show_device_tree(root, 2);
- sysfs_close_device_tree(root);
+ fprintf(stdout, "Root Device Tree: %s\n", rootname);
+
+ if (root->devices) {
+ dlist_for_each_data(root->devices, device,
+ struct sysfs_device) {
+ show_device_tree(device, 2);
+ }
+ }
+ sysfs_close_root_device(root);
+
return 0;
}
+/**
+ * show_block_partitions: show partition details
+ * @partitions: dlist of partitions
+ * returns nothing
+ */
+void show_block_partitions(struct dlist *partitions, int level)
+{
+ struct sysfs_block_partition *part = NULL;
+ struct dlist *attributes = NULL;
+
+ if (partitions == NULL)
+ return;
+ indent(level);
+ fprintf(stdout, "Partitions:\n");
+ dlist_for_each_data(partitions, part, struct sysfs_block_partition) {
+ indent(level+4);
+ fprintf(stdout, "%s\n", part->name);
+ if (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE
+ | SHOW_ALL_ATTRIB_VALUES)) {
+ attributes = sysfs_get_partition_attributes(part);
+ if (attributes != NULL)
+ show_attributes(attributes, level+8);
+ }
+ }
+}
+
+/**
+ * show_sysfs_block: prints out details of the given block device
+ * @blockname: name of the block device to show
+ * returns 0 on success, 1 on error
+ */
+int show_sysfs_block(unsigned char *blockname)
+{
+ struct sysfs_block_device *block = NULL;
+ struct dlist *attributes = NULL;
+
+ if (blockname == NULL) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ block = sysfs_open_block_device(blockname);
+ if (block == NULL) {
+ fprintf(stderr, "Error opening block device %s\n", blockname);
+ return 1;
+ }
+
+ fprintf(stdout, "Block: %s\n", blockname);
+ if (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE
+ | SHOW_ALL_ATTRIB_VALUES)) {
+ attributes = sysfs_get_blockdev_attributes(block);
+ if (attributes != NULL)
+ show_attributes(attributes, 4);
+ attributes = sysfs_get_queue_attributes(block);
+ if (attributes != NULL) {
+ indent(4);
+ fprintf(stdout, "queue:\n");
+ show_attributes(attributes, 8);
+ }
+ attributes = sysfs_get_iosched_attributes(block);
+ if (attributes != NULL) {
+ indent(8);
+ fprintf(stdout, "iosched:\n");
+ show_attributes(attributes, 12);
+ }
+ }
+ if (block->partitions != NULL)
+ show_block_partitions(block->partitions, 4);
+ if (block->device != NULL) {
+ indent(4);
+ fprintf(stdout, "Physical device:");
+ show_device(block->device, 4);
+ }
+ sysfs_close_block_device(block);
+
+ return 0;
+}
/**
* show_default_info: prints current buses, classes, and root devices
@@ -524,6 +611,15 @@ int show_default_info(void)
}
sysfs_close_list(list);
+ strcpy(subsys, SYSFS_BLOCK_DIR);
+ list = sysfs_open_subsystem_list(subsys);
+ if (list != NULL) {
+ fprintf(stdout, "Supported sysfs block devices:\n");
+ dlist_for_each_data(list, cur, char)
+ fprintf(stdout, "\t%s\n", cur);
+ }
+ sysfs_close_list(list);
+
return retval;
}
@@ -533,6 +629,7 @@ int main(int argc, char *argv[])
unsigned char *show_bus = NULL;
unsigned char *show_class = NULL;
unsigned char *show_root = NULL;
+ unsigned char *show_block = NULL;
int retval = 0;
int opt;
extern int optind;
@@ -556,6 +653,9 @@ int main(int argc, char *argv[])
case 'b':
show_bus = optarg;
break;
+ case 'B':
+ show_block = optarg;
+ break;
case 'c':
show_class = optarg;
break;
@@ -602,9 +702,11 @@ int main(int argc, char *argv[])
exit(1);
}
- if ((show_bus == NULL && show_class == NULL && show_root == NULL)
- && (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE
- | SHOW_DEVICES | SHOW_DRIVERS | SHOW_ALL_ATTRIB_VALUES))) {
+ if ((show_bus == NULL && show_class == NULL &&
+ show_root == NULL && show_block == NULL) &&
+ (show_options & (SHOW_ATTRIBUTES |
+ SHOW_ATTRIBUTE_VALUE | SHOW_DEVICES |
+ SHOW_DRIVERS | SHOW_ALL_ATTRIB_VALUES))) {
fprintf(stderr,
"Please specify a bus, class, or root device\n");
usage();
@@ -620,8 +722,11 @@ int main(int argc, char *argv[])
retval = show_sysfs_class(show_class);
if (show_root != NULL)
retval = show_sysfs_root(show_root);
+ if (show_block != NULL)
+ retval = show_sysfs_block(show_block);
- if (show_bus == NULL && show_class == NULL && show_root == NULL)
+ if (show_bus == NULL && show_class == NULL &&
+ show_root == NULL && show_block == NULL)
retval = show_default_info();
exit(retval);
diff --git a/include/libsysfs.h b/include/libsysfs.h
index 2a96b6d..da0a3ee 100644
--- a/include/libsysfs.h
+++ b/include/libsysfs.h
@@ -33,6 +33,7 @@
#define SYSFS_PROC_MNTS "/proc/mounts"
#define SYSFS_BUS_DIR "/bus"
#define SYSFS_CLASS_DIR "/class"
+#define SYSFS_BLOCK_DIR "/block"
#define SYSFS_DEVICES_DIR "/devices"
#define SYSFS_DEVICES_NAME "devices"
#define SYSFS_DRIVERS_DIR "/drivers"
@@ -40,6 +41,10 @@
#define SYSFS_NAME_ATTRIBUTE "name"
#define SYSFS_UNKNOWN "unknown"
+/* Some "block" subsystem specific #defines */
+#define SYSFS_QUEUE_NAME "queue"
+#define SYSFS_IOSCHED_NAME "iosched"
+
#define SYSFS_PATH_MAX 255
#define SYSFS_NAME_LEN 50
#define SYSFS_BUS_ID_SIZE 20
@@ -127,6 +132,23 @@ struct sysfs_class {
struct sysfs_directory *directory;
};
+struct sysfs_block_device {
+ struct sysfs_device *device; /* the physical device */
+ struct dlist *partitions; /* struct sysfs_block_partition */
+ unsigned char name[SYSFS_NAME_LEN];
+ unsigned char path[SYSFS_PATH_MAX];
+
+ /* for internal use only */
+ struct sysfs_directory *directory;
+};
+
+struct sysfs_block_partition {
+ unsigned char name[SYSFS_NAME_LEN];
+
+ /* for internal use only */
+ struct sysfs_directory *directory;
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -226,6 +248,20 @@ extern int sysfs_find_device_class_name(unsigned char *bus_id,
extern int sysfs_write_classdev_attr(unsigned char *dev,
unsigned char *attrib, unsigned char *value);
+/* generic sysfs block access */
+extern void sysfs_close_block_partition
+ (struct sysfs_block_partition *partition);
+extern void sysfs_close_block_device(struct sysfs_block_device *block);
+extern struct sysfs_block_device *sysfs_open_block_device(unsigned char *name);
+extern struct dlist *sysfs_get_blockdev_attributes
+ (struct sysfs_block_device *block);
+extern struct dlist *sysfs_get_partition_attributes
+ (struct sysfs_block_partition *part);
+extern struct dlist *sysfs_get_queue_attributes
+ (struct sysfs_block_device *block);
+extern struct dlist *sysfs_get_iosched_attributes
+ (struct sysfs_block_device *block);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d343f01..2b5049a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,5 +1,5 @@
lib_LIBRARIES = libsysfs.a
libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \
- sysfs_device.c sysfs_driver.c sysfs.h dlist.c
+ sysfs_device.c sysfs_driver.c sysfs_block.c sysfs.h dlist.c
INCLUDES = -I../include
diff --git a/lib/Makefile.in b/lib/Makefile.in
index a2e859e..2ecbd5f 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -77,7 +77,7 @@ am__quote = @am__quote@
install_sh = @install_sh@
lib_LIBRARIES = libsysfs.a
libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \
- sysfs_device.c sysfs_driver.c sysfs.h dlist.c
+ sysfs_device.c sysfs_driver.c sysfs_block.c sysfs.h dlist.c
INCLUDES = -I../include
subdir = lib
@@ -90,7 +90,8 @@ libsysfs_a_AR = $(AR) cru
libsysfs_a_LIBADD =
am_libsysfs_a_OBJECTS = sysfs_utils.$(OBJEXT) sysfs_dir.$(OBJEXT) \
sysfs_bus.$(OBJEXT) sysfs_class.$(OBJEXT) \
- sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) dlist.$(OBJEXT)
+ sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) \
+ sysfs_block.$(OBJEXT) dlist.$(OBJEXT)
libsysfs_a_OBJECTS = $(am_libsysfs_a_OBJECTS)
DEFS = @DEFS@
@@ -100,8 +101,8 @@ LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist.Po ./$(DEPDIR)/sysfs_bus.Po \
-@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_class.Po \
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist.Po ./$(DEPDIR)/sysfs_block.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_bus.Po ./$(DEPDIR)/sysfs_class.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_device.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_dir.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/sysfs_driver.Po \
@@ -168,6 +169,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_block.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_bus.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_class.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_device.Po@am__quote@
diff --git a/lib/sysfs_block.c b/lib/sysfs_block.c
new file mode 100644
index 0000000..601f575
--- /dev/null
+++ b/lib/sysfs_block.c
@@ -0,0 +1,309 @@
+/*
+ * sysfs_block.c
+ *
+ * Generic block utility functions for libsysfs
+ *
+ * Copyright (C) IBM Corp. 2003
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * NOTES:
+ * Write functions to:
+ * Device major/minor given a device
+ * As of now, only the "block" device has writable attribs.
+ * Library has to take care of navigating to the attribute
+ * (may be at various directory levels)
+ */
+
+#include "libsysfs.h"
+#include "sysfs.h"
+
+void sysfs_del_partition(void *partition)
+{
+ sysfs_close_block_partition((struct sysfs_block_partition *)partition);
+}
+
+/**
+ * sysfs_close_block_partition: closes a block partition
+ * @partition: sysfs_block_partition to close
+ */
+void sysfs_close_block_partition(struct sysfs_block_partition *partition)
+{
+ if (partition != NULL) {
+ if (partition->directory != NULL)
+/* reuse sysfs_dir from the earlier structure - just set it to NULL here
+ * free it while closing sysfs_block_device->directory
+ * sysfs_close_directory(partition->directory);*/
+ partition->directory = NULL;
+ }
+}
+
+/**
+ * sysfs_close_block_device: closes a sysfs_block_device
+ * @block: sysfs_block_device structure
+ */
+void sysfs_close_block_device(struct sysfs_block_device *block)
+{
+ if (block != NULL) {
+ if (block->directory != NULL)
+ sysfs_close_directory(block->directory);
+ if (block->device != NULL)
+ sysfs_close_device(block->device);
+ if (block->partitions != NULL)
+ dlist_destroy(block->partitions);
+ }
+}
+
+/**
+ * alloc_block_device: allocate a sysfs_block_device
+ * returns sysfs_block_device or NULL
+ */
+static struct sysfs_block_device *alloc_block_device()
+{
+ return (struct sysfs_block_device *)
+ calloc(1, sizeof(struct sysfs_block_device));
+}
+
+/**
+ * open_block_dir: opens a sysfs block directory
+ * returns sysfs_directory on success or NULL on error
+ */
+static struct sysfs_directory *open_block_dir(const unsigned char *name)
+{
+ unsigned char path[SYSFS_PATH_MAX];
+ struct sysfs_directory *directory = NULL;
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ memset(path, 0, SYSFS_PATH_MAX);
+ if ((sysfs_get_mnt_path(path, SYSFS_PATH_MAX)) != 0) {
+ dprintf("Error getting sysfs mount path\n");
+ return NULL;
+ }
+
+ strcat(path, SYSFS_BLOCK_DIR);
+ strcat(path, "/");
+ strcat(path, name);
+ directory = sysfs_open_directory(path);
+ if (directory == NULL) {
+ dprintf("Block device %s not supported on this system", name);
+ return NULL;
+ }
+ if ((sysfs_read_directory(directory)) != 0) {
+ dprintf("Error reading directory %s\n", directory->path);
+ sysfs_close_directory(directory);
+ return NULL;
+ }
+ sysfs_read_all_subdirs(directory);
+
+ return directory;
+}
+
+/**
+ * alloc_block_partition: alloc a sysfs_block_partition structure
+ */
+static struct sysfs_block_partition *alloc_block_partition(void)
+{
+ return(struct sysfs_block_partition *)
+ calloc(1, sizeof(struct sysfs_block_partition));
+}
+
+/**
+ * get_all_block_devices: Retrieves details of block directory
+ * @block: sysfs_block_device for which details are required
+ * returns 0 on success, -1 on failure
+ */
+static int get_all_block_devices(struct sysfs_block_device *block)
+{
+ struct sysfs_directory *cur = NULL;
+ struct sysfs_block_partition *part = NULL;
+
+ if (block == NULL || block->directory == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ dlist_for_each_data(block->directory->subdirs, cur,
+ struct sysfs_directory) {
+ switch(strcmp(cur->name, SYSFS_QUEUE_NAME)) {
+ case 0: /* this is the "queue" directory */
+ if ((sysfs_read_directory(cur)) < 0) {
+ dprintf("Error reading directory %s\n",
+ cur->path);
+ return -1;
+ }
+ break;
+ default: /* these are the partitions */
+ part = alloc_block_partition();
+ if (part == NULL) {
+ perror("calloc");
+ return -1;
+ }
+ part->directory = cur;
+ strcpy(part->name, cur->name);
+ if (block->partitions == NULL)
+ block->partitions =
+ dlist_new_with_delete
+ (sizeof(struct
+ sysfs_block_partition),
+ sysfs_del_partition);
+ dlist_unshift(block->partitions, part);
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
+ * sysfs_open_block_device: opens the specific block device and all its related
+ * details as partitions, etc
+ * returns sysfs_block_device struct on success and NULL on error
+ */
+struct sysfs_block_device *sysfs_open_block_device(unsigned char *name)
+{
+ struct sysfs_block_device *block = NULL;
+ struct sysfs_directory *blockdir = NULL;
+ struct sysfs_link *curlink = NULL;
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ block = alloc_block_device();
+ if (block == NULL) {
+ perror("calloc");
+ return NULL;
+ }
+ strcpy(block->name, name);
+ blockdir = open_block_dir(name);
+ if (blockdir == NULL) {
+ sysfs_close_block_device(block);
+ return NULL;
+ }
+ strcpy(block->path, blockdir->path);
+ block->directory = blockdir;
+ if ((get_all_block_devices(block)) != 0) {
+ dprintf("Error retrieving devices for block %s\n", name);
+ sysfs_close_block_device(block);
+ return NULL;
+ }
+ /* check if the "block" device has a link to the physical device */
+ if (block->directory->links != NULL) {
+ dlist_for_each_data(block->directory->links, curlink,
+ struct sysfs_link) {
+ block->device = sysfs_open_device(curlink->target);
+ if (block->device == NULL) {
+ dprintf("Error opening device at %s\n",
+ curlink->target);
+ }
+ }
+ }
+
+ return block;
+}
+
+/**
+ * sysfs_get_blockdev_attributes: returns attributes for the block device
+ * @block: block device for which attribs are to be returned
+ */
+struct dlist *sysfs_get_blockdev_attributes(struct sysfs_block_device *block)
+{
+ if (block == NULL || block->directory == NULL)
+ return NULL;
+
+ return(block->directory->attributes);
+}
+
+/**
+ * sysfs_get_partition_attributes: returns attributes for the block
+ * device partition
+ * @block: block device partition for which attribs are to be returned
+ */
+struct dlist *sysfs_get_partition_attributes
+ (struct sysfs_block_partition *part)
+{
+ if (part == NULL || part->directory == NULL)
+ return NULL;
+
+ return(part->directory->attributes);
+}
+
+/**
+ * sysfs_get_queue_attributes: returns attributes for the block device's
+ * QUEUE parameters. Used to set #of queued
+ * requests as well as the choice of IO
+ * scheduler
+ * @block: block device for which the attributes are needed.
+ */
+struct dlist *sysfs_get_queue_attributes(struct sysfs_block_device *block)
+{
+ struct dlist *list = NULL;
+ struct sysfs_directory *dir = NULL;
+ unsigned int found = 0;
+
+ dlist_for_each_data(block->directory->subdirs, dir,
+ struct sysfs_directory) {
+ if ((strcmp(dir->name, SYSFS_QUEUE_NAME)) != 0)
+ continue;
+ else
+ return (dir->attributes);
+ }
+ return NULL;
+}
+
+/**
+ * sysfs_get_iosched_attributes: returns attributes for the block device's
+ * IOSCHED parameters for the given device
+ * @block: block device for which the attributes are needed
+ * returns a dlist of iosched attributes.
+ */
+struct dlist *sysfs_get_iosched_attributes(struct sysfs_block_device *block)
+{
+ struct dlist *list = NULL;
+ struct sysfs_directory *dir = NULL, *new = NULL;
+ unsigned int found = 0;
+
+ dlist_for_each_data(block->directory->subdirs, dir,
+ struct sysfs_directory) {
+ if ((strcmp(dir->name, SYSFS_QUEUE_NAME)) != 0)
+ continue;
+ else {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ /*
+ * this is the queue directory - read this and the
+ * iosched directory too
+ */
+ dlist_for_each_data(dir->subdirs, new,
+ struct sysfs_directory) {
+ if ((strcmp(new->name, SYSFS_IOSCHED_NAME)) == 0)
+ if ((sysfs_read_directory(new)) == 0)
+ return new->attributes;
+ }
+ }
+ dprintf("IOSCHED attributes not found\n");
+ return NULL;
+}
+
diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c
index 6c969b5..9172a1e 100644
--- a/lib/sysfs_class.c
+++ b/lib/sysfs_class.c
@@ -264,7 +264,7 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name)
cls = alloc_class();
if (cls == NULL) {
- perror("malloc");
+ perror("calloc");
return NULL;
}
strcpy(cls->name, name);
diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c
index 1d730e7..46ebd52 100644
--- a/lib/sysfs_dir.c
+++ b/lib/sysfs_dir.c
@@ -525,10 +525,11 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
}
}
- if (sysdir->attributes == NULL)
+ if (sysdir->attributes == NULL) {
sysdir->attributes = dlist_new_with_delete
(sizeof(struct sysfs_attribute),
sysfs_del_attribute);
+ }
dlist_unshift(sysdir->attributes, attr);
} else if (S_ISDIR(astats.st_mode)) {
subdir = sysfs_open_directory(file_path);