\section{RPM (Red Hat Package Manager}

\begin{frame}
   {Advantages of Using RPM}

   \begin{itemize}
      \item Manages software packages
      \begin{itemize}
         \item Collection of files related to a single task or
         subsystem
         \item Contains programs, data, documentation, and
         configuration information
         \item May also contain dependency information
         \item Does not retrieve packages
      \end{itemize}
      \item Advantages for administrators
      \begin{itemize}
         \item Easy to install and uninstall (erase) packages
         \item Easy to verify that a package was installed
         correctly
         \item Can use \textbf{FTP} or \textbf{HTTP} to install
         packages
      \end{itemize}
      \item Advantages for developers
      \begin{itemize}
         \item Can use original ``pristine'' sources
         \item Can generate \textbf{RPM}s for different
         architectures
      \end{itemize}
   \end{itemize}

\end{frame}

\cprotect\note{

   \textbf{RPM} is a package management utility developed
   by \textbf{Red Hat}. (The name originally stood for \textbf{R}edhat
   \textbf{P}ackage \textbf{M}anager.) All files related to a specific
   task are packaged into a single file, which also
   contains information about how and where to install and
   uninstall the files. When developers create a new
   version of a program, they usually release a new
   \textbf{RPM} package.  Be aware that these files may not
   be usable for other \textbf{Linux} distributions.

   For system administrators, \textbf{RPM} makes software
   packages easy to manage. It is easy to determine which
   package a particular file comes from, which version of
   the package is installed, and whether it was installed
   correctly. It is also easy to remove complete packages
   to free up disk space. \textbf{RPM} also distinguishes
   documentation files from the rest of a package, allowing
   you to choose whether to install documentation on a
   system.

   \textbf{RPM} makes the software developer's job
   easier. Often, developers must change the code to get it
   to compile and execute correctly on another operating
   system. \textbf{RPM} allows builders to keep the changes
   necessary for building on \textbf{Linux} separate from
   the original source. This capability facilitates
   incorporating new versions of the code, because
   build-related changes are all in one place. It also
   facilitates building versions of \textbf{Linux} for
   different architectures.

   \begin{info}[Installation from the Network]

      Unless given a specific URL to draw from, \textbf{rpm}
      does not retrieve packages over the network; it
      installs only from the local machine using absolute or
      relative paths.

      However, one can also install directly from remote
      locations using protocols such as \textbf{HTTP,} or
      even the deprecated \textbf{FTP}.
   \end{info}

}

\section{Package File Names}
\begin{frame}
   {Package File Names}

   \begin{itemize}
      \item Standard binary \textbf{RPM} package naming format:
      \begin{kcode}
<name>-<version>-<release>.<distro>.<architecture>.rpm
sed-4.5-2.el8.x86_64.rpm
      \end{kcode}

      \item Standard source \textbf{RPM} package naming format:
      \begin{kcode}
<name>-<version>-<release>.<distro>.src.rpm
sed-4.5-2.el8.src.rpm
      \end{kcode}

   \end{itemize}

\end{frame}

\cprotect\note {

   \textbf{RPM} package file names are based on fields that
   represent specific information, as documented in the
   \textbf{RPM} standard (\url{http://www.rpm.org/})

   Note that the \texttt{distro} field often actually
   specifies the repository that the package came from, as
   a given installation may use a number of different
   package repositories as we shall discuss when we discuss
   \textbf{dnf}, \textbf{yum} and \textbf{zypper} which work
   at a level above \textbf{RPM}.

}

\section{RPM Database and Helper Programs}
\begin{frame}
   {RPM Database and Helper Programs}

   \begin{itemize}
      \item \textbf{RPM} database located in
      \filelink{/var/lib/rpm}
      \item Database files stored as \textbf{Berkeley DB} hash
      files
      \item Other helper programs in this directory
      \item Database can be rebuilt with:
      \begin{cmd}
$ sudo rpm --rebuilddb
      \end{cmd}
   \end{itemize}

\end{frame}

\cprotect\note{

   \filelink{/var/lib/rpm} is the default system directory
   which holds \textbf{RPM} database files in the form of
   \textbf{Berkeley DB} hash files.  The database files
   should not be manually modified; updates should be done
   only through use of the \textbf{rpm} program.

   An alternative database directory can be specified with
   the \verb?--dbpath? option to the \textbf{rpm}
   program. One might do this, for example, to examine an
   \textbf{RPM} database copied from another system.

   You can use the \verb?--rebuilddb? option to rebuild
   the database indices from the installed package headers;
   this is more of a repair, and not a rebuild from
   scratch.

   Helper programs and scripts used by \textbf{RPM} reside
   in \filelink{/usr/lib/rpm}.  There are quite a few; for
   example on an \textbf{RHEL 8} system:
   \begin{cmd}
 $ ls /usr/lib/rpm | wc -l
   \end{cmd}
   \begin{response}
  74
   \end{response}
   where \textbf{wc} is reporting the number of lines of
   output.

   You can create an \texttt{rpmrc} file to specify default
   settings for \textbf{rpm}. By default, \textbf{rpm}
   looks for:
   \begin{enumerate}
      \item \filelink{/usr/lib/rpm/rpmrc}
      \item \filelink{/etc/rpmrc}
      \item \filelink{\textasciitilde/.rpmrc}
   \end{enumerate}
   in the above order.  Note all these files are read;
   \textbf{rpm} does not stop as soon as it finds that one
   exists.

   An alternative \texttt{rpmrc} file can be specified
   using the \verb?--rcfile? option.

}
\section{Queries}
\begin{frame}
   {Queries}

   \begin{itemize}
      \item All \textbf{rpm} queries include the \verb?-q?
      option
      \item The \verb?-q? option can be combined with
      numerous other query options:
      \begin{itemize}
         \item[] \verb?-f?: allows you to determine
         which package a file came from
         \item[] \verb?-l?: lists the contents of a
         specific package
         \item[] \verb?-a?: all the packages
         installed on the system
         \item[] \verb?-i?: information about the
         package
         \item[] \verb?-p?: run the query against a
         package file instead of the package database
      \end{itemize}
   \end{itemize}

\end{frame}

\cprotect\note{

   \begin{table}[H]
      \caption{\textbf{rpm} Query Command Examples}
      \vspace{-15pt}
   \end{table}

   \small{\begin{tcolorbox}[tabularx={p{0.65\textwidth}|X}]

         Which version of a package is installed?
         &
         \verb?rpm -q bash?
         \\ \hline

         Which package did this file come from?
         &
         \verb?rpm -qf /bin/bash?
         \\ \hline

         What files were installed by this package?
         &
         \verb?rpm -ql bash?
         \\ \hline

         Show information about this package.
         &
         \verb?rpm -qi bash?
         \\ \hline

         Show information about this package from the package
         file, not the package data base.
         &
         \verb?rpm -qip foo-1.0.0.1.noarch.rpm?
         \\ \hline

         List all installed packages on this system.
         &
         \verb?rpm -qa?
      \end{tcolorbox}}

   A couple of other useful parameters are
   \texttt{--requires} and \texttt{--whatprovides}.

   The \verb?--requires? option will return a list of
   prerequisites for a package, while the
   \verb?--whatprovides? option will show what
   installed package provides a particular requisite
   package.

   \begin{cmd}
$ rpm -q  --requires bash     
$ rpm -qp --requires foo-1.0.0-1.noarch.rpm
$ rpm -q  --whatprovides libc.so.6
   \end{cmd}

}

\section{Verifying Packages}
\begin{frame}
   {Verifying Packages}

   \begin{itemize}
      \item The \texttt{rpm -V} command is used to verify
      packages
      \item No output when everything is OK
      \begin{itemize}
         \item \texttt{S}: filesize differs
         \item \texttt{M}: mode differs (permissions
         and file type)
         \item \texttt{5}: MD5 sum differs
         \item \texttt{D}: device major/minor number
         mismatch
         \item \texttt{L}: readLink path mismatch
         \item \texttt{U}: user ownership differs
         \item \texttt{G}: group ownership differs
         \item \texttt{T}: mTime differs
      \end{itemize}
      \item
      To check all packages:
      \begin{cmd}
$ sudo rpm -Va
      \end{cmd}
   \end{itemize}




\end{frame}

\cprotect\note{

   The \texttt{-V} option to \textbf{rpm} allows you to
   verify whether the files from a particular package are
   consistent with the system's RPM database.  Use
   \texttt{rpm -Va} to verify all packages on the system.

   In the output (you only see output if there is a
   problem) each of the characters denotes the result of
   a comparison of attribute(s) of the file to the value
   of those attribute(s) recorded in the database.  A
   single "." (period) means the test passed, while a
   single "?" (question mark) indicates the test could
   not be performed (e.g. file permissions prevent
   reading). Otherwise, the
   character denotes the failure of the corresponding
   \verb?--verify? test.

   No output when everything is OK.

   \begin{cmd}
$ rpm -V bash
   \end{cmd}

   Output indicating that a file's size, checksum, and
   modification time have changed.

   \begin{cmd}
$ rpm -V logrotate
   \end{cmd}
   \begin{response}
S.5....T.  c /etc/logrotate.conf
   \end{response}

   Output indicating that a file is missing.
   \begin{cmd}
$ sudo mv /sbin/logrotate /sbin/logrotate_KEEP
$ rpm -V logrotate
   \end{cmd}
   \begin{response}
S.5....T.  c /etc/logrotate.conf
missing     /usr/sbin/logrotate
   \end{response}
}

\section{Installing and Removing Packages}
\begin{frame}
   {Installing Packages}

   \begin{itemize}
      \item RPM performs a number of tasks when installing a
      package
      \begin{itemize}
         \item Dependency checks
         \item Conflict checks
         \item Commands required before installation
         \item Handles configuration files with intelligent care
         \item Unpacks files from package and installs them with
         correct attributes
         \item Commands required after installation
         \item Updates system \textbf{RPM} database
      \end{itemize}
      \item \texttt{rpm -i} to install a package
      \begin{cmd}
$ sudo rpm -ivh bash-4.4.19-12.el8_0.x86_64
      \end{cmd}
      where the \verb?-i? is for install, \verb?-v? is for
      verbose, and \verb?-h? means print hash marks to show
      progress
   \end{itemize}

\end{frame}

\cprotect\note{

   Dependency checks are necessary because some packages
   will not operate properly unless some other package is
   also installed.

   Conflicts include attempts to install an
   already-installed package, or to install an older version
   over a newer version.

   The person who builds a package can specify that certain
   tasks be performed before or after the install.

   When installing a configuration file, if the file exists
   and has been changed since the previous version of the
   package was installed, \textbf{RPM} saves the old
   version with the suffix \texttt{.rpmsave}.  This allows
   you to integrate the changes you have made to the old
   configuration file into the new version of the file.
   This feature depends on properly created RPM packages.

   In addition to installing files in the right place, RPM
   also sets attributes such as permissions, ownership, and
   modification (build) time.

   Every time \textbf{RPM} installs a package, it updates
   information in the system database. It uses this
   information when checking for conflicts.  }



\begin{frame}
   {Uninstalling Packages}

   \begin{itemize}
      \item Successful uninstall normally produces no output

      \begin{cmd}
$ sudo rpm -e system-config-lvm
      \end{cmd}
      \begin{response}
package system-config-lvm is not installed
      \end{response}

      \item Error due to dependencies

      \begin{cmd}
$ sudo rpm --test -e xz
     \end{cmd}

      \begin{responsevar}{\footnotesize}
error: Failed dependencies:
	xz is needed by (installed) pcp-5.1.1-4.el8_3.x86_64
	xz is needed by (installed) sos-3.9.1-6.el8.noarch
	xz is needed by (installed) gettext-devel-0.19.8.1-17.el8.x86_64
	xz is needed by (installed) libreport-2.9.5-15.el8.x86_64
	xz is needed by (installed) dracut-049-95.git20200804.el8_3.4.x86_64
	xz is needed by (installed) libvirt-daemon-driver-qemu-6.0.0-28.module+el8.3.0+7827+5e65edd7.x86_64
	xz is needed by (installed) rpm-build-4.14.3-4.el8.x86_64
	xz is needed by (installed) libguestfs-1:1.40.2-25.module+el8.3.0+7421+642fe24f.x86_64
	xz is needed by (installed) sysstat-11.7.3-5.el8.x86_64
	/usr/bin/xz is needed by (installed) file-roller-3.28.1-3.el8.x86_64
      \end{responsevar}
   \end{itemize}


\end{frame}

\cprotect\note{

   The \texttt{-e} option causes rpm to uninstall (erase) a
   package. Normally, \texttt{rpm -e} fails with an error
   message if the package you are attempting to uninstall
   is required by other packages on the system.

   You can use the \verb?--test? option along with
   \texttt{-e} to determine whether the uninstall would
   succeed or fail, without actually doing the
   uninstall. If the operation would be successful,
   \texttt{rpm} prints no output. Add the \texttt{-vv}
   option to get more information.

   Remember the package argument for the erase is the
   package name, not the \textbf{rpm} file name.

   \textbf{IMPORTANT NOTE:} Never remove (erase/uninstall)
   the \textbf{rpm} package itself.  The only way to fix
   this problem is to re-install the OS, or with a rescue
   environment.
   \begin{figure}[H]
      \includegraphics[width=6in]{IMAGES/rpme}
      \caption{Uninstalling RPM Packages}
   \end{figure}

   Note the example in the screenshot has somewhat different
   dependencies as it was done on an \textbf{openSUSE}
   system; the one on the slide was on a \textbf{RHEL}
   system.

}
\section{Updating, Upgrading and Freshening RPM Packages}
\begin{frame}
   {Updating Packages}

   \begin{itemize}
      \item Updating replaces original package, if
      installed
      \begin{cmd}
$ rpm -Uvh bash-4.4.19-12.el8.x86_64.rpm
         \end{cmd}
      \item Installs package if not currently installed
      \item Cannot install two packages containing the same
      files.
      \item Can downgrade using \verb?--oldpackage? option
   \end{itemize}


\end{frame}

\cprotect\note{

   When upgrading, the already installed package is removed
   after the newer version is installed.  The one exception
   is the configuration files from the original
   installation which are kept with a \texttt{.rpmsave}
   extension.

   If you use the \texttt{-U} option and the package is not
   already installed, it is simply installed and there is
   no error.

   The \texttt{-i} option is not designed for upgrades;
   attempting to install a new \textbf{RPM} package over an
   older one fails with error messages because it tries to
   overwrite existing system files.

   However different versions of the same package may be
   installed if each version of the package does not
   contain the same files: kernel packages and library
   packages from other architectures are typically the only
   packages that would be commonly installed multiple
   times.

   If you want to downgrade with \texttt{rpm -U} (that is,
   to replace the current version with an earlier version),
   you must add the \verb?--oldpackage? option to the
   command line.

}

\begin{frame}
   {Freshening Packages}

   \begin{itemize}
      \item To \textbf{freshen} all packages in
      the current directory:
      \begin{cmd}
$ sudo rpm -Fvh *.rpm
      \end{cmd}
      \begin{itemize}
         \item
         If  an older version of a package is installed, it
         will be upgraded to the newer version in the directory.
         \item
         If the version on the system is the same as the one in
         the directory, nothing happens.
         \item
         If there is no version of a package installed, the package
         in the directory is ignored.
      \end{itemize}
      \item
      Freshening can be useful for applying a lot of patches
      (i.e., upgraded packages) at once.
   \end{itemize}

\end{frame}

\cprotect\note{

   Freshening is similar to upgrading with one
   exception.  When you are upgrading and the package
   does not already exist, then it is loaded.  When
   you are freshening, if the package is not already
   loaded then it is simply ignored.  Both upgrading
   and freshening will install a new package if the
   original package is already loaded.

   The \texttt{-F} option is useful when you have
   downloaded several new patches and want to upgrade
   the packages that are already installed, but not
   install any new ones.

}

\section{Upgrading the Linux Kernel}
\begin{frame}
   {Upgrading the Linux Kernel}

   \begin{itemize}
      \item Always install a new kernel (do not upgrade)

      On a \textbf{Red Hat}-based system:
      \begin{cmd}
$ sudo rpm -ivh kernel-{version}.{arch}.rpm
      \end{cmd}
      \item Can revert to old kernel if there is problem
      \item Can remove old kernel after new one is tested, but
      it is always a good idea to keep at least one older
      kernel that is known to work
   \end{itemize}

\end{frame}

\cprotect\note{

   When you install a new kernel on your system, it
   requires a reboot (one of the few updates that do) to
   take effect.  You should not do an upgrade (\texttt{-U})
   of a kernel: an upgrade would remove the old currently
   running kernel.

   This in and of itself will not stop the system, but if
   after a reboot you have any problems, you will no longer
   be able to reboot into the old kernel since it has been
   removed from the system. However, if you install
   (\texttt{-i}), both kernels coexist and you can choose to
   boot into either one; i.e., you can revert back to the
   old one if need be.

   When you do this the \textbf{GRUB} configuration file
   will automatically be updated to include the new
   version; it will be the default choice at boot unless
   you reconfigure the system to do something else.

   Once the new kernel version has been tested, you may
   remove the old version if you wish, though this is not
   necessary.  Unless you are short on space, it is
   recommended that you keep one or more older kernels
   available.

}

\section{rpm2archive and rpm2cpio}

\begin{frame}
   {Using rpm2archive and rpm2cpio}

   \begin{itemize}
      \item Convert an RPM package file to an archive:

      \begin{cmd}
$ rpm2archive bash-XXXX.rpm 
      \end{cmd}
      creates \file{bash-XXXX.rpm.tgz}.

      \item
      Extract in one step:
      \begin{cmd}
$ cat bash-XXXX.rpm | rpm2archive - | tar -xvz
      \end{cmd}

      \item Convert an RPM package file to a \texttt{cpio}
      archive:
      \begin{cmd}
$ rpm2cpio bash-XXXX.rpm > bash.cpio
      \end{cmd}
      \item Extract one or more files:
      \begin{cmd}
$ rpm2cpio bash-XXXX.rpm | cpio -ivd bin/bash
$ rpm2cpio logrotate-XXXX.rpm | cpio --extract --make-directories
      \end{cmd}

      \item
      List files in a package;
      \begin{cmd}
$ rpm -qilp bash-XXXX.rpm
      \end{cmd}

   \end{itemize}

\end{frame}

\cprotect\note{

   \textbf{rpm2archive} is used to convert RPM package files
   to \textbf{tar} archives. If \verb?-? is given as an
   argument, input and output will be on \verb?stdin? and
   \verb?stdout?.

   It is more direct and efficient than the older
   \textbf{rpm2cpio} utility, which can be used to convert
   package files to \textbf{cpio} archives, or to extract
   files from the package file. When doing so, all files are
   extracted relative to the current directory. So if the
   user is in the \file{/home/student} directory and
   extracts the \file{bin/bash} file as in the example
   above, it will be stored in
   \filelink{/home/student/bin/bash}.

   If all you want to is list the files in a package, the
   easiest method is to use the \textbf{rpm} command itself:
   \begin{cmd}
$ rpm -qilp package.rpm
   \end{cmd}

}




