[PATCH] added libsysfs code from sysutils-0.1.1-071803 release

This commit is contained in:
greg@kroah.com 2003-07-18 20:08:00 -07:00 committed by Greg KH
parent 469c7cff3b
commit 070f54223f
10 changed files with 2210 additions and 0 deletions

441
libsysfs/LGPL Normal file
View File

@ -0,0 +1,441 @@
GNU Lesser Public License
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to
share and change it. By contrast, the GNU General Public Licenses are
intended to guarantee your freedom to share and change free software--to
make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially
designated software packages--typically libraries--of the Free Software
Foundation and other authors who decide to use it. You can use it too, but
we suggest you first think carefully about whether this license or the
ordinary General Public License is the better strategy to use in any
particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not
price. Our General Public Licenses are designed to make sure that you have
the freedom to distribute copies of free software (and charge for this
service if you wish); that you receive source code or can get it if you
want it; that you can change the software and use pieces of it in new free
programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for you
if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or
for a fee, you must give the recipients all the rights that we gave you.
You must make sure that they, too, receive or can get the source code. If
you link other code with the library, you must provide complete object
files to the recipients, so that they can relink them with the library
after making changes to the library and recompiling it. And you must show
them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that there is
no warranty for the free library. Also, if the library is modified by
someone else and passed on, the recipients should know that what they have
is not the original version, so that the original author's reputation will
not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any
free program. We wish to make sure that a company cannot effectively
restrict the users of a free program by obtaining a restrictive license
from a patent holder. Therefore, we insist that any patent license
obtained for a version of the library must be consistent with the full
freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License. This license, the GNU Lesser General Public
License, applies to certain designated libraries, and is quite different
from the ordinary General Public License. We use this license for certain
libraries in order to permit linking those libraries into non-free
programs.
When a program is linked with a library, whether statically or using a
shared library, the combination of the two is legally speaking a combined
work, a derivative of the original library. The ordinary General Public
License therefore permits such linking only if the entire combination fits
its criteria of freedom. The Lesser General Public License permits more
lax criteria for linking other code with the library.
We call this license the "Lesser" General Public License because it does
Less to protect the user's freedom than the ordinary General Public
License. It also provides other free software developers Less of an
advantage over competing non-free programs. These disadvantages are the
reason we use the ordinary General Public License for many libraries.
However, the Lesser license provides advantages in certain special
circumstances.
For example, on rare occasions, there may be a special need to encourage
the widest possible use of a certain library, so that it becomes a
de-facto standard. To achieve this, non-free programs must be allowed to
use the library. A more frequent case is that a free library does the same
job as widely used non-free libraries. In this case, there is little to
gain by limiting the free library to free software only, so we use the
Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of free
software. For example, permission to use the GNU C Library in non-free
programs enables many more people to use the whole GNU operating system,
as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is linked
with the Library has the freedom and the wherewithal to run that program
using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a "work
based on the library" and a "work that uses the library". The former
contains code derived from the library, whereas the latter must be
combined with the library in order to run.
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other program
which contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Lesser General
Public License (also called "this License"). Each licensee is addressed as
"you".
A "library" means a collection of software functions and/or data prepared
so as to be conveniently linked with application programs (which use some
of those functions and data) to form executables.
The "Library", below, refers to any such software library or work which
has been distributed under these terms. A "work based on the Library"
means either the Library or any derivative work under copyright law: that
is to say, a work containing the Library or a portion of it, either
verbatim or with modifications and/or translated straightforwardly into
another language. (Hereinafter, translation is included without limitation
in the term "modification".)
"Source code" for a work means the preferred form of the work for making
modifications to it. For a library, complete source code means all the
source code for all modules it contains, plus any associated interface
definition files, plus the scripts used to control compilation and
installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of running a
program using the Library is not restricted, and output from such a
program is covered only if its contents constitute a work based on the
Library (independent of the use of the Library in a tool for writing it).
Whether that is true depends on what the Library does and what the program
that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's complete
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the notices
that refer to this License and to the absence of any warranty; and
distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you
may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it,
thus forming a work based on the Library, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that
you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices stating
that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no charge to
all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a table
of data to be supplied by an application program that uses the facility,
other than as an argument passed when the facility is invoked, then you
must make a good faith effort to ensure that, in the event an
application does not supply such function or table, the facility still
operates, and performs whatever part of its purpose remains meaningful.
(For example, a function in a library to compute square roots has a
purpose that is entirely well-defined independent of the application.
Therefore, Subsection 2d requires that any application-supplied function
or table used by this function must be optional: if the application does
not supply it, the square root function must still compute square
roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library, and
can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based on
the Library, the distribution of the whole must be on the terms of this
License, whose permissions for other licensees extend to the entire
whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of a
storage or distribution medium does not bring the other work under the
scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so that
they refer to the ordinary GNU General Public License, version 2, instead
of to this License. (If a newer version than version 2 of the ordinary GNU
General Public License has appeared, then you can specify that version
instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that
copy, so the ordinary GNU General Public License applies to all subsequent
copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of the
Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of
it, under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you accompany it with the complete
corresponding machine-readable source code, which must be distributed
under the terms of Sections 1 and 2 above on a medium customarily used for
software interchange.
If distribution of object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source code
from the same place satisfies the requirement to distribute the source
code, even though third parties are not compelled to copy the source along
with the object code.
5. A program that contains no derivative of any portion of the Library,
but is designed to work with the Library by being compiled or linked with
it, is called a "work that uses the Library". Such a work, in isolation,
is not a derivative work of the Library, and therefore falls outside the
scope of this License.
However, linking a "work that uses the Library" with the Library creates
an executable that is a derivative of the Library (because it contains
portions of the Library), rather than a "work that uses the library". The
executable is therefore covered by this License. Section 6 states terms
for distribution of such executables.
When a "work that uses the Library" uses material from a header file that
is part of the Library, the object code for the work may be a derivative
work of the Library even though the source code is not. Whether this is
true is especially significant if the work can be linked without the
Library, or if the work is itself a library. The threshold for this to be
true is not precisely defined by law.
If such an object file uses only numerical parameters, data structure
layouts and accessors, and small macros and small inline functions (ten
lines or less in length), then the use of the object file is unrestricted,
regardless of whether it is legally a derivative work. (Executables
containing this object code plus portions of the Library will still fall
under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute
the object code for the work under the terms of Section 6. Any executables
containing that work also fall under Section 6, whether or not they are
linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a
"work that uses the Library" with the Library to produce a work containing
portions of the Library, and distribute that work under terms of your
choice, provided that the terms permit modification of the work for the
customer's own use and reverse engineering for debugging such
modifications.
You must give prominent notice with each copy of the work that the Library
is used in it and that the Library and its use are covered by this
License. You must supply a copy of this License. If the work during
execution displays copyright notices, you must include the copyright
notice for the Library among them, as well as a reference directing the
user to the copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete corresponding machine-readable
source code for the Library including whatever changes were used in the
work (which must be distributed under Sections 1 and 2 above); and, if
the work is an executable linked with the Library, with the complete
machine-readable "work that uses the Library", as object code and/or
source code, so that the user can modify the Library and then relink to
produce a modified executable containing the modified Library. (It is
understood that the user who changes the contents of definitions files
in the Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the Library.
A suitable mechanism is one that (1) uses at run time a copy of the
library already present on the user's computer system, rather than
copying library functions into the executable, and (2) will operate
properly with a modified version of the library, if the user installs
one, as long as the modified version is interface-compatible with the
version that the work was made with.
c) Accompany the work with a written offer, valid for at least three
years, to give the same user the materials specified in Subsection 6a,
above, for a charge no more than the cost of performing this
distribution.
d) If distribution of the work is made by offering access to copy from a
designated place, offer equivalent access to copy the above specified
materials from the same place.
e) Verify that the user has already received a copy of these materials
or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the Library"
must include any data and utility programs needed for reproducing the
executable from it. However, as a special exception, the materials to be
distributed need not include anything that is normally distributed (in
either source or binary form) with the major components (compiler, kernel,
and so on) of the operating system on which the executable runs, unless
that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions
of other proprietary libraries that do not normally accompany the
operating system. Such a contradiction means you cannot use both them and
the Library together in an executable that you distribute.
7. You may place library facilities that are a work based on the Library
side-by-side in a single library together with other library facilities
not covered by this License, and distribute such a combined library,
provided that the separate distribution of the work based on the Library
and of the other library facilities is otherwise permitted, and provided
that you do these two things:
a) Accompany the combined library with a copy of the same work based on
the Library, uncombined with any other library facilities. This must be
distributed under the terms of the Sections above.
b) Give prominent notice with the combined library of the fact that part
of it is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the
Library except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, link with, or distribute the
Library is void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights, from you
under this License will not have their licenses terminated so long as such
parties remain in full compliance.
9. You are not required to accept this License, since you have not signed
it. However, nothing else grants you permission to modify or distribute
the Library or its derivative works. These actions are prohibited by law
if you do not accept this License. Therefore, by modifying or distributing
the Library (or any work based on the Library), you indicate your
acceptance of this License to do so, and all its terms and conditions for
copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the original
licensor to copy, distribute, link with or modify the Library subject to
these terms and conditions. You may not impose any further restrictions on
the recipients' exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot distribute
so as to satisfy simultaneously your obligations under this License and
any other pertinent obligations, then as a consequence you may not
distribute the Library at all. For example, if a patent license would not
permit royalty-free redistribution of the Library by all those who receive
copies directly or indirectly through you, then the only way you could
satisfy both it and this License would be to refrain entirely from
distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any such
claims; this section has the sole purpose of protecting the integrity of
the free software distribution system which is implemented by public
license practices. Many people have made generous contributions to the
wide range of software distributed through that system in reliance on
consistent application of that system; it is up to the author/donor to
decide if he or she is willing to distribute software through any other
system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain
countries either by patents or by copyrighted interfaces, the original
copyright holder who places the Library under this License may add an
explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions
of the Lesser General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail
to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Library does not specify a license version
number, you may choose any version ever published by the Free Software
Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these, write
to the author to ask for permission. For software which is copyrighted by
the Free Software Foundation, write to the Free Software Foundation; we
sometimes make exceptions for this. Our decision will be guided by the two
goals of preserving the free status of all derivatives of our free
software and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE
LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT
LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES
SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE
WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

44
libsysfs/Makefile Normal file
View File

@ -0,0 +1,44 @@
# Makefile for libsysfs.a
# Copyright (c) International Business Machines Corp., 2003
CC=gcc
H_INCLUDE=../include
LIB_INCLUDE=.
OBJS=sysfs_bus.o sysfs_class.o sysfs_device.o sysfs_dir.o sysfs_driver.o \
sysfs_utils.o
# Install directory
# Options
CFLAGS=-O2 -Wall -ansi -g
# sysfs library
LIBSYSFS=libsysfs.a
RM=rm -f
libsysfs.a: $(OBJS)
ar cru $(LIBSYSFS) $(OBJS)
ranlib $(LIBSYSFS)
sysfs_bus.o: sysfs_bus.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_bus.c
sysfs_class.o: sysfs_class.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_class.c
sysfs_device.o: sysfs_device.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_device.c
sysfs_dir.o: sysfs_dir.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_dir.c
sysfs_driver.o: sysfs_driver.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_driver.c
sysfs_utils.o: sysfs_utils.c
$(CC) -I$(H_INCLUDE) -I$(LIB_INCLUDE) $(CFLAGS) -c sysfs_utils.c
clean:
$(RM) *.o *~ core $(LIBSYSFS)

162
libsysfs/libsysfs.h Normal file
View File

@ -0,0 +1,162 @@
/*
* libsysfs.h
*
* Header Definitions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#ifndef _LIBSYSFS_H_
#define _LIBSYSFS_H_
#include <sys/types.h>
/*
* Generic #defines go here..
*/
#define SYSFS_FSTYPE_NAME "sysfs"
#define SYSFS_PROC_MNTS "/proc/mounts"
#define SYSFS_BUS_DIR "/bus"
#define SYSFS_CLASS_DIR "/class"
#define SYSFS_DEVICES_DIR "/devices"
#define SYSFS_DEVICES_NAME "devices"
#define SYSFS_DRIVERS_DIR "/drivers"
#define SYSFS_DRIVERS_NAME "drivers"
#define SYSFS_NAME_ATTRIBUTE "name"
#define SYSFS_PATH_MAX 255
#define SYSFS_NAME_LEN 50
#define SYSFS_BUS_ID_SIZE 20
#define SYSFS_METHOD_SHOW 0x01 /* attr can be read by user */
#define SYSFS_METHOD_STORE 0x02 /* attr can be changed by user */
struct sysfs_attribute {
struct sysfs_attribute *next;
char path[SYSFS_PATH_MAX];
char *value;
unsigned short len; /* value length */
unsigned short method; /* show and store */
};
struct sysfs_dlink {
struct sysfs_dlink *next;
char name[SYSFS_NAME_LEN];
struct sysfs_directory *target;
};
struct sysfs_directory {
struct sysfs_directory *next;
char path[SYSFS_PATH_MAX];
struct sysfs_directory *subdirs;
struct sysfs_dlink *links;
struct sysfs_attribute *attributes;
};
struct sysfs_driver {
struct sysfs_driver *next;
char name[SYSFS_NAME_LEN];
struct sysfs_directory *directory;
struct sysfs_device *device;
};
struct sysfs_device {
struct sysfs_device *next;
char name[SYSFS_NAME_LEN];
char bus_id[SYSFS_NAME_LEN];
struct sysfs_driver *driver;
struct sysfs_directory *directory;
struct sysfs_device *parent;
struct sysfs_device *children;
};
struct sysfs_bus {
struct sysfs_bus *next;
char name[SYSFS_NAME_LEN];
struct sysfs_directory *directory;
struct sysfs_driver *drivers;
struct sysfs_device *devices;
};
struct sysfs_class_device {
struct sysfs_class_device *next;
char name[SYSFS_NAME_LEN];
struct sysfs_directory *directory;
struct sysfs_device *sysdevice; /* NULL if virtual */
struct sysfs_driver *driver; /* NULL if not implemented */
};
struct sysfs_class {
struct sysfs_class *next;
char name[SYSFS_NAME_LEN];
struct sysfs_directory *directory;
struct sysfs_class_device *devices;
};
#ifdef __cplusplus
extern "C" {
#endif
/*
* Function Prototypes
*/
extern int sysfs_get_mnt_path(char *mnt_path, size_t len);
extern int sysfs_get_name_from_path(const char *path, char *name, size_t len);
extern int sysfs_get_link(const char *path, char *target, size_t len);
/* sysfs directory and file access */
extern void sysfs_close_attribute(struct sysfs_attribute *sysattr);
extern struct sysfs_attribute *sysfs_open_attribute(const char *path);
extern int sysfs_read_attribute(struct sysfs_attribute *sysattr);
extern int sysfs_read_attribute_value(const char *attrpath, char *value,
size_t vsize);
extern char *sysfs_get_value_from_attributes(struct sysfs_attribute *attr,
const char * name);
extern void sysfs_close_directory(struct sysfs_directory *sysdir);
extern struct sysfs_directory *sysfs_open_directory(const char *path);
extern int sysfs_read_directory(struct sysfs_directory *sysdir);
extern void sysfs_close_dlink(struct sysfs_dlink *dlink);
extern struct sysfs_dlink *sysfs_open_dlink(const char *linkpath);
extern int sysfs_read_dlinks(struct sysfs_dlink *dlink);
/* sysfs driver access */
extern void sysfs_close_driver(struct sysfs_driver *driver);
extern struct sysfs_driver *sysfs_open_driver(const char *path);
/* generic sysfs device access */
extern void sysfs_close_device(struct sysfs_device *dev);
extern void sysfs_close_device_tree(struct sysfs_device *dev);
extern struct sysfs_device *sysfs_open_device(const char *path);
extern struct sysfs_device *sysfs_open_device_tree(const char *path);
extern struct sysfs_attribute *sysfs_get_device_attr
(struct sysfs_device *dev, const char *name);
/* generic sysfs bus access */
extern void sysfs_close_bus(struct sysfs_bus *bus);
extern struct sysfs_bus *sysfs_open_bus(const char *name);
/* generic sysfs class access */
extern void sysfs_close_class_device(struct sysfs_class_device *dev);
extern struct sysfs_class_device *sysfs_open_class_device(const char *path);
extern void sysfs_close_class(struct sysfs_class *cls);
extern struct sysfs_class *sysfs_open_class(const char *name);
#ifdef __cplusplus
}
#endif
#endif /* _LIBSYSFS_H_ */

49
libsysfs/sysfs.h Normal file
View File

@ -0,0 +1,49 @@
/*
* sysfs.h
*
* Internal Header Definitions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#ifndef _SYSFS_H_
#define _SYSFS_H_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <mntent.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
/* external library functions */
extern int lstat(const char *file_name, struct stat *buf);
extern int readlink(const char *path, char *buf, size_t bufsize);
extern int getpagesize(void);
extern int isascii(int c);
/* Debugging */
#ifdef DEBUG
#define dprintf(format, arg...) fprintf(stderr, format, ## arg)
#else
#define dprintf(format, arg...) do { } while (0)
#endif
#endif /* _SYSFS_H_ */

301
libsysfs/sysfs_bus.c Normal file
View File

@ -0,0 +1,301 @@
/*
* sysfs_bus.c
*
* Generic bus utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_close_bus: close single bus
* @bus: bus structure
*/
void sysfs_close_bus(struct sysfs_bus *bus)
{
struct sysfs_device *curdev = NULL, *nextdev = NULL;
struct sysfs_driver *curdrv = NULL, *nextdrv = NULL;
if (bus != NULL) {
if (bus->directory != NULL)
sysfs_close_directory(bus->directory);
for (curdev = bus->devices; curdev != NULL;
curdev = nextdev) {
nextdev = curdev->next;
sysfs_close_device(curdev);
}
for (curdrv = bus->drivers; curdrv != NULL;
curdrv = nextdrv) {
nextdrv = curdrv->next;
sysfs_close_driver(curdrv);
}
free(bus);
}
}
/**
* alloc_bus: mallocs new bus structure
* returns sysfs_bus_bus struct or NULL
*/
static struct sysfs_bus *alloc_bus(void)
{
return (struct sysfs_bus *)calloc(1, sizeof(struct sysfs_bus));
}
/**
* open_bus_dir: opens up sysfs bus directory
* returns sysfs_directory struct with success and NULL with error
*/
static struct sysfs_directory *open_bus_dir(const char *name)
{
struct sysfs_directory *busdir = NULL, *cur = NULL, *next = NULL;
char buspath[SYSFS_PATH_MAX];
if (name == NULL) {
errno = EINVAL;
return NULL;
}
memset(buspath, 0, SYSFS_PATH_MAX);
if ((sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) != 0) {
dprintf(stderr, "Sysfs not supported on this system\n");
return NULL;
}
strcat(buspath, SYSFS_BUS_DIR);
strcat(buspath, "/");
strcat(buspath, name);
busdir = sysfs_open_directory(buspath);
if (busdir == NULL) {
errno = EINVAL;
dprintf(stderr,"Bus %s not supported on this system\n",
name);
return NULL;
}
if ((sysfs_read_directory(busdir)) != 0) {
dprintf(stderr, "Error reading %s bus dir %s\n", name,
buspath);
sysfs_close_directory(busdir);
return NULL;
}
/* read in devices and drivers subdirs */
for (cur = busdir->subdirs; cur != NULL; cur = next) {
next = cur->next;
if ((sysfs_read_directory(cur)) != 0)
continue;
}
return busdir;
}
/**
* add_dev_to_bus: adds a bus device to bus device list
* @bus: bus to add the device
* @dev: device to add
*/
static void add_dev_to_bus(struct sysfs_bus *bus, struct sysfs_device *dev)
{
if (bus != NULL && dev != NULL) {
dev->next = bus->devices;
bus->devices = dev;
}
}
/**
* add_driver_to_bus: adds a bus driver to bus driver list
* @bus: bus to add driver to
* @driver: driver to add
*/
static void add_driver_to_bus(struct sysfs_bus *bus,
struct sysfs_driver *driver)
{
if (bus != NULL && driver != NULL) {
driver->next = bus->drivers;
bus->drivers = driver;
}
}
/**
* get_all_bus_devices: gets all devices for bus
* @bus: bus to get devices for
* returns 0 with success and -1 with failure
*/
static int get_all_bus_devices(struct sysfs_bus *bus)
{
struct sysfs_device *bdev = NULL;
struct sysfs_directory *cur = NULL;
struct sysfs_dlink *curl = NULL, *nextl = NULL;
char dirname[SYSFS_NAME_LEN];
if (bus == NULL || bus->directory == NULL) {
errno = EINVAL;
return -1;
}
for (cur = bus->directory->subdirs; cur != NULL; cur = cur->next) {
memset(dirname, 0, SYSFS_NAME_LEN);
if ((sysfs_get_name_from_path(cur->path, dirname,
SYSFS_NAME_LEN)) != 0)
continue;
if (strcmp(dirname, SYSFS_DEVICES_NAME) != 0)
continue;
for (curl = cur->links; curl != NULL; curl = nextl) {
nextl = curl->next;
bdev = sysfs_open_device(curl->target->path);
if (bdev == NULL) {
dprintf(stderr, "Error opening device at %s\n",
curl->target->path);
continue;
}
add_dev_to_bus(bus, bdev);
}
}
return 0;
}
/**
* get_all_bus_drivers: get all pci drivers
* @bus: pci bus to add drivers to
* returns 0 with success and -1 with error
*/
static int get_all_bus_drivers(struct sysfs_bus *bus)
{
struct sysfs_driver *driver = NULL;
struct sysfs_directory *cur = NULL, *next = NULL;
struct sysfs_directory *cursub = NULL, *nextsub = NULL;
char dirname[SYSFS_NAME_LEN];
if (bus == NULL || bus->directory == NULL) {
errno = EINVAL;
return -1;
}
for (cur = bus->directory->subdirs; cur != NULL; cur = next) {
next = cur->next;
memset(dirname, 0, SYSFS_NAME_LEN);
if ((sysfs_get_name_from_path(cur->path, dirname,
SYSFS_NAME_LEN)) != 0)
continue;
if (strcmp(dirname, SYSFS_DRIVERS_NAME) != 0)
continue;
for (cursub = cur->subdirs; cursub != NULL; cursub = nextsub) {
nextsub = cursub->next;
driver = sysfs_open_driver(cursub->path);
if (driver == NULL) {
dprintf(stderr, "Error opening driver at %s\n",
cursub->path);
continue;
}
add_driver_to_bus(bus, driver);
}
}
return 0;
}
/**
* match_bus_device_to_driver: returns 1 if device is bound to driver
* @driver: driver to match
* @busid: busid of device to match
* returns 1 if found and 0 if not found
*/
static int match_bus_device_to_driver(struct sysfs_driver *driver, char *busid)
{
struct sysfs_dlink *cur = NULL, *next = NULL;
int found = 0;
if (driver == NULL || driver->directory == NULL || busid == NULL) {
errno = EINVAL;
return found;
}
for (cur = driver->directory->links; cur != NULL && found == 0;
cur = next) {
next = cur->next;
if ((strcmp(cur->name, busid)) == 0)
found++;
}
return found;
}
/**
* link_bus_devices_to_drivers: goes through and links devices to drivers
* @bus: bus to link
*/
static void link_bus_devices_to_drivers(struct sysfs_bus *bus)
{
struct sysfs_device *dev = NULL, *nextdev = NULL;
struct sysfs_driver *drv = NULL, *nextdrv = NULL;
if (bus != NULL && bus->devices != NULL && bus->drivers != NULL) {
for (dev = bus->devices; dev != NULL; dev = nextdev) {
nextdev = dev->next;
for (drv = bus->drivers; drv != NULL; drv = nextdrv) {
nextdrv = drv->next;
if ((match_bus_device_to_driver(drv,
dev->bus_id)) != 0) {
dev->driver = drv;
drv->device = dev;
}
}
}
}
}
/**
* sysfs_open_bus: opens specific bus and all its devices on system
* returns sysfs_bus structure with success or NULL with error.
*/
struct sysfs_bus *sysfs_open_bus(const char *name)
{
struct sysfs_bus *bus = NULL;
struct sysfs_directory *busdir = NULL;
if (name == NULL) {
errno = EINVAL;
return NULL;
}
bus = alloc_bus();
if (bus == NULL) {
perror("malloc");
return NULL;
}
strcpy(bus->name, name);
busdir = open_bus_dir(name);
if (busdir == NULL) {
dprintf(stderr,"Invalid bus, %s not supported on this system\n",
name);
sysfs_close_bus(bus);
return NULL;
}
bus->directory = busdir;
if ((get_all_bus_devices(bus)) != 0) {
dprintf(stderr, "Error reading %s bus devices\n", name);
sysfs_close_bus(bus);
return NULL;
}
if ((get_all_bus_drivers(bus)) != 0) {
dprintf(stderr, "Error reading %s bus drivers\n", name);
sysfs_close_bus(bus);
return NULL;
}
link_bus_devices_to_drivers(bus);
return bus;
}

273
libsysfs/sysfs_class.c Normal file
View File

@ -0,0 +1,273 @@
/*
* sysfs_class.c
*
* Generic class utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_close_class_device: closes a single class device.
* @dev: class device to close.
*/
void sysfs_close_class_device(struct sysfs_class_device *dev)
{
if (dev != NULL) {
if (dev->directory != NULL)
sysfs_close_directory(dev->directory);
if (dev->sysdevice != NULL)
sysfs_close_device(dev->sysdevice);
if (dev->driver != NULL)
sysfs_close_driver(dev->driver);
free(dev);
}
}
/**
* sysfs_close_class: close single class
* @class: class structure
*/
void sysfs_close_class(struct sysfs_class *cls)
{
struct sysfs_class_device *cur = NULL, *next = NULL;
if (cls != NULL) {
if (cls->directory != NULL)
sysfs_close_directory(cls->directory);
for (cur = cls->devices; cur != NULL; cur = next) {
next = cur->next;
sysfs_close_class_device(cur);
}
free(cls);
}
}
/**
* alloc_class_device: mallocs and initializes new class device struct.
* returns sysfs_class_device or NULL.
*/
static struct sysfs_class_device *alloc_class_device(void)
{
return (struct sysfs_class_device *)
calloc(1, sizeof(struct sysfs_class_device));
}
/**
* alloc_class: mallocs new class structure
* returns sysfs_class struct or NULL
*/
static struct sysfs_class *alloc_class(void)
{
return (struct sysfs_class *)calloc(1, sizeof(struct sysfs_class));
}
/**
* open_class_dir: opens up sysfs class directory
* returns sysfs_directory struct with success and NULL with error
*/
static struct sysfs_directory *open_class_dir(const char *name)
{
struct sysfs_directory *classdir = NULL;
char classpath[SYSFS_PATH_MAX];
if (name == NULL) {
errno = EINVAL;
return NULL;
}
memset(classpath, 0, SYSFS_PATH_MAX);
if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) {
dprintf(stderr, "Sysfs not supported on this system\n");
return NULL;
}
strcat(classpath, SYSFS_CLASS_DIR);
strcat(classpath, "/");
strcat(classpath, name);
classdir = sysfs_open_directory(classpath);
if (classdir == NULL) {
errno = EINVAL;
dprintf(stderr,"Class %s not supported on this system\n",
name);
return NULL;
}
if ((sysfs_read_directory(classdir)) != 0) {
dprintf(stderr, "Error reading %s class dir %s\n", name,
classpath);
sysfs_close_directory(classdir);
return NULL;
}
return classdir;
}
/**
* sysfs_open_class_device: Opens and populates class device
* @path: path to class device.
* returns struct sysfs_class_device with success and NULL with error.
*/
struct sysfs_class_device *sysfs_open_class_device(const char *path)
{
struct sysfs_class_device *cdev = NULL;
struct sysfs_directory *dir = NULL, *cur = NULL;
struct sysfs_dlink *curl = NULL;
struct sysfs_device *sdev = NULL;
struct sysfs_driver *drv = NULL;
char temp[SYSFS_NAME_LEN];
if (path == NULL) {
errno = EINVAL;
return NULL;
}
cdev = alloc_class_device();
if (cdev == NULL) {
perror("malloc");
return NULL;
}
memset(temp, 0, SYSFS_NAME_LEN);
if ((sysfs_get_name_from_path(path, temp, SYSFS_NAME_LEN)) != 0) {
errno = EINVAL;
dprintf(stderr, "Invalid class device path %s\n", path);
sysfs_close_class_device(cdev);
return NULL;
}
strcpy(cdev->name, temp);
dir = sysfs_open_directory(path);
if (dir == NULL) {
dprintf(stderr, "Error opening class device at %s\n", path);
sysfs_close_class_device(cdev);
return NULL;
}
if ((sysfs_read_directory(dir)) != 0) {
dprintf(stderr, "Error reading class device at %s\n", path);
sysfs_close_directory(dir);
sysfs_close_class_device(cdev);
return NULL;
}
cdev->directory = dir;
cur = cdev->directory->subdirs;
while(cur != NULL) {
sysfs_read_directory(cur);
cur = cur->next;
}
/* get driver and device, if implemented */
curl = cdev->directory->links;
while (curl != NULL) {
if (strncmp(curl->name, SYSFS_DEVICES_NAME, 6) == 0) {
sdev = sysfs_open_device(curl->target->path);
if (sdev != NULL) {
cdev->sysdevice = sdev;
if (cdev->driver != NULL)
sdev->driver = cdev->driver;
}
} else if (strncmp(curl->name, SYSFS_DRIVERS_NAME, 6) == 0) {
drv = sysfs_open_driver(curl->target->path);
if (drv != NULL) {
cdev->driver = drv;
if (cdev->sysdevice != NULL)
drv->device = cdev->sysdevice;
}
}
curl = curl->next;
}
return cdev;
}
/**
* add_dev_to_class: adds a class device to class list
* @class: class to add the device
* @dev: device to add
*/
static void add_dev_to_class(struct sysfs_class *cls,
struct sysfs_class_device *dev)
{
if (cls != NULL && dev != NULL) {
dev->next = cls->devices;
cls->devices = dev;
}
}
/**
* get_all_class_devices: gets all devices for class
* @class: class to get devices for
* returns 0 with success and -1 with failure
*/
static int get_all_class_devices(struct sysfs_class *cls)
{
struct sysfs_class_device *dev = NULL;
struct sysfs_directory *cur = NULL, *next = NULL;
if (cls == NULL || cls->directory == NULL) {
errno = EINVAL;
return -1;
}
for (cur = cls->directory->subdirs; cur != NULL; cur = next) {
next = cur->next;
dev = sysfs_open_class_device(cur->path);
if (dev == NULL) {
dprintf(stderr, "Error opening device at %s\n",
cur->path);
continue;
}
add_dev_to_class(cls, dev);
}
return 0;
}
/**
* sysfs_open_class: opens specific class and all its devices on system
* returns sysfs_class structure with success or NULL with error.
*/
struct sysfs_class *sysfs_open_class(const char *name)
{
struct sysfs_class *cls = NULL;
struct sysfs_directory *classdir = NULL;
if (name == NULL) {
errno = EINVAL;
return NULL;
}
cls = alloc_class();
if (cls == NULL) {
perror("malloc");
return NULL;
}
strcpy(cls->name, name);
classdir = open_class_dir(name);
if (classdir == NULL) {
dprintf(stderr,
"Invalid class, %s not supported on this system\n",
name);
sysfs_close_class(cls);
return NULL;
}
cls->directory = classdir;
if ((get_all_class_devices(cls)) != 0) {
dprintf(stderr, "Error reading %s class devices\n", name);
sysfs_close_class(cls);
return NULL;
}
return cls;
}

199
libsysfs/sysfs_device.c Normal file
View File

@ -0,0 +1,199 @@
/*
* sysfs_device.c
*
* Generic device utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_close_device: closes and cleans up a device
* @dev = device to clean up
*/
void sysfs_close_device(struct sysfs_device *dev)
{
if (dev != NULL) {
dev->next = NULL;
dev->driver = NULL;
if (dev->directory != NULL)
sysfs_close_directory(dev->directory);
dev->children = NULL;
free(dev);
}
}
/**
* alloc_device: allocates and initializes device structure
* returns struct sysfs_device
*/
static struct sysfs_device *alloc_device(void)
{
return (struct sysfs_device *)calloc(1, sizeof(struct sysfs_device));
}
/**
* sysfs_get_device_attr: searches dev's attributes by name
* @dev: device to look through
* @name: attribute name to get
* returns sysfs_attribute reference with success or NULL with error.
*/
struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
const char *name)
{
struct sysfs_attribute *cur = NULL;
char attrname[SYSFS_NAME_LEN];
if (dev == NULL || dev->directory == NULL || name == NULL) {
errno = EINVAL;
return NULL;
}
for (cur = dev->directory->attributes; cur != NULL; cur = cur->next) {
if ((sysfs_get_name_from_path(cur->path, attrname,
SYSFS_NAME_LEN)) != 0)
continue;
if (strcmp(name, attrname) != 0)
continue;
return cur;
}
return NULL;
}
/**
* sysfs_open_device: opens and populates device structure
* @path: path to device, this is the /sys/devices/ path
* returns sysfs_device structure with success or NULL with error
*/
struct sysfs_device *sysfs_open_device(const char *path)
{
struct sysfs_device *dev = NULL;
struct sysfs_directory *sdir = NULL;
char *p = NULL;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
dev = alloc_device();
if (dev == NULL) {
dprintf(stderr, "Error allocating device at %s\n", path);
return NULL;
}
sdir = sysfs_open_directory(path);
if (sdir == NULL) {
dprintf(stderr, "Invalid device at %s\n", path);
errno = EINVAL;
sysfs_close_device(dev);
return NULL;
}
if ((sysfs_read_directory(sdir)) != 0) {
dprintf(stderr, "Error reading device directory at %s\n", path);
sysfs_close_directory(sdir);
sysfs_close_device(dev);
return NULL;
}
dev->directory = sdir;
sysfs_get_name_from_path(sdir->path, dev->bus_id, SYSFS_NAME_LEN);
/* get device name */
p = sysfs_get_value_from_attributes(sdir->attributes,
SYSFS_NAME_ATTRIBUTE);
if (p != NULL) {
strncpy(dev->name, p, SYSFS_NAME_LEN);
p = dev->name + strlen(dev->name) - 1;
if ((strlen(dev->name) > 0) && *p == '\n')
*p = '\0';
}
return dev;
}
/**
* sysfs_close_device_tree: closes every device in the supplied tree,
* closing children only.
* @devroot: device root of tree.
*/
void sysfs_close_device_tree(struct sysfs_device *devroot)
{
if (devroot != NULL) {
if (devroot->children != NULL) {
struct sysfs_device *child = NULL, *next = NULL;
for (child = devroot->children; child != NULL;
child = next) {
next = child->next;
sysfs_close_device_tree(child);
}
}
sysfs_close_device(devroot);
}
}
/**
* add_device_child_to_parent: adds child device to parent
* @parent: parent device.
* @child: child device to add.
*/
static void add_device_child_to_parent(struct sysfs_device *parent,
struct sysfs_device *child)
{
if (parent != NULL && child != NULL) {
child->next = parent->children;
parent->children = child;
child->parent = parent;
}
}
/**
* sysfs_open_device_tree: opens root device and all of its children,
* creating a tree of devices. Only opens children.
* @path: sysfs path to devices
* returns struct sysfs_device and its children with success or NULL with
* error.
*/
struct sysfs_device *sysfs_open_device_tree(const char *path)
{
struct sysfs_device *rootdev = NULL, *new = NULL;
struct sysfs_directory *cur = NULL;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
rootdev = sysfs_open_device(path);
if (rootdev == NULL) {
dprintf(stderr, "Error opening root device at %s\n", path);
return NULL;
}
cur = rootdev->directory->subdirs;
while (cur != NULL) {
new = sysfs_open_device_tree(cur->path);
if (new == NULL) {
dprintf(stderr, "Error opening device tree at %s\n",
cur->path);
sysfs_close_device_tree(rootdev);
return NULL;
}
add_device_child_to_parent(rootdev, new);
cur = cur->next;
}
return rootdev;
}

496
libsysfs/sysfs_dir.c Normal file
View File

@ -0,0 +1,496 @@
/*
* syfs_dir.c
*
* Directory utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_close_attribute: closes and cleans up attribute
* @sysattr: attribute to close.
*/
void sysfs_close_attribute(struct sysfs_attribute *sysattr)
{
if (sysattr != NULL) {
if (sysattr->value != NULL)
free(sysattr->value);
free(sysattr);
}
}
/**
* alloc_attribute: allocates and initializes attribute structure
* returns struct sysfs_attribute with success and NULL with error.
*/
static struct sysfs_attribute *alloc_attribute(void)
{
return (struct sysfs_attribute *)
calloc(1, sizeof(struct sysfs_attribute));
}
/**
* sysfs_open_attribute: creates sysfs_attribute structure
* @path: path to attribute.
* returns sysfs_attribute struct with success and NULL with error.
*/
struct sysfs_attribute *sysfs_open_attribute(const char *path)
{
struct sysfs_attribute *sysattr = NULL;
struct stat fileinfo;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
sysattr = alloc_attribute();
if (sysattr == NULL) {
dprintf(stderr, "Error allocating attribute at %s\n", path);
return NULL;
}
strncpy(sysattr->path, path, sizeof(sysattr->path));
if ((stat(sysattr->path, &fileinfo)) != 0) {
perror("stat");
sysattr->method = 0;
} else {
if (fileinfo.st_mode & S_IRUSR)
sysattr->method |= SYSFS_METHOD_SHOW;
if (fileinfo.st_mode & S_IWUSR)
sysattr->method |= SYSFS_METHOD_STORE;
}
return sysattr;
}
/**
* sysfs_read_attribute: reads value from attribute
* @sysattr: attribute to read
* returns 0 with success and -1 with error.
*/
int sysfs_read_attribute(struct sysfs_attribute *sysattr)
{
char *fbuf = NULL;
char *vbuf = NULL;
size_t length = 0;
int pgsize = 0;
int fd;
if (sysattr == NULL) {
errno = EINVAL;
return -1;
}
if (!(sysattr->method & SYSFS_METHOD_SHOW)) {
dprintf (stderr, "Show method not supported for attribute %s\n",
sysattr->path);
return -1;
}
pgsize = getpagesize();
fbuf = (char *)calloc(1, pgsize+1);
if (fbuf == NULL) {
perror("calloc");
return -1;
}
if ((fd = open(sysattr->path, O_RDONLY)) < 0) {
dprintf (stderr, "Error reading attribute %s\n", sysattr->path);
free(fbuf);
return -1;
}
length = read(fd, fbuf, pgsize);
if (length < 0) {
dprintf (stderr, "Error reading from attribute %s\n",
sysattr->path);
close(fd);
free(fbuf);
return -1;
}
sysattr->len = length;
close(fd);
vbuf = (char *)realloc(fbuf, length+1);
if (vbuf == NULL) {
perror("realloc");
free(fbuf);
return -1;
}
sysattr->value = vbuf;
return 0;
}
/**
* sysfs_read_attribute_value: given path to attribute, return its value.
* values can be up to a pagesize, if buffer is smaller the value will
* be truncated.
* @attrpath: sysfs path to attribute
* @value: buffer to put value
* @vsize: size of value buffer
* returns 0 with success and -1 with error.
*/
int sysfs_read_attribute_value(const char *attrpath, char *value, size_t vsize)
{
struct sysfs_attribute *attr = NULL;
size_t length = 0;
if (attrpath == NULL || value == NULL) {
errno = EINVAL;
return -1;
}
attr = sysfs_open_attribute(attrpath);
if (attr == NULL) {
dprintf(stderr, "Invalid attribute path %s\n", attrpath);
errno = EINVAL;
return -1;
}
if((sysfs_read_attribute(attr)) != 0 || attr->value == NULL) {
dprintf(stderr, "Error reading from attribute %s\n", attrpath);
sysfs_close_attribute(attr);
return -1;
}
length = strlen(attr->value);
if (length > vsize)
dprintf(stderr,
"Value length %d is larger than supplied buffer %d\n",
length, vsize);
strncpy(value, attr->value, vsize);
sysfs_close_attribute(attr);
return 0;
}
/**
* sysfs_get_value_from_attrbutes: given a linked list of attributes and an
* attribute name, return its value
* @attr: attribute to search
* @name: name to look for
* returns char * value - could be NULL
*/
char *sysfs_get_value_from_attributes(struct sysfs_attribute *attr,
const char *name)
{
struct sysfs_attribute *cur = NULL;
char tmpname[SYSFS_NAME_LEN];
if (attr == NULL || name == NULL) {
errno = EINVAL;
return NULL;
}
cur = attr;
while (cur != NULL) {
memset(tmpname, 0, SYSFS_NAME_LEN);
if ((sysfs_get_name_from_path(cur->path, tmpname,
SYSFS_NAME_LEN)) != 0) {
cur = cur->next;
continue;
}
if (strcmp(tmpname, name) == 0)
return cur->value;
cur = cur->next;
}
return NULL;
}
/**
* add_subdir_to_dir: adds subdirectory to directory's subdirs
* @sysdir: directory to add subdir to
* @subdir: subdirectory to add.
*/
static void add_subdir_to_dir(struct sysfs_directory *sysdir,
struct sysfs_directory *subdir)
{
if (sysdir != NULL && subdir != NULL) {
subdir->next = sysdir->subdirs;
sysdir->subdirs = subdir;
}
}
/**
* add_attr_to_dir: adds attribute to directory's attributes
* @sysdir: directory to add attribute to
* @sysattr: attribute to add.
*/
static void add_attr_to_dir(struct sysfs_directory *sysdir,
struct sysfs_attribute *sysattr)
{
if (sysdir != NULL && sysattr != NULL) {
sysattr->next = sysdir->attributes;
sysdir->attributes = sysattr;
}
}
/**
* sysfs_close_dlink: closes and cleans up directory link.
* @dlink: directory link to close.
*/
void sysfs_close_dlink(struct sysfs_dlink *dlink)
{
if (dlink != NULL) {
dlink->next = NULL;
if (dlink->target != NULL)
sysfs_close_directory(dlink->target);
free(dlink);
}
}
/**
* add_dlink_to_dir: adds directory link to directory's links list.
* @sysdir: directory to add it to.
* @dlink: link to add.
*/
static void add_dlink_to_dir(struct sysfs_directory *sysdir,
struct sysfs_dlink *dlink)
{
if (sysdir != NULL && dlink != NULL) {
dlink->next = sysdir->links;
sysdir->links = dlink;
}
}
/**
* sysfs_close_directory: closes directory, cleans up attributes and links
* @sysdir: sysfs_directory to close
*/
void sysfs_close_directory(struct sysfs_directory *sysdir)
{
struct sysfs_directory *sdir = NULL, *dnext = NULL;
struct sysfs_dlink *dlink = NULL, *nextl = NULL;
struct sysfs_attribute *attr = NULL, *anext = NULL;
if (sysdir != NULL) {
if (sysdir->subdirs != NULL) {
for (sdir = sysdir->subdirs; sdir != NULL;
sdir = dnext) {
dnext = sdir->next;
sysfs_close_directory(sdir);
}
}
if (sysdir->links != NULL) {
for (dlink = sysdir->links; dlink != NULL;
dlink = nextl) {
nextl = dlink->next;
sysfs_close_dlink(dlink);
}
}
if (sysdir->attributes != NULL) {
for (attr = sysdir->attributes; attr != NULL;
attr = anext) {
anext = attr->next;
/* sysfs_close_attribute(attr); */
if (attr->value != NULL)
free(attr->value);
free(attr);
}
}
free(sysdir);
}
}
/**
* alloc_directory: allocates and initializes directory structure
* returns struct sysfs_directory with success or NULL with error.
*/
static struct sysfs_directory *alloc_directory(void)
{
return (struct sysfs_directory *)
calloc(1, sizeof(struct sysfs_directory));
}
/**
* alloc_dlink: allocates and initializes directory link structure
* returns struct sysfs_dlink with success or NULL with error.
*/
static struct sysfs_dlink *alloc_dlink(void)
{
return (struct sysfs_dlink *)calloc(1, sizeof(struct sysfs_dlink));
}
/**
* sysfs_open_directory: opens a sysfs directory, creates dir struct, and
* returns.
* @path: path of directory to open.
* returns: struct sysfs_directory * with success and NULL on error.
*/
struct sysfs_directory *sysfs_open_directory(const char *path)
{
struct sysfs_directory *sdir = NULL;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
sdir = alloc_directory();
if (sdir == NULL) {
dprintf(stderr, "Error allocating directory %s\n", path);
return NULL;
}
strncpy(sdir->path, path, sizeof(sdir->path));
return sdir;
}
/**
* sysfs_open_dlink: opens a sysfs directory link, creates struct, and returns
* @path: path of link to open.
* returns: struct sysfs_dlink * with success and NULL on error.
*/
struct sysfs_dlink *sysfs_open_dlink(const char *linkpath)
{
struct sysfs_dlink *dlink = NULL;
struct sysfs_directory *tdir = NULL;
char name[SYSFS_NAME_LEN];
char target[SYSFS_PATH_MAX];
if (linkpath == NULL) {
errno = EINVAL;
return NULL;
}
memset(name, 0, SYSFS_NAME_LEN);
memset(target, 0, SYSFS_PATH_MAX);
if ((sysfs_get_name_from_path(linkpath, name, SYSFS_NAME_LEN)) != 0
|| (sysfs_get_link(linkpath, target, SYSFS_PATH_MAX)) != 0) {
errno = EINVAL;
dprintf(stderr, "Invalid link path %s\n", linkpath);
return NULL;
}
dlink = alloc_dlink();
if (dlink == NULL) {
dprintf(stderr,
"Error allocating directory link %s\n", linkpath);
return NULL;
}
strcpy(dlink->name, name);
tdir = sysfs_open_directory(target);
if (tdir == NULL) {
dprintf(stderr, "Invalid directory link target %s\n", target);
sysfs_close_dlink(dlink);
return NULL;
}
dlink->target = tdir;
return dlink;
}
/**
* sysfs_read_directory: grabs attributes, links, and subdirectories
* @sysdir: sysfs directory to open
* returns 0 with success and -1 with error.
*/
int sysfs_read_directory(struct sysfs_directory *sysdir)
{
DIR *dir = NULL;
struct dirent *dirent = NULL;
struct stat astats;
struct sysfs_attribute *attr = NULL;
struct sysfs_directory *subdir = NULL;
struct sysfs_dlink *dlink = NULL;
char file_path[SYSFS_PATH_MAX];
int retval = 0;
if (sysdir == NULL) {
errno = EINVAL;
return -1;
}
dir = opendir(sysdir->path);
if (dir == NULL) {
perror("opendir");
return -1;
}
while(((dirent = readdir(dir)) != NULL) && retval == 0) {
if (0 == strcmp(dirent->d_name, "."))
continue;
if (0 == strcmp(dirent->d_name, ".."))
continue;
memset(file_path, 0, SYSFS_PATH_MAX);
strncpy(file_path, sysdir->path, sizeof(file_path));
strncat(file_path, "/", sizeof(file_path));
strncat(file_path, dirent->d_name, sizeof(file_path));
if ((lstat(file_path, &astats)) != 0) {
perror("stat");
continue;
}
if (S_ISREG(astats.st_mode)) {
attr = sysfs_open_attribute(file_path);
if (attr == NULL) {
dprintf (stderr, "Error opening attribute %s\n",
file_path);
retval = -1;
break;
}
if (attr->method & SYSFS_METHOD_SHOW) {
if ((sysfs_read_attribute(attr)) != 0) {
dprintf (stderr,
"Error reading attribute %s\n",
file_path);
sysfs_close_attribute(attr);
continue;
}
}
add_attr_to_dir(sysdir, attr);
} else if (S_ISDIR(astats.st_mode)) {
subdir = sysfs_open_directory(file_path);
if (subdir == NULL) {
dprintf (stderr, "Error opening directory %s\n",
file_path);
retval = -1;
break;
}
add_subdir_to_dir(sysdir, subdir);
} else if (S_ISLNK(astats.st_mode)) {
dlink = sysfs_open_dlink(file_path);
if (dlink == NULL) {
dprintf(stderr, "Error opening link %s\n",
file_path);
retval = -1;
break;
}
add_dlink_to_dir(sysdir, dlink);
}
}
closedir(dir);
return(retval);
}
/**
* sysfs_read_dlinks: reads a directory link's target directory. Can
* supply a linked list of links.
* @dlink: directory link to read.
* returns 0 with success or -1 with error.
*/
int sysfs_read_dlinks(struct sysfs_dlink *dlink)
{
struct sysfs_dlink *cur = NULL;
if (dlink == NULL || dlink->target == NULL) {
errno = EINVAL;
return -1;
}
cur = dlink;
while (cur != NULL) {
if ((sysfs_read_directory(cur->target)) != 0) {
dprintf(stderr,
"Error reading directory link target %s\n",
dlink->name);
return -1;
}
cur = cur->next;
}
return 0;
}

89
libsysfs/sysfs_driver.c Normal file
View File

@ -0,0 +1,89 @@
/*
* sysfs_driver.c
*
* Driver utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_close_driver: closes and cleans up driver structure
* @driver: driver to close
*/
void sysfs_close_driver(struct sysfs_driver *driver)
{
if (driver != NULL) {
if (driver->directory != NULL)
sysfs_close_directory(driver->directory);
free(driver);
}
}
/**
* alloc_driver: allocates and initializes driver
* returns struct sysfs_driver with success and NULL with error.
*/
static struct sysfs_driver *alloc_driver(void)
{
return (struct sysfs_driver *)calloc(1, sizeof(struct sysfs_driver));
}
/**
* sysfs_open_driver: opens and initializes driver structure
* @path: path to driver directory
* returns struct sysfs_driver with success and NULL with error
*/
struct sysfs_driver *sysfs_open_driver(const char *path)
{
struct sysfs_driver *driver = NULL;
struct sysfs_directory *sdir = NULL;
char devname[SYSFS_NAME_LEN];
if (path == NULL) {
errno = EINVAL;
return NULL;
}
sdir = sysfs_open_directory(path);
if (sdir == NULL) {
dprintf (stderr, "Error opening directory %s\n", path);
return NULL;
}
if ((sysfs_read_directory(sdir)) != 0) {
dprintf (stderr, "Error reading directory %s\n", path);
sysfs_close_directory(sdir);
return NULL;
}
driver = alloc_driver();
if (driver == NULL) {
dprintf(stderr, "Error allocating driver at %s\n", path);
sysfs_close_directory(sdir);
return NULL;
}
if ((sysfs_get_name_from_path(path, devname, SYSFS_NAME_LEN)) != 0) {
dprintf (stderr, "Error reading directory %s\n", path);
sysfs_close_directory(sdir);
free(driver);
return NULL;
}
strncpy(driver->name, devname, sizeof(driver->name));
driver->directory = sdir;
return driver;
}

156
libsysfs/sysfs_utils.c Normal file
View File

@ -0,0 +1,156 @@
/*
* syfs_utils.c
*
* System utility functions for libsysfs
*
* Copyright (C) 2003 International Business Machines, Inc.
*
* 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
*
*/
#include "libsysfs.h"
#include "sysfs.h"
/**
* sysfs_get_mnt_path: Gets the mount point for specified filesystem.
* @fs_type: filesystem type to retrieve mount point
* @mnt_path: place to put the retrieved mount path
* @len: size of mnt_path
* returns 0 with success and -1 with error.
*/
static int sysfs_get_fs_mnt_path(const char *fs_type, char *mnt_path,
size_t len)
{
FILE *mnt;
struct mntent *mntent;
int ret = 0;
size_t dirlen = 0;
/* check arg */
if (fs_type == NULL || mnt_path == NULL) {
errno = EINVAL;
return -1;
}
if ((mnt = setmntent(SYSFS_PROC_MNTS, "r")) == NULL) {
dprintf(stderr, "Error getting mount information\n");
return -1;
}
while (ret == 0 && dirlen == 0 && (mntent = getmntent(mnt)) != NULL) {
if (strcmp(mntent->mnt_type, fs_type) == 0) {
dirlen = strlen(mntent->mnt_dir);
if (dirlen <= (len - 1)) {
strcpy(mnt_path, mntent->mnt_dir);
} else {
dprintf(stderr,
"Error - mount path too long\n");
ret = -1;
}
}
}
endmntent(mnt);
if (dirlen == 0 && ret == 0) {
dprintf(stderr, "Filesystem %s not found!\n", fs_type);
errno = EINVAL;
ret = -1;
}
return ret;
}
/*
* sysfs_get_mnt_path: Gets the sysfs mount point.
* @mnt_path: place to put "sysfs" mount point
* @len: size of mnt_path
* returns 0 with success and -1 with error.
*/
int sysfs_get_mnt_path(char *mnt_path, size_t len)
{
int ret = -1;
if (mnt_path != NULL)
ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len);
else
errno = EINVAL;
return ret;
}
/**
* sysfs_get_name_from_path: returns last name from a "/" delimited path
* @path: path to get name from
* @name: where to put name
* @len: size of name
*/
int sysfs_get_name_from_path(const char *path, char *name, size_t len)
{
char *n = NULL;
if (path == NULL || name == NULL) {
errno = EINVAL;
return -1;
}
n = strrchr(path, '/');
if (n == NULL) {
errno = EINVAL;
return -1;
}
n++;
strncpy(name, n, len);
return 0;
}
/**
* sysfs_get_link: returns link source
* @path: symbolic link's path
* @target: where to put name
* @len: size of name
*/
int sysfs_get_link(const char *path, char *target, size_t len)
{
char devdir[SYSFS_PATH_MAX];
char linkpath[SYSFS_PATH_MAX];
char *d = NULL;
if (path == NULL || target == NULL) {
errno = EINVAL;
return -1;
}
memset(devdir, 0, SYSFS_PATH_MAX);
memset(linkpath, 0, SYSFS_PATH_MAX);
if ((sysfs_get_mnt_path(devdir, SYSFS_PATH_MAX)) != 0) {
dprintf(stderr, "Sysfs not supported on this system\n");
return -1;
}
if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) {
return -1;
}
d = linkpath;
/* getting rid of leading "../.." */
while (*d == '/' || *d == '.')
d++;
d--;
strcat(devdir, d);
strncpy(target, devdir, len);
return 0;
}