Ken & Deb Allen
20 years ago
I have been toying with the idea of checking whether or not I can use
SQLite in a Windows device driver as its database. I am working on an
existing product that is implemented as a series of Windows device
drivers, filter drivers and even a file system driver. The file
system driver manages a dedicated disk partition that contains an
NTFS file system and a series of files (some flat files and some
Btree files) that serve as the database. The code that manages this
database is quite old and has been heavily modified several times,
but the code is not well structured and contains a number of
architectural features that act as hinderances to modifications and
performance enhancements.
From the beginning it was clear to me that several issues would be
greatly minimized or even eliminated if we could use some form of a
relational database management package instead of the home-grown file
management code, but there do not seem to be any database packages
that are available to kernel code.
As part of another effort we looked at using SQLite, and performed a
number of tests to that end. When I discovered that all of the source
code was available, it seemed that we may be able to 'port' the code
for use within out file system driver, either as a kernel DLL or
directly compiled into the existing component. A number of features
would have to be modified, such as the use of malloc() and free()
calls, which would need to be replaced with the appropriate calls to
kernel routines (if not the development of an extra set of routines
for such dynamic memory usage), but we were hopeful.
I had used the Visual C++ 6 compiler (in C mode) to compile the
existing SQLite source for use in user space, and that was not much
of a problem, but the DDK (kernel) compiler was a modified version of
the Visual C++ 7 compiler, and a number of compilation features are
quite different when compiling code into the kernel as opposed as
into user space. We had a number of problems with compiling the
SQLite code as part of our kernel build, and so I decided to attempt
to compile the latest source code for user space using the Visual C++
7 compiler (Visual Studio .Net 2003). I have an HTML file that is the
output from this attempt, which lists 193 compiler warnings (the code
actually runs) based on the 3.2.7 version of the SQLite source code.
This mail list does not permit me to attach the file (message
rejected as too large), but if anyone wants to see it I can send it
to you.
The vast majority of the warnings are related to either unsafe
implicit data type conversions or signed and unsigned comparison
operations. Some of these are not unreasonable, such as a complaint
about conversion from "size_t" to "int", which should be the same
size objects, but others definitely appear to be significant, such as
an implicit conversion from "i64" or "u64" to int, which is a
legitimate concern. Some of the signed/unsigned comparisons are also
suspect (is an unsigned integer value of 0x81230001 greater than or
less than a signed integer value of 0x00000001? -- hint, as a signed
value the former is a negative number, but as an unsigned it is not).
Some of these warnings are simply the compiler being extremely (and
appropriately) cautious, but some of them truly do look like odd
coding. Why should the code unconditionally and implicitly assign a
64-bit integer value into a 32-bit integer variable? If the
conditions under which this is done are such that there can be no
loss of data, then there should be a comment explaining this, and the
cast should be explicit to enforce that this is expected.
Unfortunately, there are no such comments and not all of the implicit
casts have a clear context when simply examining isolated lines of code.
I had a quick look at some of the code, but I am not certain whether
all, or even most, of these warnings can be safely ignored or not. I
tried modifying the code to add explicit casts to eliminate all of
the warnings, which worked, but I do not know whether or not the
resulting code contains runtime errors or not (specifically as a
result of data loss at runtime or improper comparison logic).
Could someone have a look at some of these and provide some opinions?
I know that the coding style used for SQLite is what I have heard
referred to as "minimal C", but should the code not be commented
concerning such conversions, and the conversion be made explicit?
-ken
SQLite in a Windows device driver as its database. I am working on an
existing product that is implemented as a series of Windows device
drivers, filter drivers and even a file system driver. The file
system driver manages a dedicated disk partition that contains an
NTFS file system and a series of files (some flat files and some
Btree files) that serve as the database. The code that manages this
database is quite old and has been heavily modified several times,
but the code is not well structured and contains a number of
architectural features that act as hinderances to modifications and
performance enhancements.
From the beginning it was clear to me that several issues would be
greatly minimized or even eliminated if we could use some form of a
relational database management package instead of the home-grown file
management code, but there do not seem to be any database packages
that are available to kernel code.
As part of another effort we looked at using SQLite, and performed a
number of tests to that end. When I discovered that all of the source
code was available, it seemed that we may be able to 'port' the code
for use within out file system driver, either as a kernel DLL or
directly compiled into the existing component. A number of features
would have to be modified, such as the use of malloc() and free()
calls, which would need to be replaced with the appropriate calls to
kernel routines (if not the development of an extra set of routines
for such dynamic memory usage), but we were hopeful.
I had used the Visual C++ 6 compiler (in C mode) to compile the
existing SQLite source for use in user space, and that was not much
of a problem, but the DDK (kernel) compiler was a modified version of
the Visual C++ 7 compiler, and a number of compilation features are
quite different when compiling code into the kernel as opposed as
into user space. We had a number of problems with compiling the
SQLite code as part of our kernel build, and so I decided to attempt
to compile the latest source code for user space using the Visual C++
7 compiler (Visual Studio .Net 2003). I have an HTML file that is the
output from this attempt, which lists 193 compiler warnings (the code
actually runs) based on the 3.2.7 version of the SQLite source code.
This mail list does not permit me to attach the file (message
rejected as too large), but if anyone wants to see it I can send it
to you.
The vast majority of the warnings are related to either unsafe
implicit data type conversions or signed and unsigned comparison
operations. Some of these are not unreasonable, such as a complaint
about conversion from "size_t" to "int", which should be the same
size objects, but others definitely appear to be significant, such as
an implicit conversion from "i64" or "u64" to int, which is a
legitimate concern. Some of the signed/unsigned comparisons are also
suspect (is an unsigned integer value of 0x81230001 greater than or
less than a signed integer value of 0x00000001? -- hint, as a signed
value the former is a negative number, but as an unsigned it is not).
Some of these warnings are simply the compiler being extremely (and
appropriately) cautious, but some of them truly do look like odd
coding. Why should the code unconditionally and implicitly assign a
64-bit integer value into a 32-bit integer variable? If the
conditions under which this is done are such that there can be no
loss of data, then there should be a comment explaining this, and the
cast should be explicit to enforce that this is expected.
Unfortunately, there are no such comments and not all of the implicit
casts have a clear context when simply examining isolated lines of code.
I had a quick look at some of the code, but I am not certain whether
all, or even most, of these warnings can be safely ignored or not. I
tried modifying the code to add explicit casts to eliminate all of
the warnings, which worked, but I do not know whether or not the
resulting code contains runtime errors or not (specifically as a
result of data loss at runtime or improper comparison logic).
Could someone have a look at some of these and provide some opinions?
I know that the coding style used for SQLite is what I have heard
referred to as "minimal C", but should the code not be commented
concerning such conversions, and the conversion be made explicit?
-ken