Packaging/Unowned Directories

From openSUSE

Contents

Unowned Directories

The term "unowned directory" (or "orphaned directory") refers to a packaging mistake where these three things happen:

  • a package includes files within a directory it creates, but not the directory itself
  • none of the package's dependencies provide the directory either
  • the directory belongs to your package and does not belong to any core package or base filesystem package that is considered essential/fundamental to any openSUSE System.

Issues

Unowned directories can cause the following problems.

Inaccessible Directories

Inaccessible directories are not an issue for openSUSE because RPM resets the umask to 022 since version 4.4.2.3.

Directories not Removed

Upon uninstalling the package (or upgrading to another version), the old directory is not removed from the file system because it does not belong in the package in the RPM database.

Especially if directories contain a version number, they clutter up the file system with every update which doesn't remove old directories.

Directories cannot be Verified

Unowned/orphaned directories cannot be checked with rpm -V and not with rpm -qf either.

./configure Scripts can Fail

Upstream source tarball configuration can fail, because it detects the presence of an old but empty versioned header directories or because it is trying to use multiple versioned directories instead of just the latest valid one.

Tools to Help

It's easy to find unowned directories with rpm -qlv. Just a bit of carefulness is needed to not include core filesystem directories, such as %_bindir, %_libdir (and obvious others, e.g. from the "filesystem" pkg) which don't belong into your package.

Common Mistakes

Here are some examples of common packaging mistakes in spec %files lists to avoid

Wildcarding Files inside a Created Directory

Unversioned

 %{_datadir}/foo/*

This includes everything _in_ "foo", but not "foo" itself. "rpm -qlv pkgname" will show a missing drwxr-xr-x entry for "foo". Correct would be:

 %dir %{_datadir}/foo
 %{_datadir}/foo/*

to include the directory _and_ the entire tree below it.

Versioned

 %{_docdir}/%{name}-%{version}/*
 %{_includedir}/%{name}-%{version}/*.h

This is the same as the unversioned scenario with the addition that everytime the package is upgraded to a new version the old directory will remain on the filesystem. Correct would be:

 %dir %{_docdir}/%{name}-%{version}
 %{_docdir}/%{name}-%{version}/*
 %dir %{_includedir}/%{name}-%{version}
 %{_includedir}/%{name}-%{version}/*.h


Forgetting to Include a Toplevel Directory

 %dir %{_libdir}/foo-2/fu
 %dir %{_libdir}/foo-2/bar
 %{_libdir}/foo-2/fu/*.so
 %{_libdir}/foo-2/bar/config*

Here it is an attempt at including the directories explicitly with the %dir macro. However, while "bar" is included, "foo-2" is not. Typically packagers run into that mistake if all installed files are stored only in subdirs of the parent "foo-2" directory. Correct would be:

 %dir %{_libdir}/foo-2
 %dir %{_libdir}/foo-2/fu
 %dir %{_libdir}/foo-2/bar
 %{_libdir}/foo-2/fu/*.so
 %{_libdir}/foo-2/bar/config*


Only Including Files

 %{_datadir}/%{name}/db/raw/*.db
 %{_datadir}/%{name}/pixmaps/*.png

Here only specific data files are included, and all 4 directories below %_datadir are unowned. Correct would be:

 %dir %{_datadir}/%{name}
 %dir %{_datadir}/%{name}/db
 %dir %{_datadir}/%{name}/db/raw
 %dir %{_datadir}/%{name}/pixmaps
 %{_datadir}/%{name}/db/raw/*.db
 %{_datadir}/%{name}/pixmaps/*.png