Commit Graph

6698 Commits

Author SHA1 Message Date
Demi M. Obenour c3e04c2ac9 Negate the trailer offset after division
This ensures that negation cannot overflow.
2021-02-16 12:10:24 +02:00
Panu Matilainen a82251b44e Handle file install failures more gracefully
Run the file installation in multiple stages:
1) gather intel
2) unpack the archive to temporary files
3) set file metadatas
4) commit files to final location
5) mop up leftovers on failure

This means we no longer leave behind a trail of untracked, potentially
harmful junk on installation failure.

If commit step fails the package can still be left in an inconsistent stage,
this could be further improved by first backing up old files to temporary
location to allow undo on failure, but leaving that for some other day.
Also unowned directories will still be left behind.

And yes, this is a somewhat scary change as it's the biggest ever change
to how rpm lays down files on install. Adopt the hardlink test spec
over to install tests and add some more tests for the new behavior.

Fixes: #967 (+ multiple reports over the years)
2021-02-16 09:37:34 +02:00
Panu Matilainen 1c23cff729 Handle hardlink tracking with a file state pointer
No functional changes, just makes it a little cleaner as firstlink now
points to the actual file data instead of a index number somewhere.
2021-02-16 09:37:34 +02:00
Panu Matilainen dcdddd055a Clarify file installation temporary suffix rule
We only use a temporary suffix for regular files that we are actually
creating, skipped and touched files should not have it. Add XFA_CREATING()
macro to accomppany XFA_SKIPPING() to easily check whether the file
is being created or something else.

No functional changes but makes the logic clearer.
2021-02-16 09:37:34 +02:00
Panu Matilainen 930650a937 Clarify file installation temporary suffix rule
We only use a temporary suffix for regular files that we are actually
creating, skipped and touched files should not have it. Add XFA_CREATING()
macro to accomppany XFA_SKIPPING() to easily check whether the file
is being created or something else.

No functional changes but makes the logic clearer.
2021-02-16 09:37:34 +02:00
Panu Matilainen 210431f183 Refactor fsmMkfile() to take advantage of the new state struct
Move setmeta into the struct too (we'll want this later anyhow),
and now we only need to pass the struct to fsmMkfile(). One less
argument to pass around, it has way too many still.

No functional changes.
2021-02-16 09:37:34 +02:00
Panu Matilainen 924cb31c53 Refactor file install and remove around a common struct
Collect the common state info into a struct shared by both file install
and remove, update code accordingly. The change looks much more drastic
than it is - it's just adding fp-> prefix to a lot of places.
While we're at it, remember the state data throughout the operation.

No functional changes here, just paving way for the next steps which
will look clearer with these pre-requisites in place.
2021-02-16 09:37:34 +02:00
Panu Matilainen 31a9c5fa07 Don't update path info if rename failed on file commit 2021-02-16 09:37:34 +02:00
Panu Matilainen 8a9147f7d1 Drop unused filename variable 2021-02-16 09:37:34 +02:00
Panu Matilainen 073bcf7ff6 Clean up file unpack iteration logic a bit
Handle rpmfiNext() in the while-condition directly to make it more like
similar other constructs elsewhere, adjust for the end of iteration
code after the loop. Also take the file index from rpmfiNext() so
we don't need multiple calls to rpmfiFX() later.
2021-02-16 09:37:34 +02:00
Panu Matilainen 7f3fdf6868 Make Lua a hard requirement for rpm
More and more macros, scriptlets and other functionality has been getting
built around Lua, to the point that it has in practice been required for
several years now.

Maintaining the pretense of being optional comes at a cost in holding
back developments and having to check for that theoretical special
case. Lets make it a hard requirement and embrace it some more!
2021-02-09 13:57:27 +02:00
Florian Festi c6c784b70f Use "main database" instead of "master database"
to avoid undesired language
2021-02-05 11:40:28 +02:00
Panu Matilainen 551e66fc94 Remove indirect BDB leftovers
These knobs and tunables were only ever used by the BDB backend which
exposed all manner of internals to macro configuration. With that gone,
we don't needs these struct members either.
2021-02-03 14:41:48 +01:00
Panu Matilainen 4290300e24 Remove support for Berkeley Database backend
Back in 2013, the Berkeley DB license was changed in a way that prevented
most of open-source world to go along, rpm was no different. We now have
other options and a standalone migration path from BDB for those that
haven't yet done so.

Whatever else might be said about this partnership, it has been a long one.
Now's the time to part ways.
2021-02-03 14:41:48 +01:00
Panu Matilainen 77062e68f8 Honor requested file permissions when creating ndb database files
Prior to this, ndb files were using hardcoded 0666 permissions whereas
rpm generally defaults to 0644.
2021-02-02 15:33:16 +02:00
Panu Matilainen 6e6be7d6eb Fix rpmtsInitDB() argument confusion
Since it's introduction, rpmtsInitDB() has passed the second argument
directly to rpmdbInit() as permission bits. However commit
81fef98480 incorrectly documented this
as being related to the db mode read/write *mode*, and also used it
that way in the python bindings.
2021-02-02 15:33:16 +02:00
Demi Marie Obenour 5e40166380 Tag data must have count greater than zero
Zero counts are invalid, and they cause problems elsewhere.  For
instance, strtaglen() will suffer an integer underflow.
2021-01-27 11:17:13 +02:00
Demi Marie Obenour f29c43728c Verify that data does not overlap region trailer
This is already checked for other header entries.
2021-01-19 11:48:17 +02:00
Morgan Thomas 4345ee06f4 Support building on aarch64 macOS
Previously, trying to run rpmbuild on a M1 machine returns "error: No compatible architectures found for build".
Since RPM detects its architecture on macOS just by looking at what architecture flags are defined at compile time, this adds a clause to detect aarch64.
2021-01-18 10:21:04 +02:00
Panu Matilainen cb6aa82dbc Unblock signals in forked scriptlets
Since commit c5f82d3f62 we've blocked
most signals during transactions, which makes sense to rpm itself but
the signal mask is inherited to childs and carried even across exec(),
so all scriptlets are executing with those signals blocked as well.
Which in turn does not make sense, the scriptlets could run stuff that
actually depends on signal delivery (such as SIGALARM in RhBug:1913765).

Unblock all signals for forked scriptlet execution (Lua scriptlets are
totally different as they execute in-process for now)
2021-01-18 10:18:21 +02:00
Marc Seeger 70f2a02873 Add darwin support to NDB. 2021-01-18 09:33:21 +02:00
Michael Schroeder 0644e4e79c Allow database probing if _db_backend is not set
There is no harm in allowing read access in this case. We still
error out in the database rebuild case, just to be on the safe
side. We now have the following logic:

_db_backend unset:
  * error out for rebuilddb or read-write access
  * use detected backend and print a debug message
_db_backend unknown:
  * error out for rebuilddb or read-write access
  * use detected backend and print a warning message
_db_backend set:
  * use detected backend and print a warning message if it
    does not match the configured backend
2020-12-07 13:37:38 +02:00
Panu Matilainen afbc2b0783 Disable implicit database creation on read-only handle
If somebody is opening a database in a read-only mode (eg for query)
then we really have no business to *create* such database if not existing.
Update all backends to error out instead of trying to create the database
or its directory when opening read-only, add a test for this specific
behavior.

This implicit discard of read-only flag is such a long standing behavior
that this is likely to break stuff here and there.
2020-11-24 07:18:20 +02:00
Panu Matilainen 3cb955b77f Only attempt loading the keyring once the rpmdb is open
When we do lazy rpmdb open in rpmtsInitIterator(), we also do a lazy
keyring open. Except that since the keyring typically lives in the rpmdb,
we PROBABLY should try open the database first. One of those "WTF I've
been smoking" moments, lol.

Prevents an ugly if mostly harmless double error anything we can't open
the database for one reason or another.
2020-11-24 07:18:20 +02:00
Panu Matilainen fd054a40b2 Stop on first failure when trying to open a database (RhBug:1898301)
If an index open fails there's no point trying to go on, things are
not going to work and at least BDB will segfault in some cases...
2020-11-24 07:18:20 +02:00
Panu Matilainen c223d84fbf Eliminate use of obsolete gethostbyname() function
We only actually used gethostbyname() for canonicalizing buildhost,
convert that to use getaddrinfo() instead, which actually has an
option for retrieving exactly what we want.

The other "use" was to initialize name services, but as we don't need
or use hostnames for any operation, we can just as well drop it. User
and group names are what we care about.
2020-11-23 13:00:59 +02:00
Panu Matilainen fb58884177 Fix a minor memory leak on failed sqlite database open (RhBug:1896301)
Curiously, sqlite allocates resources that need freeing even in case
of failure to open. Quoting from https://www.sqlite.org/c3ref/open.html:

> Whether or not an error occurs when it is opened, resources associated
> with the database connection handle should be released by passing it to
> sqlite3_close() when it is no longer required.

I disagree, but as it's documented behavior there's no point filing a
bug. So lets close the non-open connection and chug on.
2020-11-11 09:17:54 +02:00
Panu Matilainen f9c7b53f50 Only do early name services initialization if we actually chroot
There's no point or need to do all this fluff on library initialization,
we can just as well do it when we're told to use a chroot by
calling rpmChrootSet(), at which time we're still on familiar ground.
Eliminating unused cruft from initialization can't hurt our start-up
times either.
2020-11-09 14:00:56 +02:00
Panu Matilainen 561c59db1b Convert some obvious cases to use rstrndup() instead of manual work
The net win in terms of LoC is not that big but it does make things
that little more readable and obvious.
2020-11-09 09:28:54 +02:00
Panu Matilainen 0b75075a8d Shut up bogus Doxygen warnings about undocumented parameters
As of Doxygen >= 1.8.20 it started complaining about anything marked
as @retval being undocumented. As this is widely used in rpm...
Mass-replace all @retval uses with @param[out] to silence. Some of
these are actually in/out parameters but combing through all of them
is a bit too much...

Also escape <CR><LF> in rpmpgp.h to shut up yet another new warning.
2020-10-28 10:40:41 +02:00
Fabrice Fontaine 6dbb036d2f lib/rpmrc.c: include fcntl.h for O_*
Fixes compilation on musl, otherwise it fails with undefined references
to various O_* symbols as mentioned here:

https://www.man7.org/linux/man-pages/man0/fcntl.h.0p.html

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
2020-10-26 12:42:15 +02:00
Panu Matilainen b278517d7f Don't muck with parametric macro arguments of cli defines
When converting - to _ in cli-defined macro names, stop at first '('
as we have no business mucking with the arguments.
2020-10-19 11:27:35 +03:00
Panu Matilainen b441de0031 Fix RPMTAG_SUGGESTVERSION and -FLAGS info, they're not extensions 2020-10-13 14:36:34 +02:00
Panu Matilainen 717a3f7ecf Pass install scriptlet arguments to Lua as real local arguments
The code is more obvious and there's a whole lot less of it, we get
rid of a klunky global table, allow Lua scriptlets to process arguments
using native facilities for variadic functions, all in a backwards
compatible manner. What's not to like?

As a side-effect, the package count arguments now appear as integers
instead of floats, which is much saner in the context. Lua will
automatically convert numbers as necessary so this should not break
anything.
2020-10-09 12:52:47 +03:00
Panu Matilainen 192cbafcb2 Add API support for passing options and arguments to natively to Lua
Add support for passing getopt options and arguments to natively to Lua
scriptlets via the internal API. The processed opts and args are stored
in two chunk local two tables, options keyed by the letter and arguments
by their numeric index.

Update call sites accordingly, but no actual functionality changes here,
just pre-requisites for next steps.
2020-10-09 12:52:47 +03:00
Panu Matilainen ef3ea9c69b Implement alternative transaction callback style with transaction elements
Add API to get and set callback style, defaulting to the good ole
header first style and add a new style where a transaction element
is passed in place of the header, allowing a much saner interaction.

This is doubly so in Python, where the old style callback is a
braindamaged mess. In the new mode the "key" is not passed as separate
argument at all, it can be just as well retrieved via te.Key() for
the callbacks needing it.
2020-10-05 12:21:18 +03:00
Panu Matilainen 79ac95fea5 Fix ambiguous diagnostics output on file triggers (RhBug:1883338)
All this time we've been logging file and transfile triggers with output
identical to that of regular triggers, confusing people for no good reason.

We know which of the three it is when creating so add a matching prefix
to the output at that point. All we need to do is move the '%' from
the scriptlet table to the printf() format string to make room for
the description prefix. Doh.

So now we get output using things with their proper names, such as:

  D: running post-transaction scripts
  D: %transfiletriggerin(glibc-common-2.31-4.fc32.x86_64): scriptlet start
2020-10-01 09:49:44 +03:00
Leo 9395bdc644 lib/rpmdb.c: include fcntl.h for O_*
Fixes compilation on musl, otherwise it fails with undefined references
to various O_* symbols as mentioned here:

https://www.man7.org/linux/man-pages/man0/fcntl.h.0p.html
2020-10-01 09:49:20 +03:00
Panu Matilainen 257077a60c Implement a transaction set change notification callback
Add support for an optional callback hook for reveiving notifications
about added and deleted transaction elements. This lets API clients
easily track which elements get created and/or replaced by a single
rpmtsAddFoo() call and adjust their own book-keeping accordingly.
Also makes for an easy place to set application private data pointers
for newly added elements.

Currently there's no way to delete individual transaction elements from
the API but that can happen via rpmtsEmpty(), which we do send notifications
for. rpmtsFree() does NOT send notification though, it would be precarious
and most likely totally pointless to do so when the ts is being torn down.
2020-09-30 10:46:37 +03:00
Panu Matilainen 45449d5acf Add support for application private user data in transaction elements
The "key" passed to rpmtsAddInstallEleemnt() and associated with transaction
elements is sometimes mistaken for user data, but it is not, as rpm relies
on it having a very specific meaning and is passed around with that very
assumption.

API users have all sorts of (legit!) needs, lets add a proper application
private user data member to transaction elements.

The Python bindings to this are kinda dangerous if you liberally mix Python
and C as we can't know whether the pointer is an actual Python object or not
so we can only assume it is and hope for the best. Of course nobody in their
right mind should be setting user data from one language and accessing it
from another, really...
2020-09-28 11:17:24 +03:00
Panu Matilainen e6faaefc92 Remove invalid TODO comment on Lua scriptlet cwd
Contrary to what the TODO comment said, we cannot rely on chroot cwd
because an API user could've changed to some other directory in the
meanwhile. For Lua scripts, we simply need to save whatever the directory
we are in and return to that, to avoid breaking API users.
2020-09-28 10:44:17 +03:00
Panu Matilainen 6e51ca5959 Revert "Improve ARM detection"
Should've been reverted as a part of reverting commits
0da3c50d1f and
8ab279ae6b but got left behind and Fedora
has been carrying this reversion as a patch since then (and other
distros carrying others). This equally broken for everybody -state of
ARM is good for nobody. Lets revert back to pre 4.15 state and back to
the drawing board.

This reverts commit 8c3a7b8fa9.
2020-09-25 10:37:04 +03:00
Panu Matilainen 4cbdd7c940 Unbreak build due to defined but not used warning from ensureMacro()
Warning introduced in commit 64b4ebd315
which failed to take this into account, dunno how this wasn't caught
in CI or local testing.
2020-09-21 10:35:00 +03:00
Panu Matilainen 505fe16f86 Handful of trivial and obvious const-correctness fixes to librpm code 2020-09-09 12:46:26 +03:00
Panu Matilainen 886c24cfc6 Upgrade FA_TOUCH to FA_CREATE if the file went away (RhBug:1872141)
When %_minimize_writes is enabled, we determine unchanged files during
fingerprinting and only update their metadata (FA_TOUCH) instead of
always recreating from scratch (FA_CREATE) during install. However
package scriptlets (and administrators) can and will do arbitrary stuff
in the meanwhile, such as rm -f their own files in %pre, hoping to
get a fresh copy of contents no matter what. Or something.
Now, if the file was determined to not need changing by rpm, this will
just fail with chown & friends trying to touch non-existent file.
One can consider this a case of package shooting itself in the foot, but
when a package update fails or succeeds depending on %_minimize_writes this
to me suggests the feature is at fault as much as the package.

Do fsmVerify() on all files to be FA_TOUCH'ed to detect files whose
type changed or were removed since fingerprinting. This still doesn't
ensure correctness if something tampers with the contents in the meanwhile,
(for that we'd need to run the file through the whole machinery again,
checksumming and all) but covers the most glaring cases.
2020-09-09 12:44:54 +03:00
Panu Matilainen 64b4ebd315 Disable SSD auto-detection, mark %_minimize_writes as experimental
RhBug:1872141 (PR #1347) demonstrates how brittle and dangerous this
thing is. Until we can (re-)verify (digest and all) files not needing
recreating from fsm, this thing should be considered experimental and
too dangerous to automatically enable for casual users.
2020-09-09 12:28:32 +03:00
Jes Sorensen bd02416cd3 fsverity plugin: Use tag for algorithm
This uses the algorithm from the tag, if available. Fallback is SHA256.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 7e528e6650 fsverity - add tag for fsverity algorithm
The default algorith is SHA256, but fsverity allows for other
algorithms, so add a tag to handle this.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 131eeb2bbe Process verity tag on package read
This processes verity signature tags on package read, and provides
accessor functions to access them.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 174f083d1c rpmSignVerity: Generate signatures for files not present in archive
This generates signatures for all files in the archive, then picks up
ghost files from the header metadata and generates signatures for them
as well. It finally submits them to RPMTAG_VERITYSIGNATURES in header
file order as we cannot rely on archive order and header order being
the same.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 9644bbd5b3 rpmsignverity: Add verity signature headers to the package
This adds the array of verity signatures, and a signature length
header. We use 4K block for the Merkle tree, and rely on the kernel
doing the right thing.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Jes Sorensen 37d9051258 Introduce base2bin() - a helper to convert tag array of base64 strings
This will convert a tag of base64 strings to a binary array, similar
to how hex2bin() works. It supports variable sized strings, and will
determine the maximum string length and build the output array based
on that.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-09-04 13:22:38 +03:00
Panu Matilainen a2e072d452 Stop untranslatable format strings from being translated
There's nothing to translate in "%s: %s" and the like, don't bother
people with this stuff.
2020-08-27 14:54:54 +03:00
Panu Matilainen 471b7be4bd Warn and fall back to dummy database on unknown database backend config
The rpmdb is our most precious piece of data, don't make assumptions on
invalid configuration. Together with our crazy create-db-on-read behavior,
total database loss is just one 'rpmdb --rebuilddb' away in some scenarios
with the former behavior: access an sqlite/ndb database with older
version not supporting those, silently fallback to creating empty bdb,
and if db is now rebuilt, poof the data is gone.

Detect and warn on unknown/invalid %_db_backend configuration and fall
back to using dummy backend where no damage can occur. Doesn't help with
the old versions out there, but lets at least be saner going forward.
2020-08-27 14:47:59 +03:00
Cerul Alain 92a78e6acf Remove compare of global array tagsByName to NULL
A 2016 change (57a96d2486) apparently
changed tagsByName from dynamic allocation to being static, so that
Valgrind would not complain about lost memory. The definition is:

    static headerTagTableEntry tagsByName[TABLESIZE];

But a comparison was left of `tagsByName == NULL` in lib/tagname.c
and compiling with clang gives a warning, saying it is never NULL.
2020-07-21 09:25:34 +02:00
Narek Galstyan b7c25a28b7 Fix Doxygen comments 2020-07-10 15:49:37 +02:00
Panu Matilainen 07ed169da3 Add --excludeartifacts install option
Like docs, configs etc, excluding artifacts from installation might
sometimes be desireable to eg save space. Inspired by
https://bugzilla.redhat.com/show_bug.cgi?id=1848199
2020-06-23 13:05:24 +03:00
Panu Matilainen 40175825c8 Fix (work around) FA_TOUCH not scoping correctly over hardlinks
The existing FSM code doesn't correctly handle FA_TOUCH on hardlinked
file sets, which causes the hardlink set to break on at least some
upgrade scenarios when minimize_writes is enabled.

Only enable FA_TOUCH on non-hardlinked files to work around the issue
for now. While at it, rearrange the conditionals around min_writes to make
it a bit clearer. Testcase adopted from original reproducer by
Fabian Vogt, thanks!

Fixes: #1278
2020-06-23 13:01:54 +03:00
Panu Matilainen 6f70118c33 Fix completely broken prefix search on sqlite backend
The prefix search was so wrong it's a small miracle it ever did anything
at all. What have I been thinking? Well, I do remember thinking this
prefix stuff looks kinda fishy but then it seems to work so...

The prefix search belongs to the keyed iterator fetch case of course,
not the case where we're otherwise iterating over all keys.

Fixes: #1260
2020-06-10 11:07:42 +02:00
Panu Matilainen 869a36c172 Don't auto-enable IO flushing on non-rotational disks
Commit 47e2463d8a added logic to enable
%_flush_io automatically on non-rotational disks to avoid trashing system
caches and IO peaks on the grounds that this isn't so expensive on SSD,
but real world experience suggests otherwise. Install times go from
seconds to minutes which might not matter for the random individual system
but for build systems and the like churning away continuously...
2020-06-03 11:16:31 +02:00
Hongxu Jia 4865799123 Fix: bump up the limit of signature header to 64MB
Since commits [Place file signatures into the signature header where they
belong][1] applied, run `rpm -Kv **.rpm' failed if signature header
is larger than 64KB. Here are steps:

1) A unsigned rpm package, the size is 227560 bytes
$ ls -al xz-src-5.2.5-r0.corei7_64.rpm
-rw-------. 1 mockbuild 1000 227560 Jun  3 09:59

2) Sign the rpm package
$ rpmsign --addsign ... xz-src-5.2.5-r0.corei7_64.rpm

3) The size of signed rpm is 312208 bytes
$ ls -al xz-src-5.2.5-r0.corei7_64.rpm
-rw-------. 1 mockbuild 1000 312208 Jun  3 09:48

4) Run `rpm -Kv' failed with signature hdr data out of range
$ rpm -Kv xz-src-5.2.5-r0.corei7_64.rpm
xz-src-5.2.5-r0.corei7_64.rpm:
error: xz-src-5.2.5-r0.corei7_64.rpm: signature hdr data: BAD, no. of
bytes(88864) out of range

From 1) and 3), the size of signed rpm package increased
312208 - 227560 = 84648, so the check of dl_max (64KB,65536)
is not enough.

As [1] said:

    This also means the signature header can be MUCH bigger than ever
    before,so bump up the limit (to 64MB, arbitrary something for now)

So [1] missed to multiply by 1024.

[1] f558e88605

Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
2020-06-03 10:53:58 +03:00
Panu Matilainen 2153fa4ae5 Add a pre-flight check for removed packages too
For now we simply check whether the removed packages exist at all,
ie if somebody removed the package in the time between adding the
package to the transaction and running the transaction. One could argue
that whoever removed it already did us a favor so why bother, but then
that's not in the spirit of transactions.

RPMPROB_PKG_INSTALLED is (ab)used for the purpose as it's related
to the install status anyhow, and we can trivially adjust the message
as per the instance number.
2020-06-02 15:25:57 +02:00
Panu Matilainen 37c32e6482 Refactor pre-flight checks for added packages to helper function
No intended functional changes, just pre-requisites for performing
more pre-flight checks.
2020-06-02 15:25:57 +02:00
Panu Matilainen d009ac4828 Remove support for NSS
NSS is a behemoth of a library which drags in a whole runtime subsystem
of its own which is often at odds with normal Unix system behavior
(hello SIGPIPE). Now that we have nicer alternatives available there's
little reason to lug this baggage along. NSS was deprecated in rpm 4.16
(commit 0b9efb93fb).
2020-05-29 08:54:56 +03:00
Panu Matilainen cf967331d3 Remove support for beecrypt
Beecrypt whose upstream is dead for more than ten years now, was deprecated
in rpm 4.16 (in commit 0910e6aa9e).
2020-05-29 08:54:56 +03:00
Panu Matilainen d88b929998 Refactor rpmdsCompare() to use the new version API 2020-05-27 14:14:00 +02:00
Panu Matilainen be0c4b5dce Add (beginnings of) a rpm version API (parsing, comparison)
It's more than a little hysterical that rpm hasn't had a meaningful
public API for parsing and comparing version strings. The API may seem
kinda overkill for some things but then this does give us a place to
check for invalid version strings, which is a thing we never had before
(although the current code doesn't do much in the way of checking)

Fixes: #561
2020-05-27 14:14:00 +02:00
Panu Matilainen 6800e0a4df Axe --nopromote and most of the related infrastructure
Epoch promotion was a thing around and before the turn of the millenium,
we really shouldn't be carrying that cruft around anymore.

Remove all traces that we can without too much guilt about breaking
ABI/API and not bumping soname which we dont want to do for this
stupid old thing: all the symbols are left in place, they just don't
work anymore. Nobody should notice as nobody can have been using this
stuff in the last 15+ years.
2020-05-27 14:14:00 +02:00
Panu Matilainen f1e721ccfc Consolidate our Lua-bindings to librpmio now that we can
No functional changes, just lose extra baggage that was needed to append
initialize and append rpm.vercmp() from librpm side when the rest is in
librpmio. We might need to bring it back some day, but given the history
here it doesn't seem all that likely.
2020-05-27 14:14:00 +02:00
Panu Matilainen 501fb4ef62 Move rpmvercmp() to librpmio
Adding a new header just for this seems a bit much but we'll be adding
stuff there shortly.

No functional changes as such, this is prerequisite for supporting
version comparison in expressions.
2020-05-27 14:14:00 +02:00
Panu Matilainen 290537375d Move rpmVersionCompare() to headerutil.c for better layer match
No functional change, but we'll need this in the next step.
2020-05-27 14:14:00 +02:00
Jes Sorensen f34030816d rpmfiArchiveRead() use signed return value to handle -1 on error
size_t is unsigned, so returning -1 is not going to have the expected
behavior. Fix it to return ssize_t.

Signed-off-by: Jes Sorensen <jsorensen@fb.com>
2020-05-13 11:07:49 +03:00
Panu Matilainen ead227f2da Kick out leftover development-time assert checks from rpmal 2020-04-22 15:38:35 +03:00
Panu Matilainen a4afbb62c9 Don't look into source package provides in depsolving
Fixes regressions from commit 75ec16e660e784d7897b37cac1a2b9b135825f25:
the newly added provides of to-be-built packages were being used for
dependency resolution, such as spec satifying its own buildrequires,
and matched against conflicts in installed packages.

Source packages cannot obsolete anything or provide capabilities or files
to transactions, don't add them to rpmal at all. Explicitly skip checks
against source provides, similarly to what we already did with obsoletes.

Fixes: #1189
2020-04-22 15:36:29 +03:00
Michael Schroeder de3f36acc9 Add an index sync call at the end of a database rebuild
This is normally unneeded because an index sync is already done
after each package is added to the database. But rebuilding an
empty database lead to no index sync being done and a mismatch
between the generation count. This in turn will trigger a
index regeneration.

Found by using ndb when running the test suite.
2020-04-14 13:22:12 +03:00
Michael Schroeder 6511823c97 ndb: make rpmxdbWriteHeader a void function
It's a static function and nobody tests the return code. It just
writes into mapped memory like rpmxdbUpdateSlot, which is also void.
2020-04-14 13:22:12 +03:00
Michael Schroeder 1187cf005a ndb: unmap xdb's header when closing the xdb database
Somehow I was under the impression that mapped regions are unmapped when
the corresponding file descriptor is closed, but that's not the case
for POSIX systems.
2020-04-14 13:22:12 +03:00
Michael Schroeder aea8c86ec8 ndb: do not map xdb's header read-write all the time
Instead just map it read-write if one of the functions request
exclusive access. We keep track of the number of exclusive
locks and fall back to read-only mapping if the count reaches
zero again.
2020-04-14 13:22:12 +03:00
Michael Schroeder 3cfd298e9d ndb: do not map the index databases read-write all the time
Pass the flags to rpmidxOpenXdb and use read only mode if the
user specified O_RDONLY. We already did that for rpmidxOpen in
the past but we always used read-write mode when using the Xdb.

We still open the Xdb itself in read-write mode so that we can
regenerate missing index databases.
2020-04-14 13:22:12 +03:00
Michael Schroeder 85b51e2dcf ndb: also copy the mapped pointer when keeping a slot
We forgot to copy the mapped pointer if a slot was kept when
re-syncing after a generation mismatch. This led to the mapped
pointer being zero even if the map callback was set.
Also add an extra test for the map callback before setting the
protection flag to PROT_READ.

Found by testing the code with different mapping protection flags.
See the next commits.
2020-04-14 13:22:12 +03:00
Panu Matilainen 233ee5516f .gitignore cleanup
Lots of cruft here - the build-aux move related changes from commit
cd6e4eb9e0, and all manner of historical
cruft that hasn't existed in over a decade. While at it, consolidate
it all to the toplevel .gitignore.
2020-04-09 14:27:09 +03:00
Panu Matilainen 853c48ba64 Fix regression causing segfault on database autodetection
If configuration points to non-existent backend, tryBackend() will
segfault on the first call. Duh. Regression introduced in commit
3eb0eed380.
2020-04-02 13:53:49 +03:00
Panu Matilainen 8ed452dd86 Flush 1998 vintage fcntl-compatibility mess from system.h
fcntl.h is standard, include it from places that need it and drop
from system.h.
2020-04-02 13:53:38 +03:00
Panu Matilainen 7630389dcd Flush 1998 vintage dirent.h compatibility mess from system.h
dirent.h and struct dirent are actually standard on this millenium, the
only thing that isn't is d_type member for which we have and retain
a specific test in configure.ac. Include <dirent.h> where needed,
relatively few places do which makes it even a bigger insult to have
this included from system.h.
2020-04-02 13:53:38 +03:00
Panu Matilainen f8b8e86ae3 Flush 20+ year old statfs() jungle, always use standard statvfs()
Unlike that multiple statfs() variants, statvfs() is actually in
POSIX 1-2001 already and covers everything we need so there's little
point mucking with anything else. statvfs() is what Linux has been
using all along anyway this means no change on the primary platform.

If this actually regresses something, adding back OS-specific bits
is not a problem, but at least we'll get a clean start with that.
2020-03-30 10:28:41 +02:00
Panu Matilainen 7de982ac09 Drop the experimental LMDB backend
In the three years that LMDB support has been in the tree, and four
since upstream promised 1.0.0 in a couple of months, there have been
no upstream changes towards eliminating the key size limitations that
we need. And in the meanwhile it has become clearer that LMDB is not
the promised land it seemed on the outset, instead it has issues
like requiring the database size to be pre-determined (#902).

Drop support for LMDB, there's active development going on in the area
of database backends and we cannot afford to drag along an experimental
backend that is blocked on upstream design limitations and shows no signs
of moving forward. We can always bring it back if the upstream situation
changes.
2020-03-20 12:31:04 +02:00
Panu Matilainen 8cd161b5bb Always open (and initialize) the entire database at once
In some scenarios we previously only created some of the indexes only
lazy db init through query. Partially initialized databases don't make
sense and are only asking for trouble, in particular this was causing
issues with sqlite backend which is stricter about readonly-mode.

Except for the special case of reading a potentially damaged database
for rebuilding, always open all the indexes from openDatabase().
2020-03-17 09:41:52 +02:00
Panu Matilainen 3eb0eed380 Rework and clarify database backend detection logic
Try the configured backend first, and only if that fails try autodetection.
The former logic did not anticipate multiple backends handling same
files and gets mightily confused when both bdb and bdb-ro are enabled,
causing half the test-suite failing in "make check".

Also emit a different message when database rebuild is in progress,
the old message is quite confusing in that case.

Loosely based on a similar patch by Michael Schroeder.
2020-03-17 09:41:21 +02:00
Panu Matilainen ba385ec5b7 Visibly deprecate RPM v3 support
"RPM v3 is dead" has been repeated over and over in various forums for
the last 15+ years but as long as rpm itself silently accepts it, most
users will have no clue. Log a deprecation warning on V3 retrofits,
in anticipation of eventual removal.

Related: #1107
2020-03-10 11:56:51 +02:00
Panu Matilainen b4a3f6c624 Introduce a new qualifier for meta dependencies (RhBug:1648721)
Add a new "meta" qualifier for expressing dependencies that are not
concrete install- or run-time dependencies, and thus should not take
part in install ordering.

There are quite a lot of such dependencies in the wild, for example
versioned sub-package cross-dependencies are typically of this type
and a common source of unnecessary dependency loops. Another common
case are dependencies of meta-packages.
2020-02-27 12:17:45 +01:00
Florian Festi 2fcccaaf24 Add isTransientReq macro
Centralize the logic in one place to make it easier to add new qualifiers

These relations are only relevant during installation and are ignored at some
places e.g. when processing already installed packages. They are also not added
to the rpmdb indexes.

The way the qualifiers work is a bit peculiar as no qualifier means the
relation is always relevant. Adding any qualifier restricts the the relation
to this particular place and time. But adding more qulifiers do not further
restrict the validity of the relation but adds more relevant cases.

So here there are three cases:

No qualifiers, only install only qualifiers, install only qualifiers that
get overruled by others
2020-02-27 12:17:45 +01:00
Panu Matilainen c9380471ad Fix prefix match searches on strings containing % on sqlite backend
SQL LIKE is a quirky thing when you only really want exact matches
on a substring. SUBSTR() looks promising until somebody points out
that it counts unicode characters, whereas rpm always deals with bytes.

Implement a custom MATCH() operator which operates on arbitrary bytes
to handle it the way other backends do.
2020-02-27 12:51:01 +02:00
Panu Matilainen 1913d84c1e Use uppercase for SQL(ite) keywords consistently, cosmetics only 2020-02-27 12:51:01 +02:00
Michael Schroeder 243041f5fb Add a --salvagedb option to the rpmdb tool 2020-02-26 12:50:22 +02:00
Michael Schroeder 6489957449 ndb: add a rpmpkgSalvage() method
This can be used to recover as much data as possibly from a
terminally broken database. It works by scanning the database
file for entries that are not corrupt.
2020-02-26 12:50:22 +02:00
Michael Schroeder fafdc80bf4 Use the transaction set as argument in rpmalCreate()
The rpmalCreate() function is called in two places, in both of
them the arguments are all read from the transaction set.

So simplify the code by passing the ts to rpmalCreate() and
getting the values in the constructor.
2020-02-24 11:54:22 +02:00
Michael Schroeder b2e1b46428 Switch dependency checking to use pool ids instead of strings
This needs less memory and it should also be faster as the
dependencies are already available in id form.
2020-02-24 11:54:22 +02:00
Michael Schroeder c68d858c3d Only lookup the fingerprint when the directories do not match
If the directories match the fingerprint is not used.
2020-02-24 11:54:22 +02:00
Michael Schroeder 6f9426c501 Get rid of id->str->id roundtrips in rpmalAllFileSatisfiesDepend()
We already know the ids, so just use them for fingerprinting.
2020-02-24 11:54:22 +02:00
Michael Schroeder e2f0fbcc29 Add fingerprint lookup/compare variants that take ids
This will be used to get rid of unneeded id->str->id roundtrips.
2020-02-24 11:54:22 +02:00
Michael Schroeder 5d4489f344 Only look at symlinks in new packages in fpLookupSubdir
For already installed packages only the on-disk state matters,
which is already picked up by the fingerprinting code.
2020-02-24 11:38:13 +02:00
Michael Schroeder ba9718211d Reduce the number of calls to fpLookupSubdir()
If the entry/subdirid parts of the fingerprint are equal to the
ones of the last added fingerprint, we know that calling
fpLookupSubdir() will not modify anything. So skip the call in
that case.
2020-02-24 11:38:13 +02:00
Michael Schroeder 02e1f3bc3a fpLookupSubdir: get rid of a poolid->str->poolid roundtrip
Use doLookupId() instead of doLookup() so that we can reuse
the baseNameId.
2020-02-24 11:38:13 +02:00
Panu Matilainen 47e2463d8a Auto-enable optimizations for non-rotational disks on Linux
Try to auto-detect non-rotational disks on start of transactions,
and if all involved disks are non-rotational enable optimizations:
%_minimize_io to conserve writes, and %_flush_io to avoid trashing
the system caches.

The configuration logic relies on always pushing a new definition
for these macros so we can reliably undo at setSSD(): ensureMacro()
pushes the current value again if one exists, otherwise the supplied
default is used.

Update macro documentation as per the new behavior.
2020-02-19 13:26:37 +01:00
Panu Matilainen dd0b975a00 Only enable flush_io and minimize_writes on positive values
Fix the logic for enabling flush_io and minimize_writes -behaviors,
-1 generally means automatic, 0 disabled and 1 enabled. But these
are by no means mandatory macros so comment out the default setting
for minimize_writes as well.
2020-02-19 13:26:37 +01:00
Panu Matilainen 96b0b48e6a Also do foreign key integrity check on sqlite db verify
This will detect some "shouldn't happen" cases such as rpm indexes
pointing to non-existent packages, which is far from covering full
database consistency but much more than at least BDB/LMDB can do.
2020-02-19 09:09:38 +01:00
Panu Matilainen 3afa674ad8 Fix sqlite verify results checking
PRAGMA integrity_check returns a single "ok" line if everything checks
out but otherwise error messages get returned, so we need to actually
check the returned values.

Also change the way return code is constructed in preparation for the
next commit.
2020-02-19 09:09:38 +01:00
Michael Schroeder 879dbdc020 Remove duplicated code in fpLookupSubdir
When we encounter a symlink, we have to restart the function from
the beginning. Instead of duplicating the setup code, add a new loop
and make the code do a iteration for each symlink.
2020-02-14 12:45:59 +02:00
Michael Schroeder e929bf318a Move fingerprint hash setting out of fpLookupSubdir()
fpLookupSubdir() purpose is just to patch the fingerprint to
account for symlinks. It's much cleaner to set the hash after
the call to fpLookupSubdir(), and we can also skip the call
if no symlinks were found.
2020-02-14 12:45:59 +02:00
Michael Schroeder e9ea37a78e fsmMkdirs: do not dup the last verified directory name
Instead just save the pointer returned from the iterator, which
is a pointer into the pool.
2020-02-14 10:08:07 +02:00
Michael Schroeder 66013f50d1 fsmMkdirs: Remove dnlx array
It gets only written to and nobody uses it, so be gone.
2020-02-14 10:08:07 +02:00
Panu Matilainen a0e24f2caf Reset global macro state after each spec query/parse
Parsing a spec, even unsuccessfully, will affect the global macro
state in any number of ways that may affect the following operations
in unpredictable ways. Lacking any saner way to do this, reset the
entire global macro state after each spec parse in rpmspec and spec
query code (rpmbuild already does this) while maintaining possible
cli-specified target and rcfile.
2020-02-12 10:23:23 +01:00
Panu Matilainen c886b359ba Fix pointer dereference before testing for NULL in rpmtdGetNumber() 2020-02-06 15:32:54 +01:00
Florian Festi d937b04fb1 Fix isUnorderedReq() for multiple qualifiers
isUnorderedReq() returned True as soon as any qualifier that does not
require ordering is passed. But some qulifiers - basically the scriptlets
run during installation and erasure of the package - may still require
the dependency to be taken into account during ordering.

Now isUnorderedReq() returns 0 if any of those are also set.

Resolves: #1030
2020-02-05 12:14:14 +02:00
Florian Festi 83306c2009 Move <dlfcn.h> out of system.h
It is needed in lib/rpmplugins.c only anyway.
2020-02-04 16:39:16 +02:00
Michael Schroeder 2d63d5ee78 Permit ndb database queries on read-only media
See also commit a429c99e13 for db3.
2020-02-03 12:53:24 +02:00
Panu Matilainen 85e5a70368 Fix regression on v3 package handling on database rebuild
Introduced in commit 27ea3f8624, the
wrong header is being added in case of v3 packages.

Fixes: #1017
2020-01-29 14:12:09 +02:00
Michael Schroeder bc13afbbfd ndb: fix ftruncate return value warning 2020-01-15 12:48:47 +02:00
Michael Schroeder 7cc9eb84a3 Add support for reading BDB without the library
This commit implements a read-only backend that allows accessing
of BerkeleyDB databases without using the BerkeleyDB library.
The code supports btree version 9-10 and hash version 8-10.

There are two use cases for this:

1) Conversion of an existing BerkeleyDB to a different
   backend.

2) Allowing package scriptlets to do database queries while
   in a transaction that replaced rpm with a version that
   no longer links against BerkeleyDB.

If both BerkeleyDB and the read-only backend are enabled, rpm will
default to BerkeleyDB.
2020-01-13 16:12:13 +02:00
Michael Schroeder 40269d4b3f ndb: implement index regeneration if the index is out of sync
We compare the user generation stored in the index database with
the generation count from the package database. In case there
is a mismatch, we delete all the index databases and rely on the
already existing missing index creation code to rebuild the
database.
2020-01-13 13:09:52 +02:00
Michael Schroeder 49d43a3345 ndb: add a rpmxdbDelAllBlobs method
This will delete all blobs (i.e. index databases) from the
ndb master index database. We do this kind of low-level on purpose,
so that it even works if the index database is corrupt.

This will be used in the next commit which implements automatic
index regeneration if the index is out of sync.
2020-01-13 13:09:52 +02:00
Michael Schroeder 52c3ee60a1 ndb: only clear the dbenv in the rpmdb if the last reference is gone
Otherwise we will segfault if just one index is closed.
2020-01-13 13:09:52 +02:00
Michael Schroeder f674af7efb ndb: use the generation instead of the current time in blobs
This seems to saner as the somewhat unreliable current time.
This element is not used in normal database operation, it is
for repair tools that need to decide which blob to take if two
blobs have the same pkgid.
2020-01-10 15:01:45 +02:00
Michael Schroeder 3feb7993a8 ndb: add a verify method
This adds a verify method for ndb's Packages.db database. The
Index.db database is currently not verified.
2020-01-10 15:01:45 +02:00
Michael Schroeder d435beb937 ndb: no longer free the pkgid hash all the time
Reuse the hash if the size matches. This was actually the original
intention, but for some reason the code was disabled by always
freeing the hash.
2020-01-10 15:01:45 +02:00
Michael Schroeder 8e39098fa9 ndb: drop unused number of allocated slots
This is not used as we re-read all slots everytime a package
is added or deleted.
2020-01-10 15:01:45 +02:00
Michael Schroeder cbe9bcf954 ndb: make "ordered slots" flag a boolean
We never needed to order by pkgid or slot number, so simplify
the code.
2020-01-10 15:01:45 +02:00
Michael Schroeder d8902b0ddd ndb: add and clarify some comments 2020-01-10 15:01:45 +02:00
Michael Schroeder dc0a504d3e ndb: remove unused lzo compression code 2020-01-10 15:01:45 +02:00
Panu Matilainen bb30f997c4 Don't require signature header to be in single contiguous region part II
The generic case was reported in #270 and fixed quite a while ago in
commit 34c2ba3c6a, but signing uses a
different code path and require the same treatment.

Fixes: #1002
2020-01-10 10:31:47 +02:00
Alexander Kanavin 5eb7be61e9 rpmplugins.c: call dlerror() prior to dlsym()
This is the recommended way in the manpage; if there is
a lingering error from an unrelated dl*() call that was
never obtained via dlerror(), it needs to be cleared
prior to calling dlsym().
2020-01-08 13:18:59 +02:00
Michael Schroeder 166c6c5a1e Move db_descr assignment from rpmdb to dbi
It is already used for printing error messages in the dbi backends.
2019-12-26 09:00:37 +01:00
Panu Matilainen 0094eaaf65 Avoid pulling unused data from the database in sqlite backend
We don't need to pull the key values from the db here, we already have it.
2019-12-11 11:28:02 +02:00
Panu Matilainen f964889b13 Don't bother sorting dbi set from the backend
The upper layers sort the dbi set as necessary, this is nothing but
waste of perfectly good computing cycles.
2019-12-11 11:28:02 +02:00
Panu Matilainen 10f0fe221e Use a sub-cursor for sqlite index key iteration
Spinning new cursors for each key value is just mind-bogglingly stupid
(if simple), use a sub-cursor with key binding instead. Which isn't any
more complicated, really.
2019-12-11 11:28:02 +02:00
Panu Matilainen d402c202ee Trash the stupid sqlite statement cache
Caching statements is not stupid but when it makes us go slower...
Also without the cache we have a better handle on locks and all,
revisit the caching issue later.
2019-12-11 11:28:02 +02:00
Panu Matilainen 25932e98bb Never reuse cursors for different purposes in sqlite
Rpm can reuse an iterator cursor for a write when rewriting an existing
header (such as when updating file states of already installed package),
which in sqlite terms turns a SELECT into INSERT, destroying the
iteration in progress.

Detect the condition and use a local cursor as necessary, this also means
we don't need to track the query fmt string in cursors.
2019-12-11 11:28:02 +02:00
Panu Matilainen e769796d6a Simplify sqlite cursor preparation logic
No functional changes, just makes the thing a little clearer.
2019-12-11 11:28:02 +02:00
Panu Matilainen 0f0fbead08 Use the new index key iterator for dependency check hashes
In normal transactions this is but a drop in the ocean. However on
rpm -Va, the hashes get rebuilt from scratch on every single package
which on my moderate rpmdb (~2800 packages) testcase results in
103418347 data values fetched and added to dbi sets that are only
thrown away.

With bdb and lmdb this is only a minor optimization but for ndb and sqlite
which can retrieve keys independently, this is a much bigger win. In case
of sqlite, it's a massive one.
2019-12-09 11:39:48 +02:00
Panu Matilainen 4eb7900d54 Implement a key-only rpmdb index iterator
The regular index iterator grabs the associated data too, which we
don't always need. The data associated with indexes is relatively
lightweight, but as with everything, it adds up if in the millions scale.

Update all backends to allow for NULL set in the index retrieve to
signal key-only retrieval. Ndb actually had an earlier, abandoned
implementation of the same idea under slightly different API, lets
reuse the code-block.
2019-12-09 11:39:48 +02:00
Panu Matilainen 19e375880c Optimize sqlite database rebuild
Postpone sql index creation until closing time on database rebuilds,
this is more than 50% improvement on rebuilddb time on both SSD and
traditional disks.
2019-11-25 10:07:05 +02:00
Panu Matilainen 9c8a3faf42 Fix sqlite database access for unprivileged readers in WAL mode
As of sqlite 3.22.0, a database in WAL mode can be opened readonly
if one or more of the following is true:

1) The -shm and -wal files already exists and are readable
2) There is write permission on the directory containing the database
   so that the -shm and -wal files can be created.
3) The database connection is opened using the immutable query parameter.

Regular users running queries cannot have permission to create, and
immutable databases can only exist on readonly media (because all locking
is disabled) so there's no choice but to leave the -shm and -wal files
around at all times, a little ugly as it might be.
2019-11-21 09:36:50 +02:00
Panu Matilainen f5e6a4815a Fix sqlite db open logic on errors, hopefully
Handle read-only database separately for table and index initialization
as they are different: if table cannot be created we're screwed and
should return an error, but if an index is missing it'll still work.

Also only return an allocated dbi if everything went okay.
2019-11-21 09:36:50 +02:00
Panu Matilainen 6e91d914c5 Ask sqlite if it's in readonly mode instead of educated guess 2019-11-21 09:36:50 +02:00
Panu Matilainen d320a1c67c Tie sqlite WAL auto-checkpointing to %_flush_io macro setting
While flushing IO constantly is horrible for performance on spinning
disks, it's beneficial on SSDs. So if %_flush_io is enabled, let sqlite
do its regular WAL auto-checkpointing. Pure DB install time on SSD
improves by some 25% here with %_flush_io, at cost of removal speed but
for overall sanity and smaller WAL file.
2019-11-15 08:09:59 +02:00
Panu Matilainen a8588f8e39 Switch to write-ahead-logging (WAL) mode on sqlite backend
This is an enormous performance boost to almost all operation modes,
in particular spinning disks - on my old laptop, time to erase ~3300
packages comes down from half an hour to under three minutes.

By default sqlite likes to keep the WAL file relatively slow to keep
reader performance up, but as writes are rare in rpm, we let the WAL
grow unlimited during transactions and only flush it at database
close. This way transactions are fast and at the cost of read
performance during transactions, which is perfectly okay. To do this
we need to move statement cache free earlier to drop any locks that
might be lurking there.

Special handling of RPMDB_FLAG_REBUILD is dropped here as unlike other
modes, WAL is persistent and has interactions with EXCLUSIVE locking_mode
among other things that seem non-trivial to sort out. This has some
performance cost to --rebuilddb but it's a rare operation and normal
transaction performance is far more important. We can always tweak
it more later on...
2019-11-15 08:09:59 +02:00
Panu Matilainen 61e13a608a Oops, the sqlite default "synchronous" mode is FULL, not NORMAL
This would've caused inconsistent behavior between databases where
fsync is explicitly set to enabled and to one where it was not set.
2019-11-15 08:09:59 +02:00
Panu Matilainen db1efd0828 Sqlite index tweaks for performance
Only create key indexes for strings, those are the ones that are
performance critical and anything else is just unnecessary weight.
Additionally create indexes on hnum for better performance especially
on erasure, but only bother for array type data where the amounts
get large enough for indexes to matter.
2019-11-15 08:09:59 +02:00
Panu Matilainen 7d1c644756 Reset sqlite statements at cursor close to free locks on database
As we now cache the statements, not reseting the statements kept most
of the database locked for the whole transactions, preventing concurrent
access.

Logic seems to suggest that we could then not bother reseting on fetch
from cache, but that causes failures so there's something fishy still.
2019-11-15 08:09:59 +02:00
Panu Matilainen e80f13764b Set sqlite db handle to NULL on db close to ensure no dangling pointers
sqlite_init() relies on db_dbenv pointing to NULL to properly initialize,
not sure if we can actually end up reusing the same handle but just in
case...
2019-11-15 08:09:59 +02:00
Panu Matilainen bea298986d Force case-sensitive LIKE operator in sqlite
We use LIKE for key prefix searches (file triggers) and case certainly
matters there.
2019-11-15 08:09:59 +02:00
Panu Matilainen a39824fc3a Add an error callback to the sqlite backend
Normally no output is expected there, but will help catch out abuses
and other surprises.
2019-11-07 13:43:03 +02:00
Panu Matilainen ad329e600a Ensure sqlite secure_delete behavior is disabled
Upstream sqlite defaults to secure_delete off, but its default value
is also a compile-time option which some distros (at least Fedora)
change to have it enabled by default. There's never any sensitive data
in the rpmdb, don't bother zeroing it out. Improves performance somewhat.
2019-11-07 13:43:03 +02:00
Panu Matilainen cf0e94cc8e Let sqlite handle header number allocation, don't recycle header numbers
The initial implementation could recycle the topmost header numbers which
breaks libsolv caching as it assumes the traditional rpm behavior where
header numbers are not recycled.

Sqlite primary integer key with autoincrement behaves exactly the way rpm
database has traditionally allocated new "instance" numbers, and does not
seem to have any performance impact in this usage as there's always a
limited number of such increments anyway. Let it do the job instead.
2019-11-07 13:43:03 +02:00
Panu Matilainen e5ba3247d8 Handle DBI_CREATED flag correctly for all tables in sqlite
Use sqlite3_table_column_metadata() to detect whether a table exists.
This will allow newly added rpm indexes to be automatically generated
and doesn't require running sql queries to figure out whether the
database was just created or not (and get it wrong because an empty
database would appear as newly created)
2019-11-07 13:43:03 +02:00
Michal Domonkos 1cb3be0009 Handle incomplete escape seq in queryformat (RhBug:1755230)
Previously, we assumed a backslash character would always be followed by
a character to be escaped, and advanced our "start" pointer by two
places before the next iteration.  However, this assumption breaks if
the lonely backslash happens to be the last character in the query
string, in which case we would end up pointing beyond the \0 and let the
parser wander into the unknown, possibly crashing later.

This commit ensures we detect this corner case and error out gracefully
with a message.
2019-11-04 12:49:43 +02:00
Panu Matilainen 9fe75561f9 Replace uses of localtime() with the re-entrant variant
LGTM flags localtime() as a "dangerous" function, which seems a bit
over the top to me, but as we're flirting with threads, it certainly
is not thread-safe.
2019-10-31 11:59:20 +01:00
Panu Matilainen d609a426f6 Resurrect --prtpkts debug switch functionality
Move the _print_pkts global to librpmio where the two relevant users
can actually access it, and make them use it. This has been broken
for years...
2019-10-31 11:59:20 +01:00
Panu Matilainen 63930cd524 Only permit comments at beginning of line in file manifests (RhBug:112727)
We only permit comments at beginning of line in specs and macro
files too, of all things file manifests don't need anything fancier.
Resolves the oldest rpm bug in RH bugzilla, only took 16 years...
2019-10-30 14:58:47 +01:00
Panu Matilainen c822fe7b90 Remove redundant check, size is unsigned so condition is always true 2019-10-30 14:54:09 +01:00
Panu Matilainen 7a1ffb2774 Fix parameter hiding in rpmdsNewPool()
Harmless but also unnecessary obfuscation.
2019-10-30 14:54:09 +01:00
Panu Matilainen 48501e918b Fix parameter hiding in scriptlet expansion
Harmless but also unnecessary obfuscation.
2019-10-30 14:54:09 +01:00
Panu Matilainen b9ee269fba Honor RPMSENSE_MISSINGOK on src.rpm rpmlib() dependencies too 2019-10-28 15:29:50 +02:00
Panu Matilainen bd79605819 Handle setting db_descr centrally from the backend name
Now that we can, set db_descr centrally on database open instead of
relying on backends to do it (and forget, or leak memory, as has been
the case). Also don't bother mallocing, the name of the backend is
quite enough.

With backends knowing their own names we could probably eliminate db_descr
entirely but leaving that for another rainy day, it's possible there
are code paths that assume it being set to something.
2019-10-28 15:29:02 +02:00
Panu Matilainen 385a0a417b Cache prepared SQL statements for future use
Preparing SQL statements from textual representation is relatively
expensive and we do it a lot. Add a refcounted hash table for
reusing the statements, which roughly halves the time of rpm -Va,
other operations will naturally benefit too.

db_cache should really be a private member someplace in the sqlite
backend but there's no place to hang it, so without bigger changes
that are out of scope here, the only option is adding a new member
to the rpmdb struct itself.
2019-10-28 15:29:02 +02:00
Panu Matilainen 6e9f3dfc4b Fix a titanitic memory leak in the sqlite backend
The rest of rpm expects to get a pointer to a temporary data area
containing the header blob, which is then copied on header import.
Seems my recollection of this was the exact opposite, so the sqlite
backend was pushing back malloced copies of the blobs that nobody would
then free. Oops, leaks, leaks, leaks, sunk.

There's no need for sqlite to be different in this regard, but during
Packages iteration the implementation used a temporary cursor for
the actual header, causing the data to go away before reaching the
upper layers which necessiated dup'ing the data, that nobody would free.
Refactor to eliminate the temporary cursor from the picture to fix the
mismatch of expectations and thus the leak.
2019-10-28 15:29:02 +02:00
Panu Matilainen 4eda663a5f Fix --querybynumber on non-existent record, add test
RPMDBI_PACKAGES differs from the indexes in how record searches behave,
indexes return NULL for non-existent values but with RPMDBI_PACKAGES
(and the pseudo index LABEL) we always get an iterator which we need to
walk to determine whether there's data or not. Use the newly introduced
helper to get the query return right.

One could argue that this should be done in the database code, but then
the behavior is kinda consistent other iteration over RPMDBI_PACKAGES:
you don't know how many, if any, matches there are until you walk it.
2019-10-28 15:28:34 +02:00
Panu Matilainen 3754abffa1 Refactor query match counting to a helper function
No functional changes here, needed for the next commit.
2019-10-28 15:28:34 +02:00
Panu Matilainen 83a26ae9e1 Implement support for alternative (uncompressed) payload digest
During build, also calculate a digest for the uncompressed payload data
and add to packages. On verify side this is equivalent to the existing
payload digest (through sharing the same disabler), which allows
either one to be used for verification. This means deltarpm and similar
don't need to recompress the data which is both expensive and error-prone
due to minor differences in compressed stream despite the actual data
being identical.

Add a testcase for the basic behavior and update other test output
expectations where necessary.
2019-10-28 15:27:56 +02:00
Panu Matilainen 4739ce8213 Implement verify support for alternative digests and signatures
Implements generic logic to let one digest/signature to act as an
equivalent alternative to another one.
2019-10-28 15:27:56 +02:00
Panu Matilainen d05ea15d7f Implement rpmdbStat() and rpmdbFStat() APIs
rpmdbStat() can be used without an open rpmdb handle similar to stat()
and rpmdbFStat() takes an open rpmdb handle, akin fstat().

The rationale for these calls is to give API users a backend-independent
way of obtaining data about the database's existence, timestamps etc.
2019-10-23 09:57:10 +03:00
Panu Matilainen ca72e2b923 Document dummy backend in macros, warn on dummy fallback
As the dummy backend supports no operations whatsoever, using it as
a fallback if all else fails needs to emit a warning, not debug goo.
2019-10-23 09:57:10 +03:00
Panu Matilainen 108adfc4d1 Use paths from db_ops in the backends too where possible
ndb and sqlite have control of their own paths, BDB and LMDB do things
differently and dummydb doesn't have a path at all.
2019-10-23 09:57:10 +03:00
Panu Matilainen bc236cc369 Use the new backend struct data for backend configuration and detection
Refactor the hand-written separate tests into an array walk now that we can.
No functional changes, except that there's no more special fallback for BDB.
2019-10-23 09:57:10 +03:00
Panu Matilainen bc00f99cb0 Add backend name and path of main database file to db_ops struct 2019-10-23 09:57:10 +03:00
Michael Schroeder 62e6a75071 Multiple fixes in rpmxdb.c for the ndb database backend
Found by torture-testing the ndb database.

* Usedslots was allocated with the wrong size
  This did not matter for rpm because rpm uses only a small
  number of index databases

* The addslotpage function did not enqueue the new free slots correctly
  It never gets called in rpm

* The protection bits were not set if moveblobto needed to map a blob
  This can happen if it is called from the moveblobstofront() function,
  it will just not shrink the database in the current call.
2019-10-21 15:53:00 +03:00
Michael Schroeder 20fd808020 Use xdb's pagesize instead of sysconf(_SC_PAGE_SIZE)
Our xdb may use a different page size for some reason.
2019-10-21 15:53:00 +03:00
Panu Matilainen 8094754daa Stop building BDB specific rpmdb_* utils even with internal BDB
Hijacking objects from BDB build tree was always pretty gross, and
nowadays there's simply no place left for them.
2019-10-21 15:43:28 +03:00
Panu Matilainen 5bf88af9cc Optimize sqlite index data deletion
On sqlite, deleting doesn't require painstakingly recreating the same
exact data that was used for putting, we can just sweep out everything
with the given header num at once. Cuts roughly 1/4 out of erase time.
2019-10-18 13:29:14 +03:00
Panu Matilainen 77af8e5911 Push rpmdb index put/del deeper into the backend
Let the backend see update of a single index as a whole instead of
single items fed by the upper layer. This allows backends to optimize
these operations in various ways that haven't been possible previously.
2019-10-18 13:29:14 +03:00
Panu Matilainen 0be04ef2a3 Assimilate pkgdbNew() into pkgdbPut() interface
Pass header number to pkgdbPut() as a pointer so we can return values too.
Having allocation as a separate call unnecessarily dictates details
about backend implemenation, and this makes it all just that little
bit simpler. No functional changes.
2019-10-18 13:29:14 +03:00
Panu Matilainen 07129b641b Add an experimental sqlite based rpmdb backend
All normal functionality is expected to work. Automatic generation
of missing index tables is missing, but that's not relevant at this time.
Going forward, we'll also want some sort of compatibility tracking
for the sql schema.

The database scheme basically just mirrors what BDB does, using strings
for strings and blobs for everything else due to the way integers are
handled in the sqlite C API, for now at least. Some amount of schema
changes are to be expected before this is considered final.

Performance is similar or better with BDB in the current unsafe CDB
model, but sqlite uses proper database transactions so this is expected
to be an order of magnitude more robust.

Many things are stupid and/or kind of backwards here due to the internal
API, which I've avoided changing in order to keep it backportable for the
time being. https://github.com/rpm-software-management/rpm/pull/836 is
needed but otherwise this should drop quite trivially into 4.14.x too.
However as we're planning for a longer term future here, it would be dumb
to limit ourselves by what's possible with an internal BDB-oriented API,
so I've fairly major changes planned in that direction.
2019-10-18 10:38:34 +03:00
Panu Matilainen 7ba4b9bdcf Don't report unimplemented db ctrl and verify ops as errors
ndb doesn't implement a specific verify option, but that doesn't mean
the data within should be considered invalid. This causes ndb to fail
the test-suite on "rpmdb --rebuilddb and verify empty database" for no
good reason. Similar arguments could be made for dummydb although it
matters much less there.
2019-10-17 14:16:36 +03:00
Igor Kanyuka a623c45ac7 Increase lmdb DB size from 256M to 1G 2019-10-17 09:57:27 +03:00
Michael Schroeder 3625ca14c7 Refactor mmap/munmap/mremap handling in ndb
Also emulate mremap with mmap/munmap in ndb if it is not
available.
2019-10-16 12:09:51 +03:00
Michael Schroeder 9ac6c427d2 Use fdatasync in ndb if available
No need to always sync the inode metadata.
2019-10-16 12:09:51 +03:00
Michael Schroeder 09cc8ebad2 Do not always fsync the database directories
Only call fsync when new database files got created.
2019-10-16 12:09:51 +03:00
Michael Schroeder 1c45d96b32 Delete all the IDXDB_FILESUPPORT code in the ndb backend
Rpm will always use xdb instead of plain files for the
database indexes.
2019-10-16 12:09:51 +03:00
Michael Schroeder af64fe18ff Implement fsync disabling for the ndb backend
For some reason this never got implemented. Spotted by
Jeff Johnson, thanks!
2019-10-16 12:09:51 +03:00
Panu Matilainen b759eee443 Always execute file trigger scriptlet callbacks with owning header
This is part II of commit 6d610e9b9a which
missed one but common case where the element with matches gets passed
to the callback instead of the owning one, as pointed out in RhBug:1724779.
2019-10-15 13:29:18 +03:00
Panu Matilainen facee2c70a Avoid using types from Lua includes in rpmlua.h again
rpmlua.h was originally written in a way that allows it to be included
regardless of whether Lua is actually enabled in rpm or not, or where
Lua headers are, specifically to isolate the rest of rpm from these
details. That was changed in commit 62bd62286a
when <lauxlib.h> started getting included in rpmlua.h, which leaks to
places like librpmbuild which do not directly use Lua.

The way Lua typedef's the luaL_Reg struct to itself defies my C fu for
for handling this in some nicer typesafe way, fix this all by just using
a void pointer instead, this is just an internal API where buyer can be
expected to beware.

Fixes #888
2019-10-10 16:34:12 +03:00
Panu Matilainen 5584438180 Clarify the disk space problem messages
These messages have been an endless source of confusion and complaint
throughout their existence, to the point that various programs have added
their own "translation" for these messages. Changing the message is likely
to break those (regex-based) translations but then hopefully the
translations will not be needed after this.

Fixes #879 (and at least a dozen bugs in various distro bugzillas
whose numbers I'm too lazy to dig up)
2019-10-07 14:40:19 +03:00
Panu Matilainen 8f6b56c72a Avoid modifying header on export
headerExport() is the only thing that needs offset sorting, there's
no point messing up with the header itself for this when we can just
sort a copy instead. No visible functional changes, but makes
headerExport() a read-only operation to the header, as it should be.
This also makes h->sorted a straightforward boolean indicating whether
the index is currently sorted or not instead of the strange tri-state
thing it has been (see commit da3a3a14e7)
2019-09-27 15:17:00 +03:00
Panu Matilainen 3c5e62fe17 Refactor the actual work from headerExport() to a helper function
No functional changes, this is just to create a barrier between
access to the header structure and what is actually needed from it,
ie just the index. This makes the next step much more obvious.
2019-09-27 15:17:00 +03:00
Panu Matilainen 0508e9a6e3 Localize our chroot in/out operations during transactions
The primary motivation here is to consolidate all database writes
(open, write, close) on one side of the chroot, currently it happens on
both sides of the border causing all sorts of issues and limitations (such
as preventing more advanced modes of BDB, not to mention other databases).
As a positive side-effect, the sections where we potentially run
inside chroot are more easily identifiable.

Consolidating on the outside may seem counter-productive, to improve
security it seems you'd want to spend as much time *in* as possible,
including database accesses. Unfortunately due to rpm's access patterns
and API promises, that's not really achievable (tried several approaches,
run into as many dead-ends).

Technically we could localize the chroot placement much further, but
doing so would change the side for transaction callbacks, which could
cause nasty breakage for our API users as various clients use those
callback slots to update their own databases and logs. So the chroot
spots here are selected to cover minimum possible code while preserving
the chroot side of callbacks and plugin slots: RPMCALLBACK_INST_OPEN/CLOSE,
ELEM_PROGRESS and VERIFY_* occur outside the chroot, everything else inside.
Of plugin slots, init/cleanup and tsm_pre/post occur outside, everything
else inside.
2019-09-25 14:10:18 +03:00
Panu Matilainen 3fbf5c58ec Refactor goal execution out of rpmpsmRun()
rpmpsmRun() has gathered so much extra logic around the beef that this
seems reasonable. In particular this makes the next commit much nicer.
2019-09-25 14:10:18 +03:00
Panu Matilainen 858d6babd6 Log debug messages upon entering and exiting chroot 2019-09-12 15:57:47 +03:00
Panu Matilainen 5188a7b35e Fix memleak during transaction verify step in the NOKEY case.
Found during RhBug:1714657 QA testing.
In addition, add a comment to clarify the fallthrough as intentional.
2019-08-07 10:27:49 +02:00
Panu Matilainen e219c9548d Fix off-by-one in hdrblobGet() making last entry unreachable (RhBug:1722921)
hdrblobGet() introduced in commits acfde0d0e8
and 9821de1881 has an off-by-one thinko
(perhaps the idea was to skip the first, region tag) which causes
the last entry to be unreachable. In typical packages, that is
RPMSIG_PAYLOADSIZE which is not used at all in this context so it doesn't
matter, but in large packages use RPMSIG_LONGARCHIVESIZE which has a lower
tag number and leaves either RPMSIGTAG_MD5 or RPMSIGTAG_GPG last,
unreachable and thus unverifiable. Oops.

This fixes the regression introduced in rpm 4.14, affecting verification
of large packages (ie having RPMSIG_LONGARCHIVESIZE)
2019-07-31 15:38:03 +02:00
Michael Schroeder 0fcf8c2b86 Use an erase element to delete packages with same NEVRA
Rpm used to rely on the "replacepkgs hack" to get rid of the old
header entry when reinstalling a package. This has a number of
problems when the headers are not identical or different
install flags were used.

To mitigate this, a '--reinstall' option was added that made rpm
use an erase element in this case.

This commit takes this one step further by changing the code to also
use an erase element in the --upgrade case. The code is mostly simpler,
but we need a different implementation for commit fd40d58efa, as we now
have erase elements both for --reinstall and --upgrade. Thus we
need to store the addop in the transaction element.

The commit does not change the behaviour of 'rpm --install'.
2019-07-22 16:42:15 +02:00