1
0
Fork 0
mirror of git://slackware.nl/current.git synced 2025-01-30 08:38:10 +01:00

Mon Jan 27 20:11:37 UTC 2025

a/etc-15.1-x86_64-13.txz:  Rebuilt.
  Added pcscd user (257) and pcscd group (257).
a/pkgtools-15.1-noarch-24.txz:  Rebuilt.
  setup.services: add support for enabling/disabling rc.pcscd.
a/sysvinit-scripts-15.1-noarch-26.txz:  Rebuilt.
  rc.M: start rc.pcscd.
  rc.6, rc.K: stop rc.pcscd.
d/meson-1.7.0-x86_64-1.txz:  Upgraded.
l/ccid-1.6.1-x86_64-1.txz:  Added.
  Thanks to LukenShiro.
l/fmt-11.1.3-x86_64-1.txz:  Upgraded.
l/pcsc-lite-2.3.1-x86_64-1.txz:  Added.
  Thanks to LukenShiro, Matteo Bernardini, euzao, and USUARIONUEVO.
l/qt5-5.15.16_20250122_d76aaaf8-x86_64-1.txz:  Upgraded.
n/gnupg2-2.4.7-x86_64-3.txz:  Rebuilt.
  Rebuilt using --disable-ccid-driver. Thanks to gbschenkel.
This commit is contained in:
Patrick J Volkerding 2025-01-27 20:11:37 +00:00 committed by Eric Hameleers
parent 43685d0a3f
commit 9a09b24826
287 changed files with 1753 additions and 82102 deletions

View file

@ -11,9 +11,35 @@
<description>Tracking Slackware development in git.</description>
<language>en-us</language>
<id xmlns="http://www.w3.org/2005/Atom">urn:uuid:c964f45e-6732-11e8-bbe5-107b4450212f</id>
<pubDate>Sun, 26 Jan 2025 21:35:58 GMT</pubDate>
<lastBuildDate>Sun, 26 Jan 2025 21:59:41 GMT</lastBuildDate>
<pubDate>Mon, 27 Jan 2025 20:11:37 GMT</pubDate>
<lastBuildDate>Mon, 27 Jan 2025 21:29:17 GMT</lastBuildDate>
<generator>maintain_current_git.sh v 1.17</generator>
<item>
<title>Mon, 27 Jan 2025 20:11:37 GMT</title>
<pubDate>Mon, 27 Jan 2025 20:11:37 GMT</pubDate>
<link>https://git.slackware.nl/current/tag/?h=20250127201137</link>
<guid isPermaLink="false">20250127201137</guid>
<description>
<![CDATA[<pre>
a/etc-15.1-x86_64-13.txz: Rebuilt.
Added pcscd user (257) and pcscd group (257).
a/pkgtools-15.1-noarch-24.txz: Rebuilt.
setup.services: add support for enabling/disabling rc.pcscd.
a/sysvinit-scripts-15.1-noarch-26.txz: Rebuilt.
rc.M: start rc.pcscd.
rc.6, rc.K: stop rc.pcscd.
d/meson-1.7.0-x86_64-1.txz: Upgraded.
l/ccid-1.6.1-x86_64-1.txz: Added.
Thanks to LukenShiro.
l/fmt-11.1.3-x86_64-1.txz: Upgraded.
l/pcsc-lite-2.3.1-x86_64-1.txz: Added.
Thanks to LukenShiro, Matteo Bernardini, euzao, and USUARIONUEVO.
l/qt5-5.15.16_20250122_d76aaaf8-x86_64-1.txz: Upgraded.
n/gnupg2-2.4.7-x86_64-3.txz: Rebuilt.
Rebuilt using --disable-ccid-driver. Thanks to gbschenkel.
</pre>]]>
</description>
</item>
<item>
<title>Sun, 26 Jan 2025 21:35:58 GMT</title>
<pubDate>Sun, 26 Jan 2025 21:35:58 GMT</pubDate>

View file

@ -1,3 +1,21 @@
Mon Jan 27 20:11:37 UTC 2025
a/etc-15.1-x86_64-13.txz: Rebuilt.
Added pcscd user (257) and pcscd group (257).
a/pkgtools-15.1-noarch-24.txz: Rebuilt.
setup.services: add support for enabling/disabling rc.pcscd.
a/sysvinit-scripts-15.1-noarch-26.txz: Rebuilt.
rc.M: start rc.pcscd.
rc.6, rc.K: stop rc.pcscd.
d/meson-1.7.0-x86_64-1.txz: Upgraded.
l/ccid-1.6.1-x86_64-1.txz: Added.
Thanks to LukenShiro.
l/fmt-11.1.3-x86_64-1.txz: Upgraded.
l/pcsc-lite-2.3.1-x86_64-1.txz: Added.
Thanks to LukenShiro, Matteo Bernardini, euzao, and USUARIONUEVO.
l/qt5-5.15.16_20250122_d76aaaf8-x86_64-1.txz: Upgraded.
n/gnupg2-2.4.7-x86_64-3.txz: Rebuilt.
Rebuilt using --disable-ccid-driver. Thanks to gbschenkel.
+--------------------------+
Sun Jan 26 21:35:58 UTC 2025
a/libcgroup-3.1.0-x86_64-1.txz: Upgraded.
Thanks to 0XBF for the many upgrade hints.

File diff suppressed because it is too large Load diff

View file

@ -1022,4 +1022,3 @@ gzip ./source/x/ibus/emoji-test.txt
gzip ./source/x/xcm/xcm.udev.rules.diff
gzip ./source/x/libva/doinst.sh
gzip ./testing/source/linux-6.13.x/patches-revert-i686/0001-x86-ioremap-Fix-page-aligned-size-calculation-in-__i.patch
bzip2 ./source/a/libcgroup/libcgroup-3.1.0/samples/config/large_cgconfig.conf

View file

@ -54,6 +54,7 @@ you are done." 22 74 10 \
"cairo" "Vector graphics library used by GTK+" "on" \
"cairomm" "Vector graphics library used by GTKmm" "on" \
"cairomm1" "C++ wrapper for cairo, ABI 1.16" "on" \
"ccid" "PC/SC driver for USB CCID smart card readers" "on" \
"cfitsio" "FITS file subroutine library" "on" \
"chmlib" "Library for accessing CHM files" "on" \
"clucene" "Text-Search Engine" "on" \
@ -333,6 +334,7 @@ you are done." 22 74 10 \
"pcaudiolib" "Portable C Audio Library" "on" \
"pcre" "Perl-compatible regular expression library" "on" \
"pcre2" "Perl compatible regular expression library v2" "on" \
"pcsc-lite" "PC/SC API smartcard library/daemon" "on" \
"phonon" "multimedia framework for KDE" "on" \
"phonon-backend-gstreamer" "gstreamer backend for phonon" "on" \
"pilot-link" "PalmOS communication library" "on" \
@ -467,7 +469,7 @@ if [ $? = 1 -o $? = 255 ]; then
rm -f $TMP/SeTpkgs
> $TMP/SeTnewtag
for pkg in \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 ccid cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 pcsc-lite phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
; do
echo "$pkg: SKP" >> $TMP/SeTnewtag
done
@ -475,7 +477,7 @@ GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SD
fi
cat /dev/null > $TMP/SeTnewtag
for PACKAGE in \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 ccid cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 pcsc-lite phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
; do
if grep "\(^\| \)$PACKAGE\( \|$\)" $TMP/SeTpkgs 1> /dev/null 2> /dev/null ; then
echo "$PACKAGE: ADD" >> $TMP/SeTnewtag

View file

@ -54,6 +54,7 @@ you are done." 22 74 10 \
"cairo" "Vector graphics library used by GTK+" "on" \
"cairomm" "Vector graphics library used by GTKmm" "on" \
"cairomm1" "C++ wrapper for cairo, ABI 1.16" "on" \
"ccid" "PC/SC driver for USB CCID smart card readers" "on" \
"cfitsio" "FITS file subroutine library" "on" \
"chmlib" "Library for accessing CHM files" "on" \
"clucene" "Text-Search Engine" "on" \
@ -333,6 +334,7 @@ you are done." 22 74 10 \
"pcaudiolib" "Portable C Audio Library" "on" \
"pcre" "Perl-compatible regular expression library" "on" \
"pcre2" "Perl compatible regular expression library v2" "on" \
"pcsc-lite" "PC/SC API smartcard library/daemon" "on" \
"phonon" "multimedia framework for KDE" "on" \
"phonon-backend-gstreamer" "gstreamer backend for phonon" "on" \
"pilot-link" "PalmOS communication library" "on" \
@ -467,7 +469,7 @@ if [ $? = 1 -o $? = 255 ]; then
rm -f $TMP/SeTpkgs
> $TMP/SeTnewtag
for pkg in \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 ccid cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 pcsc-lite phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
; do
echo "$pkg: SKP" >> $TMP/SeTnewtag
done
@ -475,7 +477,7 @@ GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SD
fi
cat /dev/null > $TMP/SeTnewtag
for PACKAGE in \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
GConf Imath LibRaw Mako PyQt-builder PyQt5 PyQt5_sip QScintilla SDL2 SDL2_gfx SDL2_image SDL2_mixer SDL2_net SDL2_ttf a52dec aalib abseil-cpp accountsservice adwaita-icon-theme adwaita-icon-theme-legacy alsa-lib alsa-oss alsa-plugins aom appstream-glib apr apr-util argon2 aspell aspell-en at-spi2-core atkmm atkmm2 audiofile avahi babl boost brotli cairo cairomm cairomm1 ccid cfitsio chmlib clucene colord cryfs cryptopp cxxopts dav1d db48 dbus-glib dbus-python dconf dconf-editor desktop-file-utils djvulibre dotconf duktape dvdauthor ebook-tools editorconfig-core-c eigen3 elfutils enchant esound espeak-ng exiv2 expat farstream ffmpeg fftw fluidsynth fmt freecell-solver freetype frei0r-plugins fribidi fuse fuse3 gc gcr gcr4 gd gdbm gdk-pixbuf2 gdk-pixbuf2-xlib gegl gexiv2 gi-docgen giflib gjs glade glib glib-networking glib2 glibc glibc-i18n glibc-profile glibmm glibmm2 gmime gmm gmp gnome-keyring gnome-themes-extra gnu-efi gobject-introspection grantlee graphene graphite2 gsettings-desktop-schemas gsl gspell gst-plugins-bad-free gst-plugins-base gst-plugins-good gst-plugins-libav gstreamer gtk+ gtk+2 gtk+3 gtk4 gtkmm2 gtkmm3 gtkmm4 gtksourceview3 gtkspell gvfs harfbuzz hicolor-icon-theme hunspell hyphen icon-naming-utils icu4c id3lib imagemagick immer isl iso-codes jansson jasper jemalloc jmtpfs json-c json-glib judy kdsoap keybinder3 keyutils lager lame lcms lcms2 lensfun libaio libao libappindicator libarchive libass libasyncns libatasmart libbluray libburn libcaca libcanberra libcap libcap-ng libcddb libcdio libcdio-paranoia libclc libcue libcupsfilters libdaemon libdbusmenu libdbusmenu-qt libdeflate libdiscid libdmtx libdvdnav libdvdread libedit libev libevent libexif libfakekey libffi libglade libgnome-keyring libgnt libgphoto2 libgpod libgsf libgtop libgusb libhandy libical libid3tag libidl libidn libidn2 libieee1284 libimobiledevice libimobiledevice-glue libindicator libiodbc libjpeg-turbo libkarma libmad libmcrypt libmng libmpc libmtp libnice libnih libnjb libnl libnl3 libnotify libnsl libnss_nis libnvme libodfgen libogg liboggz liboil libopusenc libpaper libpcap libplacebo libplist libpng libppd libproxy libpsl libptytty libqalculate libraw1394 librevenge librsvg libsamplerate libsass libseccomp libsecret libsigc++ libsigc++3 libsigsegv libsndfile libsodium libsoup libsoup3 libspectre libssh libssh2 libtasn1 libtheora libtiff libtraceevent libtracefs libunibreak libunistring libunwind liburing libusb libusb-compat libusbmuxd libuv libvisio libvisual libvisual-plugins libvncserver libvorbis libvpx libwebp libwmf libwnck libwnck3 libwpd libwpg libxkbcommon libxklavier libxml2 libxslt libyaml libzip lmdb loudmouth luajit-lgi lz4 lzo media-player-info mhash mlt mm movit mozilla-nss mozjs128 mpfr mujs ncurses neon netpbm newt nodejs ocl-icd oniguruma openal-soft opencv openexr openjpeg opus opusfile orc pango pangomm pangomm2 parted pcaudiolib pcre pcre2 pcsc-lite phonon phonon-backend-gstreamer pilot-link pipewire polkit polkit-gnome polkit-qt-1 poppler poppler-data popt protobuf pulseaudio pycairo pycups pycurl pygobject pygobject3 pygtk pyparsing python-Jinja2 python-MarkupSafe python-PyYAML python-alabaster python-appdirs python-babel python-build python-calver python-certifi python-cffi python-chardet python-charset-normalizer python-distro python-dnspython python-docutils python-doxypypy python-doxyqml python-editables python-flit-core python-future python-glad2 python-hatch-vcs python-hatchling python-html5lib python-idna python-imagesize python-importlib_metadata python-installer python-lxml python-markdown python-notify2 python-packaging python-pathspec python-pbr python-pillow python-pluggy python-ply python-psutil python-pycparser python-pygments python-pyproject-hooks python-pysol_cards python-random2 python-requests python-sane python-setuptools_scm python-six python-smartypants python-snowballstemmer python-sphinx python-sphinx_rtd_theme python-tomli-w python-trove-classifiers python-typogrify python-urllib3 python-versioneer python-webencodings python-wheel python-zipp python2-pycairo qrencode qt5 qt6 qtkeychain quazip readline rpcsvc-proto rttr rubygem-asciidoctor sbc sdl seatd serf sg3_utils shared-desktop-ontologies shared-mime-info sip slang slang1 sof-firmware sound-theme-freedesktop speech-dispatcher speex speexdsp spirv-llvm-translator startup-notification svgalib system-config-printer t1lib taglib talloc tango-icon-theme tango-icon-theme-extras tdb tevent tidy-html5 unicode-ucd utf8proc v4l-utils vid.stab vte wavpack wireplumber woff2 xapian-core xxHash zlib zstd zug zxing-cpp \
; do
if grep "\(^\| \)$PACKAGE\( \|$\)" $TMP/SeTpkgs 1> /dev/null 2> /dev/null ; then
echo "$PACKAGE: ADD" >> $TMP/SeTnewtag

View file

@ -39,6 +39,7 @@ brotli:REC
cairo:REC
cairomm:REC
cairomm1:REC
ccid:REC
cfitsio:REC
chmlib:REC
clucene:REC
@ -318,6 +319,7 @@ parted:ADD
pcaudiolib:REC
pcre:REC
pcre2:REC
pcsc-lite:REC
phonon:REC
phonon-backend-gstreamer:REC
pilot-link:REC

View file

@ -24,7 +24,7 @@ cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=etc
VERSION=15.1
BUILD=${BUILD:-12}
BUILD=${BUILD:-13}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then

View file

@ -60,6 +60,7 @@ users:x:100:
console:x:101:
avahi:x:214:
nut:x:218:
pcscd:x:257:
colord:x:303:
nm-openvpn:x:320:
ldap:x:330:

View file

@ -38,6 +38,7 @@ proftpd:x:97:97:User for ProFTPD:/:/bin/false
nobody:x:99:99:nobody:/:/bin/false
avahi:x:214:214:User for avahi:/dev/null:/bin/false
nut:x:218:218:User for NUT:/dev/null:/bin/false
pcscd:x:257:257:User for pcsc-lite:/var/run/pcscd:/bin/false
colord:x:303:303:User for colord:/var/lib/colord:/bin/false
nm-openvpn:x:320:320:User for NetworkManager-openvpn:/var/lib/openvpn/chroot:/bin/false
ldap:x:330:330:OpenLDAP server:/var/lib/openldap:/bin/false

View file

@ -38,6 +38,7 @@ proftpd:*:9797:0:::::
nobody:*:9797:0:::::
avahi:*:9797:0:::::
nut:*:9797:0:::::
pcscd:*:9797:0:::::
colord:*:9797:0:::::
nm-openvpn:*:9797:0:::::
ldap:*:9797:0:::::

View file

@ -1,19 +0,0 @@
# There is no Kernel tree available, run without it.
--no-tree
# Ignore the SPDX License tag, that's supposed to be the first line in
# Linux Kernel sources.
--ignore SPDX_LICENSE_TAG
# We do not follow the negative error numbering, so ignore it.
--ignore USE_NEGATIVE_ERRNO
# Follow the 100-character limit.
--max-line-length=100
# Kernel specific kstr* functions recommendation doesn't apply to us.
--ignore SSCANF_TO_KSTRTO
# Ignore new typedefs introduction warnings for now. We need to revisit files
# introducing it and remove it.
--ignore NEW_TYPEDEFS

View file

@ -1,2 +0,0 @@
[flake8]
max-line-length = 100

View file

@ -1,184 +0,0 @@
How to Contribute to the libcgroup Project
===============================================================================
https://github.com/libcgroup/libcgroup
This document outlines the steps to help you contribute to the libcgroup project.
As with the libcgroup code itself, the process is a work in progress.
Improvements and suggestions are welcome and encouraged.
## Interacting with the Community
> "When you are kind to others, it not only changes you, it changes the
> world." - Harold Kushner
The libcgroup project strives to be an inclusive and welcoming place.
If you interact with the libcgroup project, we request that you treat others
with dignity and respect. Failure to do so will result in a warning. In
extreme cases, we reserve the right to block the individual from the project.
Examples of inappropriate behavior includes: profane, abusive, or prejudicial
language directed at another person, vandalism (e.g. GitHub issue/PR "litter"),
or spam.
## Test Your Code Using Existing Tests
The libcgroup project utilizes unit and functional tests. These tests must
successfully pass prior to a commit being merged.
You can run both the unit and functional tests with the following command:
# make check
You can invoke only the unit tests with the following commands:
# cd tests/gunit
# make check
If there are unit test failures, running the unit tests outside of the
automake framework will provide more information.
# cd tests/gunit
# ./gtest
You can invoke only the functional tests with the following commands:
# cd tests/ftests
# make check
Note that the functional tests can be run within a container or directly on
your system. For the containerized tests, libcgroup utilizes LXC/LXD
containers. If your system or distro doesn't support LXC/LXD, you can
utilize the continuous integration infrastructure to test your changes. A
successful continuous integration run is required for each pull request.
Many tests can also be run outside of a container. Use caution with these
tests though, as they will modify your host's cgroup hierarchy. This could
significantly and negatively affect your system.
We encourage utilizing a VM for libcgroup development work. The continuous
integration suite utilizes the latest Ubuntu LTS.
To run the containerized tests only:
# cd tests/ftests
# ./ftests.sh
To run the non-containerized tests only:
# cd tests/ftests
# ./ftests-nocontainer.sh
After the run is complete, the ftests.sh.log and ftests-nocontainer.sh.log
contain the full debug log for each run.
## Add New Tests for New Functionality
The libcgroup project utilizes automated tests, code coverage, and continuous
integration to maintain a high level of code quality. Any pull requests that
add functionality or significantly change existing code should include
additional tests to verify the proper operation of the proposed changes. Note
that functional tests are preferred over unit tests.
The continuous integration tools run the automated tests and automatically
gather code coverage numbers. Pull requests that cause the code coverage
numbers to decrease are strongly discouraged.
## Explain Your Work
At the top of every patch you should include a description of the problem you
are trying to solve, how you solved it, and why you chose the solution you
implemented. If you are submitting a bug fix, it is also incredibly helpful
if you can describe/include a reproducer for the problem in the description as
well as instructions on how to test for the bug and verify that it has been
fixed.
## Sign Your Work
The sign-off is a simple line at the end of the patch description, which
certifies that you wrote it or otherwise have the right to pass it on as an
open-source patch. The "Developer's Certificate of Origin" pledge is taken
from the Linux Kernel and the rules are pretty simple:
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
... then you just add a line to the bottom of your patch description, with
your real name, saying:
Signed-off-by: Random J Developer <random@developer.example.org>
You can add this to your commit description in `git` with `git commit -s`
## Submitting Patches
libcgroup was initially hosted on Sourceforge and at that time only accepted
patches via the mailing list. In 2018, libcgroup was moved to github and now
accepts patches via email or github pull request. Over time the libcgroup
project will likely fully transition to gitub pull requests and issues.
### Post Your Patches Upstream
The sections below explain how to contribute via either method. Please read
each step and perform all steps that apply to your chosen contribution method.
### Submitting via Email
Depending on how you decided to work with the libcgroup code base and what
tools you are using there are different ways to generate your patch(es).
However, regardless of what tools you use, you should always generate your
patches using the "unified" diff/patch format and the patches should always
apply to the libcgroup source tree using the following command from the top
directory of the libcgroup sources:
# patch -p1 < changes.patch
If you are not using git, stacked git (stgit), or some other tool which can
generate patch files for you automatically, you may find the following command
helpful in generating patches, where "libcgroup.orig/" is the unmodified
source code directory and "libcgroup/" is the source code directory with your
changes:
# diff -purN libcgroup.orig/ libcgroup/
When in doubt please generate your patch and try applying it to an unmodified
copy of the libcgroup sources; if it fails for you, it will fail for the rest
of us.
Finally, you will need to email your patches to the mailing list so they can
be reviewed and potentially merged into the main libcgroup repository. When
sending patches to the mailing list it is important to send your email in text
form, no HTML mail please, and ensure that your email client does not mangle
your patches. It should be possible to save your raw email to disk and apply
it directly to the libcgroup source code; if that fails then you likely have
a problem with your email client. When in doubt try a test first by sending
yourself an email with your patch and attempting to apply the emailed patch to
the libcgrup repository; if it fails for you, it will fail for the rest of
us trying to test your patch and include it in the main libcgroup repository.
### Submitting via GitHub Pull Requests
See [this guide](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) if you've never done this before.

View file

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

View file

@ -1,237 +0,0 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006, 2007 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
6. Often, you can also type `make uninstall' to remove the installed
files again.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View file

@ -1,13 +0,0 @@
AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS= -I m4
DIST_SUBDIRS = dist doc include scripts src tests samples
SUBDIRS = $(DIST_SUBDIRS)
EXTRA_DIST = README_daemon libcgroup.doxyfile README_systemd CONTRIBUTING.md
AM_DISTCHECK_CONFIGURE_FLAGS = --sysconfdir=/etc --localstatedir=/var \
--enable-opaque-hierarchy="name=systemd" \
--enable-python
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libcgroup.pc

View file

@ -1,183 +0,0 @@
Design
========
After cgroup system has taken shape, its time to have some basic tools
in user space which can enable a user to use the resource management
functionality effectively.
One of the needed functionality is rule based placement of a task. In general,
there can be either uid or gid or exec based rules. Admin/root will
control/enforce uid/gid based rules and exec based rules can be defined by
user in a config file residing in user's home dir and fully controlled by user.
uid/gid based rules will be defined in /etc/cgrules.conf config file and
this file will be managed by root.
Basic idea is that to begin with provide facility to implement rules
based on uid and gid. So a hierarchy might look like as follows.
/mnt/cgroup
| |
gid1 gid2
| |
uid1 uid2
| |
proj1 proj2
Admin will write rules to control the resources among users. Then users
can manage their own cgroup at their own (proj1 and proj2) and control
the resources as they want.
Following are the few methods using which tasks can be placed in right
cgroups.
- Use pam_cgroup PAM plugin which will make sure users are placed in right
cgroup at login time and any tasks launch after login, will continue to run
in user's cgroup.
- Use command line tool "cgexec" to launch the task in right cgroup.
- Modify the program and use libcgroup provided APIs for placing a task
in right cgroup before doing exec().
- Use "cgclassify" tool to classify a already running task.
- May be, a user space daemon can also be implemented which will listen to
kernel events and place the task in right group based on the rules.
This method involves few concerns.
- Reliability of netlink socket. Messages can be dropped.
- Change the netlink with a cgroup controller which exports the
events.
- Delay incurred since the event took place and task was actually placed
in right cgroup.
- daemon will interfere with container's tasks which is not desired.
HOWTO
=====
Section 1:
----------
To use "cgexec" to place the task in right cgroup.
- make cgexec
- Run a task using cgexec. Following is the cgexec syntax.
cgexec [-g <list of controllers>:<relative path to cgroup>] command [arguments]
Note: Cgroup controllers and path are optional. If user does not know the
right cgroup, cgexec will automatically place the task in right
cgroup based on /etc/cgrules.conf
Example:
cgexec -g *:test1 ls
cgexec -g cpu,memory:test1 ls -l
cgexec -g cpu,memory:test1 -g swap:test2 ls -l
Section 2
---------
To use "cgclassify" to place task in right cgroup.
- make cgclassify
- Pick a task's pid to be classified, and run
cgclassify <list of pids>
Example:
--------
cgclassify 2140 4325
Note: After classification check out whether tasks 2140 and 4325
are in the right cgroup or not (Based on rules in /etc/cgrules.conf)
Section 3:
----------
To use a pam plugin which will automatically place the task in right
cgroup upon login.
- Build pam_cgroup.so
make pam_cgroup.so
- Copy pam_cgroup.so to /lib/security/
- Edit /etc/pam.d/su to make use of pam_cgroup.so session module upon
execution of su.
example:
Add following line at the end of /etc/pam.d/su file
session optional pam_cgroup.so
- Now launch a shell for a user "xyz" using su and the resulting shell
should be running in the cgroup designated for the user as specified
by cgrules.conf
ex. "su test1"
Try similar things with other services like sshd.
Note: pam_cgroup.so moves the service providing process in the right cgroup
and not the process which will be launched later. Due to parent child
relationship, yet to be forked/execed process will launch in right
group.
Ex. Lets say user root does "su test1". In this case process "su" is the
one providing service (launching a shell) for user "test1". pam_cgroup.so
will move process "su" to the user "test1"'s cgroup (Decided by the uid
and gid of "test1"). Now once su forks/execs a shell for user test1,
final shell is effectively running in the cgroup it should have been
running based on /etc/cgrules.conf for user test1.
Section 4:
----------
To use cgrulesengd which will move a task to right cgroup based on
rules in /etc/cgrules.conf do following.
- build and install latest libcgroup.so
- build cgrulesengd
make cgrulesengd
- specify some uid/gid based rules in /etc/cgrules.conf
- Mount some controllers and create an hierarchy of cgroups (matching
your rules).
- Run cgrulesengd.
- ./cgrulesengd
- Launch some task or login as a user to the system. Daemon should automatically
place the task in right cgroup.
FAQ
===
Q. Why admin should not control "exec" based rules.
A. Unix file system provides access control only based on uid/gid. So
even if admin starts putting tasks based on uid/gid, it can't enforce
it. For example, consider following scenario.
Lets say an admin creates following cgroup hierarchy.
/container
| |
database browser
| | | |
user1 user2 user1 user2
Now admin wants to run all the database jobs under /container/database/
and all the firefox jobs under /container/browser/. Based on which user
launched it, jobs should go in either user1 or user2 dir.
Now assume that database subdir has to more cpu resources as compared to
browser subdir. Then a user, say user2, can always move his browser job
also to /container/database/user2 dir to get more cpu resources and
admin will not be able to control that.
[Note: user2 will control what tasks can be added in /container/database/user2
and will control what further subdirs can be created under user2 dir. Root
should not restrict the control to root only for practical purposes. Its
something like that till /container/database, admin controls the resources
and below that how resources are further subdivided among various projects
should be controlled by respective user].
In the light of above, it seems to make more sense that admin should enforce
rules only based on uid and gid. Probably later we can have a per user exec
based rules config file (~/.cgrules.conf), which can be parsed by cgrulesengd
and then jobs launched by user will be placed in right cgroup based on
combination of rules in /etc/cgrules.conf and ~/cgrules.conf.

View file

@ -1,6 +0,0 @@
[![Build Status](https://github.com/libcgroup/libcgroup/workflows/Continuous%20Integration/badge.svg?branch=main)](https://github.com/libcgroup/libcgroup/actions)
[![Coverage Status](https://coveralls.io/repos/github/libcgroup/libcgroup/badge.png)](https://coveralls.io/github/libcgroup/libcgroup)
[![Doxygen Documentation](https://img.shields.io/badge/Documentation-Doxygen-green.svg)](https://libcgroup.github.io/libcgroup/)
[![CodeQL](https://github.com/libcgroup/libcgroup/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)](https://github.com/libcgroup/libcgroup/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)
The entire libcgroup README is available [here](README).

View file

@ -1,182 +0,0 @@
DESCRIPTION
===========
The CGroup Rules Engine Daemon is a tool that will automatically place tasks
into the correct cgroup based on UID/GID events from the kernel. It will not
automatically classify tasks that are already running, but it will classify
any new tasks, and any tasks which change their UID/GID. Note that we use
the euid and egid, not the ruid and rgid.
Unlike other tools, cgrulesengd caches the rules configuration in a data
structure (it's actually just a FIFO linked list) so that it doesn't need to
parse the configuration file more than once. This should be much faster than
parsing the rules for each UID/GID event. Eventually, this caching logic
should be part of libcgroup, so that any other program can take advantage of it
(and so that all programs are using the same table). The configuration can
be reloaded without stopping the daemon (more information below).
WHY A DAEMON?
=============
A daemon is easy to use, and allows an administrator to ensure that all tasks
are classified into the correct cgroups without constantly monitoring the
system. The daemon is transparent to the users, and does not require any
modifications to existing userspace programs. Finally, the daemon can be
started and stopped at any time, including at boot time with other services.
Thus, sytem administrators can decide not to use the daemon if they choose.
Most importantly, some programs create new users and/or run scripts,
threads, etc. as those users using suexec(). This call does not go through
PAM, so these scripts would continue running in the same cgroup as the parent
program. This behavior is likely not ideal, and the daemon would solve this
problem.
Apache does this. Apache creates a user called 'apache' and uses setuid() to
launch tasks as that user. This does not go through PAM, so without a daemon,
these tasks would continue to run in the 'root' cgroup rather than in the
'apache' or 'webserver' cgroup. The daemon fixes this problem by catching the
setuid() call and moving the tasks into the correct cgroup.
We would ask Apache to modify their software to interface with libcgroup, but
this solution is less than optimal because a lot of userspace software would
have to be changed, and some authors might intentionally not interact with
libcgroup, which could create an exploit. The daemon is a simple, transparent
solution.
USING THE DAEMON
================
The daemon can be used as a service with the cgred script, which is shipped
as scripts/init.d/cgred. This script should be installed as /etc/init.d/cgred
and used like any other service. To start the daemon,
/etc/init.d/cgred start
To stop it,
/etc/init.d/cgred stop
The restart (stop,start), condrestart (same as restart, but only if the daemon
was already started), and status (print whether the daemon is started or
stopped) commands are also supported. An additional command, "reload", allows
you to reload the configuration file without stopping the daemon.
/etc/init.d/cgred reload
The cgred script automatically loads configuration from /etc/sysconfig/cgred.conf,
which is shipped as samples/cgred.conf. See that file for more information.
If you choose not to run the daemon as a service, the following options are
currently supported:
--nodaemon Do not run as a daemon
--nolog Write log output to stdout instead of a log file
--config [FILE] Read rules configuration from FILE instead of
/etc/cgrules.conf
You can ask the daemon to reload the rules configuration by sending it SIGUSR2.
The easiest way to do this is with the 'kill' command:
kill -s SIGUSR2 [PID]
You can ask the daemon to reload the templates configuration by sending it
SIGUSR1. The easiest way to do this is with the 'kill' command:
kill -s SIGUSR1 [PID]
TESTING
=======
The program setuid (found in tests/setuid.c) can help you test the daemon. By
default, this program attempts to change its UID to root and then idles until
you kill it. You can change the default behavior to use a different UID, or
you can uncomment the second block of code to instead attempt to change the
GID.
In order to make sure that everything works, I used the following rules:
sjo cpu default
cgtest cpu cgtest
% memory default
@cgroup cpu,memory cgtest
peter cpu test1
% memory test2
@root * default
* * default
The users 'sjo' and 'cgtest' were normal users. 'peter' is not a user on the
system. The group 'cgroup' is a group containing sjo,root,cgtest as members,
and the group 'root' contains only root. The cgroups 'default' and 'cgtest'
exist, while 'test1' and 'test2' do not. Currently, the daemon does not check
for the existance of 'test1', though this would be easier to do once the
parsing and caching logic is moved into libcgroup.
I ran the following tests, all of which were successful:
- set UID to sjo (should move cpu controller into default)
- set UID to root (should move cpu,memory controllers into cgtest)
- set UID to cgtest (should move cpu controller into cgtest, memory
controller into default)
- set GID to root (should move all controllers into default)
- set GID to cgroup (should move cpu, memory into cgtest)
- set GID to users (should move all controllers into default)
The parsing logic will skip the 'peter' rule as well as its multi-line
components (in this case "% memory test2"), because the user does not exist.
This should work for group rules, too. Attempting to setuid() or setgid() to a
user/group that doesn't exist will just return an error and not generate a
kernel event of the PROC_EVENT_UID or PROC_EVENT_GID type, so the daemon won't
do anything for it.
CONCERNS/ISSUES
===============
- Netlink can be unreliable, and the daemon might miss an event if the buffer
is full. One possible solution is to have one or two files that the kernel
can queue UID/GID changes in, and have the daemon read those files whenever
they are updated. From testing, this does not actually appear to be a real
problem, but it could become one with faster machines.
- The daemon does not care for namespaces at all, which can cause conflicts
with containers. If a user places his tasks into exec-based cgroups (such
as 'network' and 'development'), the daemon will not realize this and will
simply place them into the user's cgroup (so, sjo/ instead of sjo/network/).
CHANGELOG
=========
V9:
- Updated documentation, because it was very old and incorrect.
- Reverted the changes to cgexec and cgclassify.
- New API function: cgroup_change_cgroup_uid_gid_flags().
- Deprecated cgroup_change_cgroup_uid_gid().
- Rewrote some of the rule matching and execution logic in api.c to be
faster, and easier to read.
- Changes all negative return values to positive values. As a side effect,
cgroup_parse_rules() now returns -1 when we get a match and we are using
non-cached rules.
- Changes CGROUP_FUSECACHE to CGFLAG_USECACHE.
- Flags are now enumerated (cgflags), instead of #defines.
V8:
- Moved the event-handling logic back into the daemon, where it should be.
- Changed cgroup_parse_rules() to work with cached rules or non-cached rules.
The other parsing function is no longer needed, and should be deprecated.
- Non-cached rules now work with the same structs as cached rules.
- Modified cgroup_change_cgroup_uid_gid() with a new 'flags' parameter.
Currently, the only flag is "CGROUP_FUSECACHE" to use the cached rules logic
(or not).
- Added cgroup_rules_loaded() boolean, to check whether the cached rules have
been loaded yet, and cgroup_init_rules_cache() to load them.
- Modified cgexec and cgclassify to work with the new
cgroup_change_cgroup_uid_gid().
V7:
- Moved parsing and caching logic into libcgroup.
- Added locking mechanisms around the list of rules.
- Cleaned up #includes in cgrulesegnd.[h,c].
- Added notification if netlink receive queue overflows.
- Added logic to catch SIGINT in addition to SIGTERM.
- New API functions:
- cgroup_free_rule(struct cgroup_rule*)
- cgroup_free_rule_list(struct cgroup_rule_list*)
- cgroup_parse_rules(void)
- cgroup_print_rules_config(FILE*)
- cgroup_reload_cached_rules(void)
- cgroup_change_cgroup_event(struct proc_event*, int, FILE*)
V6:
- Wrote new parsing logic, which is cleaner and simpler.
- Added cgred script to enable using the daemon as a service.
- Wrote caching logic to cache rules table.
- Added the ability to force a reload of the rules table with SIGUSR2 signal.
- Added two structures to libcgroup: cgre_rule and cgre_rules_list
- New API function: cgroup_reload_cached_rules, which reloads the rules table.
- Added logging capabilities (default log is /root/cgrulesengd.conf)
TODO
====
- Find a way to replace Netlink, or at least clean up that code.
- Find a solution to the namespace problem.

View file

@ -1,69 +0,0 @@
Integration with systemd
========================
systemd is a system and service manager for Linux, compatible with SysV
and LSB init scripts. systemd heavily uses control groups to manage and control
services.
Most of the libcgroup tools and APIs can be safely used on systems with systemd
without any problems. This document attempts to describe the configuration of
systemd and libcgroup so they can safely co-exist and mutually benefit each
other.
References
==========
[1] http://www.freedesktop.org/wiki/Software/systemd
Systemd home page.
[2] http://www.freedesktop.org/wiki/Software/systemd/PaxControlGroups
This is the most useful document describing systemd expectations on applications
(incl. libcgroup tools).
Compilation
===========
As stated in [2], libcgroup should not interact with the 'name=systemd'
hierarchy. Compile libcgroup with the --enable-opaque-hierarchy configure option
to do so:
./configure --enable-opaque-hierarchy=name=systemd
Consequently, the 'name=systemd' hierarchy will not be visible to libcgroup and
all of its tools. For example, the lscgroup command will not list systemd
cgroups.
Start-up and services
====================
Systemd automatically mounts all available controllers on system boot ('cpu' and
'cpuacct' together in one hierarchy by default) and can automatically put
service processes into control groups with configured parameters — by default,
each service is automatically put into the 'cpu,cpuacct:/system/$service_name'
control group. The System Administrator has full control of parameters in each
control group and of which controllers are used. Consult systemd
documentation, mainly systemd.conf(5) and systemd.exec(5) man pages, for
details.
In the vast majority of use cases, this behavior is sufficient and libcgroup
does not need to be used.
For specific use cases, e.g. when a different tree of control groups is needed,
libcgroup provides cgconfig service. This service can create arbitrary control
group hierarchies. In this case, follow these steps:
1. Set 'DefaultControllers=' in /etc/systemd/system.conf so that systemd does
not create control groups for services automatically.
2. Prepare /etc/cgconfig.conf and enable the cgconfig service. The service will
parse the /etc/cgconfig.conf file during machine boot and create all control
groups which are defined in it. The service automatically sets '+t' ("sticky")
bit on the tasks files as recommended in [2].
3. For each service that should start in a specific control group, add the
following lines into its unit file:
After=cgconfig.service
ControlGroup=<name of the control group(s)>
This ensures the service is started only after cgconfig creates the necessary
hierarchy for it. It also tells systemd which control group it should use to
start the service.

View file

@ -1,45 +0,0 @@
The libcgroup Security Vulnerability Handling Process
===============================================================================
https://github.com/libcgroup/libcgroup
This document describes the processes through which sensitive security relevant
bugs can be responsibly disclosed to the libcgroup project and how the project
maintainers should handle these reports. Just like the other libcgroup process
documents, this document should be treated as a guiding document and not a
hard, unyielding set of regulations; the bug reporters and project maintainers
are encouraged to work together to address the issues as best they can, in a
manner which works best for all parties involved.
### Reporting Problems
Problems with the libcgroup library that are not suitable for immediate public
disclosure should be emailed to the current libcgroup maintainers; see below.
We typically request at most a 90 day time period to address the issue before
it is made public, but we will make every effort to address the issue as
quickly as possible and shorten the disclosure window.
* Dhaval Giani, dhaval.giani@gmail.com
* Tom Hromatka, tom.hromatka@oracle.com
### Resolving Sensitive Security Issues
Upon disclosure of a bug, the maintainers should work together to investigate
the problem and decide on a solution. In order to prevent an early disclosure
of the problem, those working on the solution should do so privately and
outside of the traditional libcgroup development practices. One possible
solution to this is to leverage the GitHub "Security" functionality to create a
private development fork that can be shared among the maintainers, and
optionally the reporter. A placeholder GitHub issue may be created, but
details should remain extremely limited until such time as the problem has been
fixed and responsibly disclosed. If a CVE, or other tag, has been assigned to
the problem, the GitHub issue title should include the vulnerability tag once
the problem has been disclosed.
### Public Disclosure
Whenever possible, responsible reporting and patching practices should be
followed, including notification to the linux-distros and oss-security mailing
lists.
* https://oss-security.openwall.org/wiki/mailing-lists/distros
* https://oss-security.openwall.org/wiki/mailing-lists/oss-security

View file

@ -1,29 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-only
set -ex
if [ -f .git/hooks/pre-commit.sample ] && [ ! -f .git/hooks/pre-commit ] ; then
cp -p .git/hooks/pre-commit.sample .git/hooks/pre-commit && \
chmod +x .git/hooks/pre-commit && \
echo "Activated pre-commit hook."
fi
# update the git submodules - libcgroup-tests and googletest
git submodule update --init --recursive
# configure googletest
pushd googletest/googletest
git checkout release-1.8.0
cmake -DBUILD_SHARED_LIBS=ON .
make
popd
test -d m4 || mkdir m4
autoreconf -fi
rm -fr autom4te.cache
CFLAGS="$CFLAGS -g -O0" ./configure --sysconfdir=/etc --localstatedir=/var \
--enable-opaque-hierarchy="name=systemd" --enable-systemd --enable-python
make clean

View file

@ -1,266 +0,0 @@
# -*- Autoconf -*-
# SPDX-License-Identifier: LGPL-2.1-only
# Process this file with autoconf to produce a configure script.
#
# Copyright International Business Machines Corp. 2008
#
# Authors: Balbir Singh <balbir@linux.vnet.ibm.com>
#
AC_PREREQ([2.69])
# In following section update all occurences of version, including soname
AC_INIT([libcgroup],[3.1.0])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIRS([m4])
AM_INIT_AUTOMAKE([foreign dist-bzip2 subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# set library version, soname is libcgroup.so.MAJOR
AC_SUBST(LIBRARY_VERSION_MAJOR, 3)
AC_SUBST(LIBRARY_VERSION_MINOR, 1)
AC_SUBST(LIBRARY_VERSION_RELEASE, 0)
# we do not want static libraries
#AC_DISABLE_STATIC
AM_PROG_AR
LT_INIT
AC_CONFIG_SRCDIR([src])
AC_CONFIG_HEADER([config.h])
# Process command line options
AC_ARG_ENABLE([tools],
[AS_HELP_STRING([--enable-tools],[compile libcgroup tools [default=yes]])],
[
if test "x$enableval" = xno; then
with_tools=false
else
with_tools=true
fi
],
[with_tools=true])
AM_CONDITIONAL([WITH_TOOLS], [test x$with_tools = xtrue])
AC_ARG_ENABLE([pam],
[AS_HELP_STRING([--enable-pam],[compile libcgroup PAM module [default=yes]])],
[
if test "x$enableval" = xno; then
with_pam=false
else
with_pam=true
fi
],
[with_pam=true])
AM_CONDITIONAL([WITH_PAM], [test x$with_pam = xtrue])
AC_ARG_ENABLE([daemon],
[AS_HELP_STRING([--enable-daemon],[compile libcgroup daemon [default=yes]])],
[
if test "x$enableval" = xno; then
with_daemon=false
else
with_daemon=true
fi
],
[with_daemon=true])
AM_CONDITIONAL([WITH_DAEMON], [test x$with_daemon = xtrue])
AC_ARG_ENABLE([python],
[AS_HELP_STRING([--enable-python],
[build the python bindings, requires cython])])
AS_IF([test "$enable_python" = yes], [
# cython version check
AS_IF([test "$CYTHON_VER_MAJ" -eq 0 -a "$CYTHON_VER_MIN" -lt 29], [
AC_MSG_ERROR([python bindings require cython 0.29 or higher])
])
AM_PATH_PYTHON([3])
])
AM_CONDITIONAL([ENABLE_PYTHON], [test "$enable_python" = yes])
AC_DEFINE_UNQUOTED([ENABLE_PYTHON],
[$(test "$enable_python" = yes && echo 1 || echo 0)],
[Python bindings build flag.])
AC_ARG_ENABLE([systemd],
[AS_HELP_STRING([--enable-systemd],[enable systemd support [default=yes]])],
[
if test "x$enableval" = xno; then
with_systemd=false
else
with_systemd=true
fi
],
[with_systemd=true])
AM_CONDITIONAL([WITH_SYSTEMD], [test x$with_systemd = xtrue])
AC_ARG_ENABLE([initscript-install],
[AS_HELP_STRING([--enable-initscript-install],[install init scripts [default=no]])],
[
if test "x$enableval" = xno; then
with_initscript_install=false
else
with_initscript_install=true
fi
],
[with_initscript_install=false])
AM_CONDITIONAL([WITH_INITSCRIPT_INSTALL], [test x$with_initscript_install = xtrue])
socket_path="/var/run/cgred.socket"
AC_ARG_ENABLE([cgred-socket],
[AS_HELP_STRING([--enable-cgred-socket=PATH],[specify location of cgrulesengd communication socket
(default=/var/run/cgred.socket)])],
[
if test "x$enableval" = xno -o "x$enableval" = xyes; then
AC_MSG_ERROR([Provide valid path with --enable-cgred-socket option.])
else
socket_path="$enableval"
fi
], [])
AC_DEFINE_UNQUOTED([CGRULE_CGRED_SOCKET_PATH],"$socket_path", [Cgrulesengd socket path])
pam_module_dir="$libdir/security"
AC_ARG_ENABLE([pam-module-dir],
[AS_HELP_STRING([--enable-pam-module-dir=PATH],[specify location of libcgroup PAM module
(default=$libdir/security)])],
[
if test "x$enableval" = xno -o "x$enableval" = xyes; then
AC_MSG_ERROR([Provide valid path with --enable-pam-module-dir option.])
else
pam_module_dir="$enableval"
fi
], [])
AC_SUBST([pamlibdir],"$pam_module_dir")
AC_ARG_ENABLE([opaque-hierarchy],
[AS_HELP_STRING([--enable-opaque-hierarchy=NAME],[specify name of a hierarchy which libcgroup should ignore, e.g. name=systemd
(default=none)])],
[
if test "x$enableval" = xno -o "x$enableval" = xyes; then
AC_MSG_ERROR([Provide name of a hierarchy.])
else
AC_DEFINE_UNQUOTED([OPAQUE_HIERARCHY], "$enableval",
[Define to ignore specific hierarchy.])
fi
], [])
AC_ARG_ENABLE([tests],
[AS_HELP_STRING([--enable-tests],[compile libcgroup tests [default=yes]])],
[
if test "x$enableval" = xno; then
with_tests=false
else
with_tests=true
fi
],
[with_tests=true])
AM_CONDITIONAL([WITH_TESTS], [test x$with_tests = xtrue])
AC_ARG_ENABLE([samples],
[AS_HELP_STRING([--enable-samples],[compile libcgroup samples C programs [default=no]])],
[
if test "x$enableval" = xno; then
with_samples=false
else
with_samples=true
fi
],
[with_samples=false])
AM_CONDITIONAL([WITH_SAMPLES], [test x$with_samples = xtrue])
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
AC_PROG_YACC
if test "$YACC" = yacc; then
AC_CHECK_PROG([REALLY_YACC], [yacc], [yacc])
if test "$REALLY_YACC" = ""; then
AC_MSG_ERROR([This program cannot be built unless a version of yacc is installed.])
fi
fi
AM_PROG_LEX
if test "$LEX" != flex; then
AC_MSG_ERROR([This program cannot be built unless flex is installed.])
fi
LT_INIT
# Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS([limits.h mntent.h stdlib.h string.h sys/mount.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_CONST
AC_TYPE_UID_T
AC_C_INLINE
AC_TYPE_INT64_T
AC_TYPE_PID_T
# Checks for library functions.
AC_FUNC_CHOWN
AC_FUNC_GETMNTENT
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_FUNC_STAT
AC_CHECK_FUNCS([getmntent hasmntopt memset mkdir rmdir strdup])
orig_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -D_GNU_SOURCE"
AC_FUNC_STRERROR_R
CFLAGS="$orig_CFLAGS"
AC_SEARCH_LIBS(
[fts_open],
[fts],
[],
[AC_MSG_ERROR([Unable to find the fts_open() function])])
if test x$with_pam = xtrue; then
AC_CHECK_LIB(
[pam],
[pam_syslog],
[
dnl Override the default behavior of AC_CHECK_LIB,
dnl we don't want -lpam in LIBS.
:
],
[AC_MSG_ERROR([Cannot compile PAM module without libpam!])])
AC_CHECK_HEADERS(
[security/pam_modules.h security/pam_modutil.h security/pam_ext.h],
[],
[AC_MSG_ERROR([Cannot compile PAM module without necessary
header files!])])
fi
AX_CODE_COVERAGE
AC_CONFIG_FILES([Makefile
src/Makefile
src/daemon/Makefile
src/tools/Makefile
src/pam/Makefile
src/python/Makefile
scripts/Makefile
scripts/init.d/cgconfig
scripts/init.d/cgred
tests/Makefile
tests/ftests/Makefile
tests/gunit/Makefile
samples/Makefile
samples/c/Makefile
samples/cmdline/Makefile
samples/config/Makefile
samples/python/Makefile
include/Makefile
include/libcgroup/init.h
doc/Makefile
doc/man/Makefile
dist/Makefile
libcgroup.pc])
AC_CONFIG_FILES([dist/libcgroup.spec:dist/libcgroup.spec.in])
CFLAGS="$CFLAGS -Wall"
AC_OUTPUT

View file

@ -1 +0,0 @@
EXTRA_DIST = libcgroup.spec

View file

@ -1,16 +0,0 @@
[Unit]
Description=Control Group configuration service
# The service should be able to start as soon as possible,
# before any 'normal' services:
DefaultDependencies=no
Conflicts=shutdown.target
Before=basic.target shutdown.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/cgconfigparser -l /etc/cgconfig.conf -s 1664
[Install]
WantedBy=sysinit.target

View file

@ -1,168 +0,0 @@
%define soversion @LIBRARY_VERSION_MAJOR@.@LIBRARY_VERSION_MINOR@.@LIBRARY_VERSION_RELEASE@
%define soversion_major @LIBRARY_VERSION_MAJOR@
Name: libcgroup
Summary: Tools and libraries to control and monitor control groups
Group: System Environment/Libraries
Version: @PACKAGE_VERSION@
Release: 1%{?dist}
License: LGPLv2+
URL: http://libcg.sourceforge.net/
Source0: http://downloads.sourceforge.net/libcg/%{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: pam-devel
BuildRequires: byacc
BuildRequires: flex
BuildRequires: coreutils
Requires(pre): shadow-utils
Requires(post): chkconfig, /sbin/service
Requires(preun): /sbin/chkconfig
%description
Control groups infrastructure. The tools and library help manipulate, control,
administrate and monitor control groups and the associated controllers.
%package pam
Summary: A Pluggable Authentication Module for libcgroup
Group: System Environment/Base
Requires: libcgroup = %{version}-%{release}
%description pam
Linux-PAM module, which allows administrators to classify the user's login
processes to pre-configured control group.
%package devel
Summary: Development libraries to develop applications that utilize control groups
Group: Development/Libraries
Requires: libcgroup = %{version}-%{release}
%description devel
It provides API to create/delete and modify cgroup nodes. It will also in the
future allow creation of persistent configuration for control groups and
provide scripts to manage that configuration.
%prep
%setup -q
%build
%configure --bindir=/bin --sbindir=/sbin --libdir=%{_libdir} --enable-initscript-install --enable-pam-module-dir=/%{_lib}/security
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
# install config files
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig
cp samples/config/cgred.conf $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/cgred.conf
cp samples/config/cgconfig.sysconfig $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/cgconfig
cp samples/config/cgconfig.conf $RPM_BUILD_ROOT/%{_sysconfdir}/cgconfig.conf
cp samples/config/cgrules.conf $RPM_BUILD_ROOT/%{_sysconfdir}/cgrules.conf
cp samples/config/cgsnapshot_blacklist.conf $RPM_BUILD_ROOT/%{_sysconfdir}/cgsnapshot_blacklist.conf
# sanitize pam module, we need only pam_cgroup.so
mv -f $RPM_BUILD_ROOT/%{_lib}/security/pam_cgroup.so.*.*.* $RPM_BUILD_ROOT/%{_lib}/security/pam_cgroup.so
rm -f $RPM_BUILD_ROOT/%{_lib}/security/pam_cgroup.la $RPM_BUILD_ROOT/%{_lib}/security/pam_cgroup.so.*
# move the libraries to /
mkdir -p $RPM_BUILD_ROOT/%{_lib}
mv -f $RPM_BUILD_ROOT/%{_libdir}/libcgroup.so.%{soversion} $RPM_BUILD_ROOT/%{_lib}
rm -f $RPM_BUILD_ROOT/%{_libdir}/libcgroup.so.%{soversion_major}
ln -sf libcgroup.so.%{soversion} $RPM_BUILD_ROOT/%{_lib}/libcgroup.so.%{soversion_major}
ln -sf ../../%{_lib}/libcgroup.so.%{soversion} $RPM_BUILD_ROOT/%{_libdir}/libcgroup.so
rm -f $RPM_BUILD_ROOT/%{_libdir}/*.la
%clean
rm -rf $RPM_BUILD_ROOT
%pre
getent group cgred >/dev/null || groupadd cgred
%post
/sbin/ldconfig
/sbin/chkconfig --add cgred
/sbin/chkconfig --add cgconfig
%preun
if [ $1 = 0 ]; then
/sbin/service cgred stop > /dev/null 2>&1 || :
/sbin/service cgconfig stop > /dev/null 2>&1 || :
/sbin/chkconfig --del cgconfig
/sbin/chkconfig --del cgred
fi
%postun -p /sbin/ldconfig
%files
%defattr(-,root,root,-)
%config(noreplace) %{_sysconfdir}/sysconfig/cgred.conf
%config(noreplace) %{_sysconfdir}/sysconfig/cgconfig
%config(noreplace) %{_sysconfdir}/cgconfig.conf
%config(noreplace) %{_sysconfdir}/cgrules.conf
%config(noreplace) %{_sysconfdir}/cgsnapshot_blacklist.conf
/%{_lib}/libcgroup.so.*
%attr(2755, root, cgred) /bin/cgexec
/bin/cgclassify
/bin/cgcreate
/bin/cgget
/bin/cgset
/bin/cgdelete
/bin/lscgroup
/bin/lssubsys
/sbin/cgconfigparser
/sbin/cgrulesengd
/bin/cgsnapshot
%attr(0644, root, root) %{_mandir}/man1/*
%attr(0644, root, root) %{_mandir}/man5/*
%attr(0644, root, root) %{_mandir}/man8/*
%attr(0755,root,root) %{_initrddir}/cgconfig
%attr(0755,root,root) %{_initrddir}/cgred
%doc COPYING INSTALL README_daemon
%files pam
%defattr(-,root,root,-)
%attr(0755,root,root) /%{_lib}/security/pam_cgroup.so
%doc COPYING INSTALL
%files devel
%defattr(-,root,root,-)
%{_includedir}/libcgroup.h
%{_includedir}/libcgroup/*.h
%{_libdir}/libcgroup.*
/%{_libdir}/pkgconfig/libcgroup.pc
%doc COPYING INSTALL
%changelog
* Tue Nov 2 2010 Jan Safranek <jsafrane@redhat.com> 0.37.rc1-1
- Add cgsnapshot
* Thu Feb 18 2010 Dhaval Giani <dhaval.giani@gmail.com> 0.36.rc1-1
- Add pkgconfig file
* Tue Jan 19 2010 Balbir Singh <balbir@linux.vnet.ibm.com> 0.35.1
- Integrate Jan's fixes for distributing cgget and initscripts
* Thu Oct 22 2009 Jan Safranek <jsafrane@redhat.com> 0.34-1
- Update to latest upstream
- Split PAM module to separate subpackage
* Tue Feb 24 2009 Balbir Singh <balbir@linux.vnet.ibm.com> 0.33-1
- Update to 0.33, spec file changes to add Makefiles and pam_cgroup module
* Fri Oct 10 2008 Dhaval Giani <dhaval@linux.vnet.ibm.com> 0.32-1
- Update to latest upstream
* Thu Sep 11 2008 Dhaval Giani <dhaval@linux-vnet.ibm.com> 0.31-1
- Update to latest upstream
* Sat Aug 2 2008 Dhaval Giani <dhaval@linux.vnet.ibm.com> 0.1c-3
- Change release to fix broken upgrade path
* Wed Jun 11 2008 Dhaval Giani <dhaval@linux.vnet.ibm.com> 0.1c-1
- Update to latest upstream version
* Tue Jun 3 2008 Balbir Singh <balbir@linux.vnet.ibm.com> 0.1b-3
- Add post and postun. Also fix Requires for devel to depend on base n-v-r
* Sat May 31 2008 Balbir Singh <balbir@linux.vnet.ibm.com> 0.1b-2
- Fix makeinstall, Source0 and URL (review comments from Tom)
* Mon May 26 2008 Balbir Singh <balbir@linux.vnet.ibm.com> 0.1b-1
- Add a generatable spec file
* Tue May 20 2008 Balbir Singh <balbir@linux.vnet.ibm.com> 0.1-1
- Get the spec file to work
* Tue May 20 2008 Dhaval Giani <dhaval@linux.vnet.ibm.com> 0.01-1
- The first version of libcg

File diff suppressed because it is too large Load diff

View file

@ -1,3 +0,0 @@
DIST_SUBDIRS = man
SUBDIRS = $(DIST_SUBDIRS)

View file

@ -1,90 +0,0 @@
The libcgroup Release Process
===============================================================================
https://github.com/libcgroup/libcgroup
This is the process that should be followed when creating a new libcgroup
release.
#### 1. Verify that all issues assigned to the release milestone have been resolved
* https://github.com/libcgroup/libcgroup/milestones
#### 2. Verify that the Github Actions are all passing
#### 3. Verify that the bundled test suite runs without error
# ./bootstrap.sh
# make check
#### 4. Verify that the packaging is correct
# make distcheck
#### 5. Verify that there are no outstanding defects from Coverity
# ./bootstrap.sh
# export PATH=$PATH:/path/to/cov-build
# cov-build --dir cov-int make
# # verify the build succeeded. Examine $? and cov-int/build-log.txt
# tar czvf libcgroup-main@<current hash>.tar.gz cov-int
# Upload the tar file to Coverity
#### 6. Perform any distribution test builds
* Oracle Linux
* Fedora Rawhide
* Red Hat Enterprise Linux
* etc.
#### 7. If any problems were found up to this point that resulted in code changes, restart the process
#### 8. If this is a new major/minor release, create new 'release-X.Y' branch
# git branch "release-X.Y"
#### 9. Update the version number in configure.ac AC_INIT(...) macro
#### 10. Tag the release in the local repository with a signed tag
# git tag -s -m "version X.Y.Z" vX.Y.Z
#### 11. Build final release tarball
# make clean
# ./bootstrap.sh
# make dist-gzip
#### 12. Verify the release tarball in a separate directory
<unpack the release tarball in a temporary directory>
# ./configure --sysconfdir=/etc --localstatedir=/var \
--enable-opaque-hierarchy="name=systemd" --enable-python
# make check
#### 13. Generate a checksum for the release tarball
# sha256sum <tarball> > libcgroup-X.Y.Z.tar.gz.SHA256SUM
#### 14. GPG sign the release tarball and checksum using the maintainer's key
# gpg --armor --detach-sign libcgroup-X.Y.Z.tar.gz
# gpg --clearsign libcgroup-X.Y.Z.tar.gz.SHA256SUM
#### 15. Push the release tag to the main GitHub repository
# git push <repo> vX.Y.Z
#### 16. Create a new GitHub release using the associated tag and upload the following files
* libcgroup-X.Y.Z.tar.gz
* libcgroup-X.Y.Z.tar.gz.asc
* libcgroup-X.Y.Z.tar.gz.SHA256SUM
* libcgroup-X.Y.Z.tar.gz.SHA256SUM.asc
#### 17. Update the GitHub release notes for older releases which are now unsupported
The following Markdown text is suggested at the top of the release note, see old GitHub releases for examples.
```
***This release is no longer supported upstream, please use a more recent release***
```

View file

@ -1,7 +0,0 @@
man_MANS = cgclassify.1 cgconfig.conf.5 cgconfigparser.8 cgexec.1 \
cgred.conf.5 cgrules.conf.5 cgrulesengd.8 cgcreate.1 cgset.1 \
cgget.1 cgdelete.1 lssubsys.1 lscgroup.1 cgsnapshot.1 \
cgxget.1 cgxset.1
EXTRA_DIST = $(man_MANS)

View file

@ -1,93 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Varekova <varekova@redhat.com>.
.TH CGCLASSIFY 1 2009-03-15 "Linux" "libcgroup Manual"
.SH NAME
cgclassify \- move running task(s) to given cgroups
.SH SYNOPSIS
\fBcgclassify\fR [\fB-b\fR] [\fB-g\fR <\fIcontrollers>:<path\fR>] [--sticky | --cancel-sticky] <\fIpidlist\fR>
.SH DESCRIPTION
this command moves processes defined by the list
of processes
(\fBpidlist\fR)
to the given control groups.
The pids in the pidlist are separated by spaces
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B -g <controllers>:<path>
defines the control groups where the task will be moved.
\fBcontrollers\fR is a list of controllers and
\fBpath\fR is the relative path to control groups
in the given controllers list.
This flag can be used multiple times to
define multiple pairs of lists of controllers
and relative paths.
Instead of the list of all mounted controllers,
the wildcard \fB*\fR can be used.
If this option is not used then
\fBcgclassify\fR will automatically move the task to a
control group based on \fB/etc/cgrules.conf\fR.
.TP
.B -r
Replaces systemd scope's idle process with the
\fBfirst process\fR of the list of process (\fBpidlist\fR).
.TP
.B --sticky
If this option is used, the daemon of service cgred (cgrulesengd process)
does not change both the specified \fBpidlist\fR and their children tasks.
Without this option, the daemon does not change the specified \fBpidlist\fR
but it automatically changes their child tasks to the right cgroup based on
\fB/etc/cgrules.conf\fR.
.TP
.B --cancel-sticky
If this option is used, the daemon of service cgred (cgrulesengd process)
can automatically change both the specified \fBpidlist\fR and their child
tasks to the right cgroup based on \fB/etc/cgrules.conf\fR.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH FILES
.TP
.B /etc/cgrules.conf
default libcgroup configuration file
.TP
.B /etc/cgrules.d
default libcgroup configuration files directory
.SH EXAMPLES
.TP
.B cgclassify -g cpu:student 1234
moves process with pid number 1234 to control group student in cpu hierarchy.
.TP
.B cgclassify 1234
moves process with pid number 1234 to control groups based on
\fB/etc/cgrules.conf\fR configuration file.
.TP
.B cgclassify --sticky -g cpu:/student 1234
moves process with pid number 1234 to control group student in cpu hierarchy.
The daemon of service cgred does not change cgroups of pid 1234 and its children
(based on \fB/etc/cgrules.conf\fR).
.SH SEE ALSO
cgrules.conf (5), cgexec (1)

View file

@ -1,824 +0,0 @@
.TH CGCONFIG.CONF 5
.\"***********************************
.SH NAME
cgconfig.conf \- libcgroup configuration file
.\"***********************************
.SH DESCRIPTION
.B "cgconfig.conf"
is a configuration file used by
.B libcgroup
to define control groups, their parameters and their mount points.
The file consists of
.I mount
,
.I group
and
.I default
sections. These sections can be in arbitrary order and all of them are
optional. Any line starting with '#' is considered a comment line and
is ignored.
.LP
.I mount
section has this form:
.RS
.nf
.ft B
.sp
mount {
.RS
.ft B
<controller> = <path>;
.I "..."
.RE
.ft B
}
.ft R
.fi
.RE
.TP
.B controller
Name of the kernel subsystem. The list of subsystems supported by the kernel
can be found in
.I /proc/cgroups
file. Named hierarchy can be specified as controller
\fB"name=<somename>"\fR. Do not forget to use double quotes around
this controller name (see examples below). Apart from named hierarchy,
additional mount options may be specified by putting the controller and
the options in quotes. Options supported are \fB nosuid, noexec\fR and\fB nodev\fR.
.B Libcgroup
merges all subsystems mounted to the same directory (see
Example 1) and the directory is mounted only once.
.TP
.B path
The directory path where the group hierarchy associated to a given
controller shall be mounted. The directory is created
automatically on cgconfig service startup if it does not exist and
is deleted on service shutdown.
.LP
If no
.I mount
section is specified, no controllers are mounted.
.I group
section has this form:
.RS
.nf
.ft B
.sp
group <name> {
.RS
.ft B
[permissions]
<controller> {
.RS
.ft B
<param name> = <param value>;
.I "..."
.RE
.ft B
}
.I "..."
.RE
.ft B
}
.ft R
.fi
.RE
.TP
.B name
Name of the control group. It can contain only characters, which are
allowed for directory names.
The groups form a tree, i.e. a control group can contain zero or more
subgroups. Subgroups can be specified using '/' delimiter.
The root control group is always created automatically in all hierarchies
and it is the base of the group hierarchy. It can be explicitly specified in
.B cgconfig.conf
by using '.' as group name. This can be used e.g. to set its permissions,
as shown in Example 6.
When the parent control group of a subgroup is not specified
it is created automatically.
.TP
.B permissions
Permissions of the given control group on mounted filesystem.
.I root
has always permission to do anything with the control group.
Permissions have the following syntax:
.RS 17
.ft B
.nf
perm {
.RS
.ft B
task {
.RS
.ft B
uid = <task user>;
gid = <task group>;
fperm = <file permissions>
.RE
}
admin {
.RS
uid = <admin name>;
gid = <admin group>;
dperm = <directory permissions>
fperm = <file permissions>
.RE
}
.RE
}
.fi
.RE
.ft R
.RS
.TP 17
.B "task user/group"
Name of the user and the group, which own the
.I tasks
file of the control group. Given fperm then specify the file permissions.
Please note that the given value is not used as was specified. Instead,
current file owner permissions are used as a "umask" for group and others
permissions. For example if fperm = 777 then both group and others will get
the same permissions as the file owner.
.TP 17
.B "admin user/group"
Name of the user and the group which own the rest of control group's
files. Given fperm and dperm control file and directory permissions.
Again, the given value is masked by the file/directory owner permissions.
.LP
Permissions are only apply to the enclosing control group and are not
inherited by subgroups. If there is no
.B perm
section in the control group definition,
.I root:root
is the owner of all files and default file permissions are preserved if
fperm resp. dperm are not specified.
.RE
.TP
.B controller
Name of the kernel subsystem.
The section can be
empty, default kernel parameters will be used in this case. By
specifying
.B controller
the control group and all its parents are controlled by the specific
subsystem. One control group can be controlled by multiple subsystems,
even if the subsystems are mounted on different directories. Each
control group must be controlled by at least one subsystem, so that
.B libcgroup
knows in which hierarchies the control group should be created.
The parameters of the given controller can be modified in the following
section enclosed in brackets.
.RS
.TP
.B param name
Name of the file to set. Each controller can have zero or more
parameters.
.TP
.B param value
Value which should be written to the file when the control group is
created. If it is enclosed in double quotes `"', it can contain spaces
and other special characters.
.RE
If no
.I group
section is specified, no groups are created.
.I default
section has this form:
.RS
.nf
.ft B
.sp
default {
.RS
.ft B
perm {
.RS
.ft B
task {
.RS
.ft B
uid = <task user>;
gid = <task group>;
fperm = <file permissions>
.RE
}
admin {
.RS
uid = <admin name>;
gid = <admin group>;
dperm = <directory permissions>
fperm = <file permissions>
.RE
}
.RE
}
.RE
}
.ft R
.fi
.RE
Content of the
.B perm
section has the same form as in
.I group
section. The permissions defined here specify owner and permissions of
groups and files of all groups, which do not have explicitly specified
their permissions in their
.I group
section.
.I template
section has the same structure as
.B group
section. Template name uses the same templates string as
.B cgrules.conf
destination tag (see (\fBcgrules.conf\fR (5)).
Template definition is used as a control group definition for rules in
\fBcgrules.conf\fR (5) with the same destination name.
Templates does not use
.B default
section settings.
.I /etc/cgconfig.d/
directory can be used for additional configuration files. cgrulesengd searches this directory for additional templates.
.\"********************************************"
.SH EXAMPLES
.LP
.SS Example 1
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpu;
.RE
}
.fi
.RE
creates the hierarchy controlled by two subsystems with no groups
inside. It corresponds to the following operations:
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu
.fi
.RE
.SS Example 2
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
"name=scheduler" = /mnt/cgroups/cpu;
"name=noctrl" = /mnt/cgroups/noctrl;
.RE
}
group daemons {
.RS
cpu {
.RS
cpu.shares = "1000";
.RE
}
.RE
}
group test {
.RS
"name=noctrl" {
}
.RE
}
.RE
.fi
creates two hierarchies. One hierarchy named \fBscheduler\fR controlled by cpu
subsystem, with group \fBdaemons\fR inside. Second hierarchy is named
\fBnoctrl\fR without any controller, with group \fBtest\fR. It corresponds to
following operations:
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mount -t cgroup -o cpu,name=scheduler cpu /mnt/cgroups/cpu
mount -t cgroup -o none,name=noctrl none /mnt/cgroups/noctrl
mkdir /mnt/cgroups/cpu/daemons
echo 1000 > /mnt/cgroups/cpu/daemons/www/cpu.shares
mkdir /mnt/cgroups/noctrl/tests
.fi
.RE
The
.I daemons
group is created automatically when its first subgroup is
created. All its parameters have the default value and only root can
access group's files.
.LP
Since both
.I cpuacct
and
.I cpu
subsystems are mounted to the same directory, all
groups are implicitly controlled also by
.I cpuacct
subsystem, even if there is no
.I cpuacct
section in any of the groups.
.RE
.SS Example 3
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpu;
.RE
}
group daemons/www {
.RS
perm {
.RS
task {
.RS
uid = root;
gid = webmaster;
fperm = 770;
.RE
}
admin {
.RS
uid = root;
gid = root;
dperm = 775;
fperm = 744;
.RE
}
.RE
}
cpu {
.RS
cpu.shares = "1000";
.RE
}
.RE
}
group daemons/ftp {
.RS
perm {
.RS
task {
.RS
uid = root;
gid = ftpmaster;
fperm = 774;
.RE
}
admin {
.RS
uid = root;
gid = root;
dperm = 755;
fperm = 700;
.RE
}
.RE
}
cpu {
.RS
cpu.shares = "500";
.RE
}
.RE
}
.RE
.fi
creates the hierarchy controlled by two subsystems with one group and
two subgroups inside, setting one parameter.
It corresponds to the following operations (except for file permissions
which are little bit trickier to emulate via chmod):
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu
mkdir /mnt/cgroups/cpu/daemons
mkdir /mnt/cgroups/cpu/daemons/www
chown root:root /mnt/cgroups/cpu/daemons/www/*
chown root:webmaster /mnt/cgroups/cpu/daemons/www/tasks
echo 1000 > /mnt/cgroups/cpu/daemons/www/cpu.shares
# + chmod the files so the result looks like:
# ls -la /mnt/cgroups/cpu/daemons/www/
# admin.dperm = 755:
# drwxr-xr-x. 2 root webmaster 0 Jun 16 11:51 .
#
# admin.fperm = 744:
# --w-------. 1 root webmaster 0 Jun 16 11:51 cgroup.event_control
# -r--r--r--. 1 root webmaster 0 Jun 16 11:51 cgroup.procs
# -r--r--r--. 1 root webmaster 0 Jun 16 11:51 cpuacct.stat
# -rw-r--r--. 1 root webmaster 0 Jun 16 11:51 cpuacct.usage
# -r--r--r--. 1 root webmaster 0 Jun 16 11:51 cpuacct.usage_percpu
# -rw-r--r--. 1 root webmaster 0 Jun 16 11:51 cpu.rt_period_us
# -rw-r--r--. 1 root webmaster 0 Jun 16 11:51 cpu.rt_runtime_us
# -rw-r--r--. 1 root webmaster 0 Jun 16 11:51 cpu.shares
# -rw-r--r--. 1 root webmaster 0 Jun 16 11:51 notify_on_release
#
# tasks.fperm = 770
# -rw-rw----. 1 root webmaster 0 Jun 16 11:51 tasks
mkdir /mnt/cgroups/cpu/daemons/ftp
chown root:root /mnt/cgroups/cpu/daemons/ftp/*
chown root:ftpmaster /mnt/cgroups/cpu/daemons/ftp/tasks
echo 500 > /mnt/cgroups/cpu/daemons/ftp/cpu.shares
# + chmod the files so the result looks like:
# ls -la /mnt/cgroups/cpu/daemons/ftp/
# admin.dperm = 755:
# drwxr-xr-x. 2 root ftpmaster 0 Jun 16 11:51 .
#
# admin.fperm = 700:
# --w-------. 1 root ftpmaster 0 Jun 16 11:51 cgroup.event_control
# -r--------. 1 root ftpmaster 0 Jun 16 11:51 cgroup.procs
# -r--------. 1 root ftpmaster 0 Jun 16 11:51 cpuacct.stat
# -rw-------. 1 root ftpmaster 0 Jun 16 11:51 cpuacct.usage
# -r--------. 1 root ftpmaster 0 Jun 16 11:51 cpuacct.usage_percpu
# -rw-------. 1 root ftpmaster 0 Jun 16 11:51 cpu.rt_period_us
# -rw-------. 1 root ftpmaster 0 Jun 16 11:51 cpu.rt_runtime_us
# -rw-------. 1 root ftpmaster 0 Jun 16 11:51 cpu.shares
# -rw-------. 1 root ftpmaster 0 Jun 16 11:51 notify_on_release
#
# tasks.fperm = 774:
# -rw-rw-r--. 1 root ftpmaster 0 Jun 16 11:51 tasks
.fi
.RE
The
.I daemons
group is created automatically when its first subgroup is
created. All its parameters have the default value and only root can
access the group's files.
.LP
Since both
.I cpuacct
and
.I cpu
subsystems are mounted to the same directory, all
groups are implicitly also controlled by the
.I cpuacct
subsystem, even if there is no
.I cpuacct
section in any of the groups.
.RE
.SS Example 4
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpuacct;
.RE
}
group daemons {
.RS
cpuacct{
}
cpu {
}
.RE
}
.fi
.RE
creates two hierarchies and one common group in both of them.
It corresponds to the following operations:
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mkdir /mnt/cgroups/cpuacct
mount -t cgroup -o cpu cpu /mnt/cgroups/cpu
mount -t cgroup -o cpuacct cpuacct /mnt/cgroups/cpuacct
mkdir /mnt/cgroups/cpu/daemons
mkdir /mnt/cgroups/cpuacct/daemons
.fi
.RE
In fact there are two groups created. One in the
.I cpuacct
hierarchy, the second in the
.I cpu
hierarchy. These two groups have nothing in common and can
contain different subgroups and different tasks.
.SS Example 5
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpuacct;
.RE
}
group daemons {
.RS
cpuacct{
}
.RE
}
group daemons/www {
.RS
cpu {
.RS
cpu.shares = "1000";
.RE
}
.RE
}
group daemons/ftp {
.RS
cpu {
.RS
cpu.shares = "500";
.RE
}
.RE
}
.fi
.RE
creates two hierarchies with few groups inside. One of the groups
is created in both hierarchies.
It corresponds to the following operations:
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mkdir /mnt/cgroups/cpuacct
mount -t cgroup -o cpu cpu /mnt/cgroups/cpu
mount -t cgroup -o cpuacct cpuacct /mnt/cgroups/cpuacct
mkdir /mnt/cgroups/cpuacct/daemons
mkdir /mnt/cgroups/cpu/daemons
mkdir /mnt/cgroups/cpu/daemons/www
echo 1000 > /mnt/cgroups/cpu/daemons/www/cpu.shares
mkdir /mnt/cgroups/cpu/daemons/ftp
echo 500 > /mnt/cgroups/cpu/daemons/ftp/cpu.shares
.fi
.RE
Group
.I daemons
is created in both hierarchies. In the
.I cpuacct
hierarchy the group is explicitly mentioned in the configuration
file. In the
.I cpu
hierarchy the group is created implicitly when
.I www
is created there. These two groups have nothing in common, for example
they do not share processes and subgroups. Groups
.I www
and
.I ftp
are created only in the
.I cpu
hierarchy and are not controlled by the
.I cpuacct
subsystem.
.SS Example 6
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpu;
.RE
}
group . {
.RS
perm {
.RS
task {
.RS
uid = root;
gid = operator;
.RE
}
admin {
.RS
uid = root;
gid = operator;
.RE
}
.RE
}
cpu {
}
.RE
}
group daemons {
.RS
perm {
.RS
task {
.RS
uid = root;
gid = daemonmaster;
.RE
}
admin {
.RS
uid = root;
gid = operator;
.RE
}
.RE
}
cpu {
}
.RE
}
.RE
.fi
creates the hierarchy controlled by two subsystems with one group having some
special permissions.
It corresponds to the following operations:
.LP
.RS
.nf
mkdir /mnt/cgroups/cpu
mount -t cgroup -o cpu,cpuacct cpu /mnt/cgroups/cpu
chown root:operator /mnt/cgroups/cpu/*
chown root:operator /mnt/cgroups/cpu/tasks
mkdir /mnt/cgroups/cpu/daemons
chown root:operator /mnt/cgroups/cpu/daemons/*
chown root:daemonmaster /mnt/cgroups/cpu/daemons/tasks
.fi
.RE
Users which are members of the
.I operator
group are allowed to administer the control groups, i.e. create new control
groups and move processes between these groups without having root
privileges.
Members of the
.I daemonmaster
group can move processes to the
.I daemons
control group, but they can not move the process out of the group. Only the
.I operator
or root can do that.
.SS Example 7
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
cpu = /mnt/cgroups/cpu;
cpuacct = /mnt/cgroups/cpuacct;
.RE
}
group students {
.RS
cpuacct{
}
cpu {
}
.RE
}
template students/%u {
.RS
cpuacct{
}
cpu {
}
.RE
}
mkdir /mnt/cgroups/cpu/daemons
mkdir /mnt/cgroups/cpuacct/daemons
.fi
.RE
The situation is the similar as in Example 4. The only difference is template,
which is used if some rule uses "/students/%u" as a destination.
.SS Example 8
.LP
The configuration file:
.LP
.RS
.nf
mount {
.RS
"cpu,nodev,nosuid,noexec" = /mnt/cgroups/cpu;
.RE
}
.fi
.RE
This is the same as
mount -t cgroup cgroup -o nodev,nosuid,noexec,cpu /mnt/cgroups/cpu
It mounts the cpu controller with MS_NODEV, MS_NOSUID and MS_NOEXEC
options passed.
.SH RECOMMENDATIONS
.SS Keep hierarchies separated
Having multiple hierarchies is perfectly valid and can be useful
in various scenarios. To keeps things clean, do not
create one group in multiple hierarchies. Examples 4 and 5 show
how unreadable and confusing it can be, especially when reading
somebody elses configuration file.
.SS Explicit is better than implicit
.B libcgroup
can implicitly create groups which are needed for the creation of
configured subgroups. This may be useful and save some typing in
simple scenarios. When it comes to multiple hierarchies, it's
better to explicitly specify all groups and all controllers
related to them.
.SH FILES
.TP
.B /etc/cgconfig.conf
default libcgroup configuration file
.TP
.B /etc/cgconfig.d/
default libcgroup configuration files directory
.SH SEE ALSO
cgconfigparser (8)
.SH BUGS
Parameter values must be single strings without spaces.
Parsing of quoted strings is not implemented.
.SH

View file

@ -1,92 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Varekova <varekova@redhat.com>.
.TH CGCONFIGPARSER 8 2009-03-16 "Linux" "libcgroup Manual"
.SH NAME
cgconfigparser \- setup control group file system
.SH SYNOPSIS
\fBcgconfigparser\fR [\fB-h\fR] [\fB-l\fR \fI<filename>\fR] [\fB-L\fR \fI<directory>\fR] [...]
.SH OPTIONS
.TP
.B -h, --help
Displays help.
.TP
.B -l, --load=FILE
Parses the control groups configuration file
Sets up the control group file system
defined by the configuration file and mounts
mount points defined by the configuration file.
The format of the file is described in
\fBcgconfig.conf\fR. This option can be used multiple times and can be mixed
with \fB-L\fR option.
.TP
.B -L, --load-directory=DIR
Finds all files in given directory and parses them in alphabetical order
like they were specified by \fB-l\fR option. This option can be used
multiple times and can be mixed with \fB-l\fR option.
.TP
.B -a <agid>:<auid>
defines the default owner of the
rest of the defined control groups files. These users are
allowed to set subsystem parameters and create subgroups.
The default value is the same as has the parent cgroup.
.TP
.B -d, --dperm=mode
sets the default permissions of a control groups directory.
The permissions needs to be specified as octal numbers e.g.
\fB-d 775\fR.
.TP
.B -f, --fperm=mode
sets the default permissions of the control group files.
The permissions needs to be specified as octal numbers e.g.
\fB-f 775\fR.
The value is not used as given because the current owner's
permissions are used as an umask (so 777 will set group and
others permissions to the owners permissions).
.TP
.B -s, --tperm=mode
sets the default permissions of the control group tasks files.
The permissions needs to be specified as octal numbers e.g.
\fB-f 775\fR.
The value is not used as given because the current owner's
permissions are used as an umask (so 777 will set group and
others permissions to the owners permissions).
.TP
.B -t <tuid>:<tgid>
defines the default owner of tasks file of the defined control
group. I.e. this user and members
of this group have write access to the file.
.LP
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH FILES
.TP
.B /etc/cgconfig.conf
default libcgroup configuration file
.TP
.B /etc/cgconfig.d/
default libcgroup configuration files directory
.SH EXAMPLES
.TP
.B cgconfigparser -l /etc/cgconfig.conf
setup control group file system based on \fB/etc/cgconfig.conf\fR configuration file
.SH SEE ALSO
cgconfig.conf (5)

View file

@ -1,113 +0,0 @@
.\" Written by Ivana Hutarova Varekova <varekova@redhat.com>
.TH CGCREATE 1 2009-03-15 "Linux" "libcgroup Manual"
.SH NAME
cgcreate \- create new cgroup(s)
.SH SYNOPSIS
\fBcgcreate\fR [\fB-h\fR] [\fB-b\fR] [\fB-c\fR]
[\fB-t\fR <\fItuid>:<tgid\fR>] [\fB-a\fR <\fIagid>:<auid\fR>]
[\fB-f\fR mode] [\fB-d\fR mode]
[\fB-s\fR mode] \fB-g\fR <\fIcontrollers>:<path\fR> [\fB-g\fR ...]
.SH DESCRIPTION
The command creates new cgroup(s) defined by the options
\fB-g\fR.
.TP
.B -a <agid>:<auid>
defines the name of the user and the group which own the
rest of the defined control groups files. These users are
allowed to set subsystem parameters and create subgroups.
The default value is the same as has the parent cgroup.
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B -c, --scope
creates a new systemd scope. The cgroup name provided after the
\fB-g\fR flag must be of the form
\fB<slice-name>.slice/<scope-name>.scope\fR. If the slice
does not exist, systemd will create it. Libcgroup will place an
idle process in the scope's cgroup.procs file unless the \fB-p\fR
flag is provided.
.TP
.B -d, --dperm=mode
sets the permissions of a control groups directory.
The permissions needs to be specified as octal numbers e.g.
\fB-d 775\fR.
.TP
.B -f, --fperm=mode
sets the permissions of the control groups parameters.
The permissions needs to be specified as octal numbers e.g.
\fB-f 775\fR.
The value is not used as given because the current owner's
permissions are used as an umask (so 777 will set group and
others permissions to the owners permissions).
.TP
.B -g <controllers>:<path>
defines control groups to be added.
\fBcontrollers\fR is a list of controllers. Character "*" can be used
as a shortcut for "all mounted controllers".
\fBpath\fR is the relative path to control groups
in the given controllers list. This option can be specified
multiple times.
.TP
.B -h, --help
display this help and exit
.TP
.B -p, --pid=pid
moves the provided \fBpid\fR into the
\fB<slice-name>.slice/<scope-name>.scope\fR. Must be used in
conjunction with \fB-c\fR.
.TP
.B -s, --tperm=mode
sets the permissions of the control group tasks file.
The permissions needs to be specified as octal numbers e.g.
\fB-s 775\fR.
The value is not used as given because the current owner's
permissions are used as an umask (so 777 will set group and
others permissions to the owners permissions).
.TP
.B -S, --setdefault
sets the scope specified via the \fB-c\fR option as the default
libcgroup scope. This default scope is used by libcgroup tools
to build up the cgroup path. See the \fB-b\fR option.
.TP
.B -t <tuid>:<tgid>
defines the name of the user and the group, which owns tasks
file of the defined control group. I.e. this user and members
of this group have write access to the file.
The default value is the same as has the parent cgroup.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH EXAMPLES
.TP
.B cgcreate -g *:student devices:teacher
create control group student in all mounted hierarchies and create
control group teacher in hierarchy containing controller devices.
.SH SEE ALSO
cgrules.conf (5)
cgexec (1)
cgclassify (1)

View file

@ -1,51 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Jan Safranek <jsafrane@redhat.com>
.TH CGDELETE 1 2009-10-26 "Linux" "libcgroup Manual"
.SH NAME
cgdelete \- remove control group(s)
.SH SYNOPSIS
\fBcgdelete\fR [\fB-h\fR] [\fB-r\fR] [\fB-b\fR] [[\fB-g\fR]
<\fIcontrollers\fR>:\fI<path\fR>] ...
.SH DESCRIPTION
The \fBcgdelete\fR
program removes all specified control groups.
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B [-g] <controllers>:<path>
Defines the control group to delete. Multiple control groups may be
specified.
.B -g
is optional.
.TP
.B -h, --help
Display this help and exit.
.TP
.B -r, --recursive
Recursively remove all subgroups.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH EXAMPLES
.TP
.B cgdelete -g cpu,devices:/test
remove control group test from hierarchies containing cpu and device controllers
.SH SEE ALSO
cgcreate (1), lscgroup (1)

View file

@ -1,106 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Varekova <varekova@redhat.com>
.TH CGEXEC 1 2009-03-15 "Linux" "libcgroup Manual"
.SH NAME
cgexec \- run the task in given control groups
.SH SYNOPSIS
\fBcgexec\fR [\fB-h\fR] [\fB-b\fR] [\fB-g\fR <\fIcontrollers>:<path\fR>] [--sticky] \fBcommand\fR [\fIarguments\fR]
.SH DESCRIPTION
The \fBcgexec\fR
program executes the task \fBcommand\fR
with arguments \fBarguments\fR in the given control groups.
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B -g <controllers>:<path>
defines the control groups in which the task will be run.
\fBcontrollers\fR is a list of controllers and
\fBpath\fR is the relative path to control groups
in the given controllers list.
This flag can be used multiple times to
define multiple pairs of lists of controllers
and relative paths.
Instead of the list of all mounted controllers,
the wildcard \fBb"*b"\fR can be used.
If this option is not used,
\fBcgexec\fR will automatically place the task in the right
cgroup based on \fB/etc/cgrules.conf\fR.
If \fB/etc/cgrules.conf\fR configuration file is used, there can be used
template names. Then the control group name contains
a template in destination tag (see \fBcgrules.conf\fR (5))
and if the cgroup does not exist in execution time,
it is created, based on \fB/etc/cgconfig.conf\fR specification.
If the specifications are not present the group is created with the default
kernel values.
.TP
.B -h, --help
Display this help and exit.
.TP
.B -r
Replaces systemd scope's idle process with the task \fBcommand\fR.
.TP
.B --sticky
If running the task \fBcommand\fR with this option, the daemon of
service cgred (cgrulesengd process) does not change both the task
of the \fBcommand\fR and the child tasks. Without this option,
the daemon does not change the task of the \fBcommand\fR but it
changes the child tasks to the right cgroup based on
\fB/etc/cgrules.conf\fR automatically.
.LP
.SH EXAMPLES
.nf
.ft B
cgexec -g *:test1 ls
.ft R
.fi
runs command \fBls\fR in control group test1
in all mounted controllers.
.nf
.ft B
cgexec -g cpu,memory:test1 ls -l
.ft R
.fi
runs command \fBls -l\fR in control group test1
in controllers cpu and memory.
.nf
.ft B
cgexec -g cpu,memory:test1 -g swap:test2 ls -l
.ft R
.fi
runs command \fBls -l\fR in control group test1
in controllers cpu and memory and control group
test2 in controller swap.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH FILES
.TP
.B /etc/cgrules.conf
default libcgroup configuration file
.SH SEE ALSO
cgrules.conf (5)

View file

@ -1,115 +0,0 @@
.\" Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
.\" Written by Jan Safranek <jsafrane@redhat.com>
.TH CGGET 1 2010-01-18 "Linux" "libcgroup Manual"
.SH NAME
cgget \- print parameter(s) of given group(s)
.SH SYNOPSIS
\fBcgget\fR [\fB-n\fR] [\fB-v\fR] [\fB-m\fR] [\fB-b\fR] [\fB-r\fR <\fIname\fR>]
[\fB-g\fR <\fIcontroller\fR>] [\fB-a\fR] <\fBpath\fR> ...
.br
\fBcgget\fR [\fB-n\fR] [\fB-v\fR] [\fB-m\fR] [\fB-b\fR] [\fB-r\fR <\fIname\fR>]
\fB-g\fR <\fIcontroller\fR>:<\fBpath\fR> ...
.SH DESCRIPTION
Prints the parameter(s) of input cgroup(s).
If neither controller nor variable are specified,
the values of all possible variables are displayed.
.TP
.B <path>
is the name of the cgroup which should be read.
This parameter can be used multiple times.
.TP
.B -a, --all
print the variables for all controllers which consist in the given cgroup
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B -c
displays the controllers and their versions.
This option can be used along with -m option.
.TP
.B -g <controller>
defines controllers whose values should be displayed.
This option can be used multiple times.
.TP
.B -g <controller>:<path>
defines control groups whose values should be displayed.
This option can be used multiple times.
.TP
.B -h, --help
display help and exit
.TP
.B -m
displays the current control groups setup mode. The control groups can be set up in one of three modes,
legacy (cgroup v1 only), unified (cgroup v2 only) or hybrid (cgroup v1/v2).
.TP
.B -n
do not print headers, i.e. names of groups.
.TP
.B -r, --variable <name>
defines parameter to display.
This option can be used multiple times.
.TP
.B -v, --values-only
print only values, not parameter names.
.SH EXAMPLES
.nf
$ cgget -r cpuset.cpus -r cpuset.mems first second
first:
cpuset.cpus=0-1
cpuset.mems=0
second:
cpuset.cpus=0
cpuset.mems=0
$ cgget -n -r cpuset.cpus -r cpuset.mems first second
cpuset.cpus=0-1
cpuset.mems=0
cpuset.cpus=0
cpuset.mems=0
$ cgget -nv -r cpuset.cpus -r cpuset.mems first second
0-1
0
0
0
$ cgget -n -g cpu /
cpu.rt_period_us=1000000
cpu.rt_runtime_us=950000
cpu.shares=1024
$ cgget -m
Unified Mode (Cgroup v2 only).
.fi
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH SEE ALSO
cgrules.conf (1), cgcreate (1), cgget (1)

View file

@ -1,49 +0,0 @@
.\" Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Varekova <varekova@redhat.com>.
.TH CGRED.CONF 5 2009-03-16 "Linux" "libcgroup Manual"
.SH NAME
cgred.conf \- libcgroup configuration file
.SH DESCRIPTION
\fBcgred.conf\fR is cgred service configuration file.
In this file there could be defined several internal values.
Defining anything else in this file will cause the
CGroup Rules Daemon program to fail.
.TP
\fBCONFIG_FILE\fR
specifies the configuration file for cgred service
.TP
\fBLOG_FILE\fR
variable specifies the file to which logs will be written
(by default they are not sent to a file but to syslog)
.TP
\fBNODAEMON\fR
if it is equal to "--nodaemon" then
run cgred in non-daemon mode
.TP
\fBLOG\fR
define the verbosity of logging. Accepted values are '-v', '-vv', '-q'
and '--nolog'.
.LP
.SH FILES
.LP
.PD .1v
.TP 20
.B /etc/cgred.conf
.TP
default libcgroup configuration file
.PD .
.SH SEE ALSO
cgrules.conf (5),
cgconfig.conf (5), cgrules.d (5)

View file

@ -1,165 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Varekova <varekova@redhat.com>
.TH CGRULES.CONF 5 2009-03-10 "Linux" "libcgroup Manual"
.SH NAME
cgrules.conf \- libcgroup configuration file
.SH DESCRIPTION
.B "cgrules.conf"
configuration file is used by
.B libcgroups
to define control groups to which a process belongs.
The file contains a list of rules which assign to a defined group/user a control
group in a subsystem (or control groups in subsystems).
Rules have two formats:
.in +4n
.nf
<user> <controllers> <destination>
.fi
.nf
<user>:<process name> <controllers> <destination>
.fi
.in
Where:
.I user
can be:
.nf
- a user name
- a group name with @group syntax
- the wildcard '*', for any user or group
- '%', which is equivalent to "ditto" (useful for
multi-line rules where different cgroups need to be
specified for various hierarchies for a single user)
.fi
.I process name
is optional and it can be:
.nf
- a process name
- a full command path of a process
.fi
.I controllers
can be:
.nf
- comma separated controller names (no spaces) or
- * (for all mounted controllers)
.fi
.I destination
can be:
.nf
- path relative to the controller hierarchy (ex. pgrp1/gid1/uid1)
- following strings called "\fBtemplates\fR" and will get expanded
%u username, uid if name resolving fails
%U uid
%g group name, gid if name resolving fails
%G gid
%p process name, pid if name not available
%P pid
'\\' can be used to escape '%'
.fi
First rule which matches the criteria will be executed.
Any text starting with '#' is considered as a start of comment line and is
ignored.
If the
.I destination
contains
.B template
string, the control group can be created on-fly. In time when some process wants
to use the template rule which leads to control group (see
\fBcgexec\fR (1)) and the control group does not exist, the group is created. The
template control group parameters can be specified in
.B cgconfig.conf
configuration file. See (\fBcgconfig.conf\fR (5)).
If the template definition is not found there created group have default
kernel setting.
To create a hierarchy of configuration files, use \fB/etc/cgrules.d\fR directory.
.SH EXAMPLES
.nf
student devices /usergroup/students
.fi
Student's processes in the 'devices' subsystem belong to the control
group /usergroup/students.
.nf
student:cp devices /usergroup/students/cp
.fi
When student executes 'cp' command, the processes in the 'devices' subsystem
belong to the control group /usergroup/students/cp.
.nf
@admin * admingroup/
.fi
Processes started by anybody from admin group no matter in what subsystem belong
to the control group admingroup/.
.nf
peter cpu test1/
% memory test2/
.fi
The first line says Peter's task for cpu controller belongs to test1 control
group. The second one says Peter's tasks for memory controller belong to test2/
control group.
.nf
* * default/
.fi
All processes in any subsystem belong to the control group default/. Since
the earliest matched rule is applied, it makes sense to have this line
at the end of the list. It will put a task which was not mentioned in the
previous rules to default/ control group.
.nf
@students cpu,cpuacct students/%u
.fi
Processes in cpu and cpuacct subsystems started by anybody from students group
belong to group students/name. Where "name" is user name of owner of the
process.
.SH FILES
.LP
.PD .1v
.TP 20
.B /etc/cgrules.conf
.RS 6
default libcgroup configuration file
.RE
.TP 20
.B /etc/cgrules.d
.RS 6
default libcgroup configuration files directory
.RE
.PD
.SH SEE ALSO
cgconfig.conf (5), cgclassify (1), cgred.conf (5), cgrules.d (5)
.SH BUGS

View file

@ -1,50 +0,0 @@
.\" Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
.\" Written by Jan Chaloupka <jchaloup@redhat.com>
.TH CGRULES.D 5 2014-07-14 "Linux" "libcgroup Manual"
.SH NAME
cgrules.d \- libcgroup configuration files directory
.SH DESCRIPTION
.B "cgrules.d"
configuration files directory is used by
.B libcgroups
and contains additional configuration files with the same syntax as
\fBcgconfig.conf\fR (5).
Files are parsed in an arbitrary order.
If the cache is disabled, the searching algorithm of \fBcgrulesengd\fR (8)
tries the first match.
If there are two rules which match the criteria for a given process,
and each rule is in a separate file, then there is no guarantee which one
is chosen. If you want to control the given order of the rules, put them
in one configuration file.
\fB/etc/cgconfig.conf\fR is parsed as the first file. After success,
all files from /etc/cgconfig.d are parsed as well (in an arbitrary order).
If some file from the directory ends up with a parsing error,
the process is stopped. With cache enabled, all successfully processed
rules
are kept in the cache. With cache disabled,
matching is stopped and ends with a 'not found' result.
If \fB/etc/cgrules.d\fR is empty, \fBcgrulesengd\fR (8) acts
in a backwards compatibility mode.
.SH FILES
.LP
.PD .1v
.TP 20
.B /etc/cgrules.d
.RS 4
default libcgroup configuration files directory
.RE
.B /etc/cgconfig.conf
.RS 4
default libcgroup configuration file
.RE
.PD .
.SH SEE ALSO
cgconfig.conf (5), cgrulesengd (8)

View file

@ -1,84 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Jan Safranek <jsafrane@redhat.com>.
.TH CGRULESENGD 8 2009-02-18 "Linux" "libcgroup Manual"
.SH NAME
cgrulesengd \- control group rules daemon
.SH SYNOPSIS
\fBcgrulesengd\fR [options]
.SH DESCRIPTION
\fBcgrulesengd\fR is a daemon, which distributes processes to control groups. When
any process changes its effective UID or GID, \fBcgrulesengd\fR inspects the list
of rules loaded from the \fIcgrules.conf\fR file and files in \fIcgrules.d\fR
(see \fBcgrules.d\fR (5) for potential conflicts) directory
and moves the process to the appropriate control group.
The list of rules is read during the daemon startup and cached in the daemon's memory.
The daemon reloads the list of rules when it receives SIGUSR2 signal.
The daemon reloads the list of templates when it receives SIGUSR1 signal.
The daemon opens a standard unix socket to receive 'sticky' requests from \fBcgexec\fR.
.SH OPTIONS
.TP
.B -h|--help
Display help.
.TP
.B -f <path>|--logfile=<path>
Write log messages to the given log file. When '-' is used as <path>, log messages
are written to the standard output. If '\fB-f\fR' and '\fB-s\fR' are used together,
the logs are sent to both destinations.
.TP
.B -s[facility]|--syslog=[facility]
Write log messages to syslog. The default facility is DAEMON. If '\fB-f\fR'
and '\fB-s\fR' are used together, the logs are sent to both destinations.
.TP
.B -n|--nodaemon
Don't fork the daemon, stay in the foreground.
.TP
.B -v|--verbose
Display more log messages. This option can be used three times to enable more
verbose log messages.
.TP
.B -q|--quiet
Display less log messages.
.TP
.B -Q|--nolog
Disable logging.
.TP
.B -d|--debug
Equivalent to '-nvvvf -', i.e. don't fork the daemon, display all log messages and
write them to the standard output.
.TP
.B -u <user>|--socket-user=<user>
.B -g <group>|--socket-group=<group>
Set the owner of cgrulesengd socket. Assumes that \fBcgexec\fR runs with proper
suid permissions so it can write to the socket when \fBcgexec\fR --sticky is used.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH FILES
.TP
.B /etc/cgrules.conf
default libcgroup configuration file
.TP
.B /etc/cgrules.d
default libcgroup configuration files directory
.TP
.B /etc/cgconfig.conf
default templates file
.TP
.B /etc/cgconfig.d
default templates directory
.SH SEE ALSO
cgrules.conf (5), cgrules.d (5)

View file

@ -1,57 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Hutarova Varekova <varekova@redhat.com>
.TH CGSET 1 2009-03-15 "Linux" "libcgroup Manual"
.SH NAME
cgset \- set the parameters of given cgroup(s)
.SH SYNOPSIS
\fBcgset\fR [\fB-b\fR] [\fB-r\fR <\fIname=value\fR>] <\fBcgroup_path\fR> ...
.br
\fBcgset\fR [\fB-b\fR] \fB--copy-from\fR <\fIsource_cgroup_path\fR> <\fBcgroup_path\fR> ...
.SH DESCRIPTION
Set the parameters of input cgroups.
.TP
.B <path>
is the name of the cgroup which should be changed.
This parameter can be used multiple times.
.TP
.B -b
ignores the default systemd delegated hierarchy path and
constructs the path of the control groups relative to the
cgroup root hierarchy.
.TP
.B -r <name=value>
defines the name of the file to set and
the value which should be written to that file.
This parameter can be used multiple times.
.TP
.B --copy-from <source_cgroup_path>
defines the name of the cgroup whose parameters will be
copied to the input cgroup.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH EXAMPLES
.TP
.B cgset -r cpuset.cpus=0-1 student
set variable cpus in control group student (controller cpuset) to 0-1
.TP
.B cgset --copy-from group1/ group2/
copy all parameters of group group1 to group group2
(for all path where both cgroups are defined)
.SH SEE ALSO
cgrules.conf (1), cgcreate (1), cgget (1)

View file

@ -1,113 +0,0 @@
.\" Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Hutarova Varekova <varekova@redhat.com>
.TH CGSNAPSHOT 1 2010-07-28 "Linux" "libcgroup Manual"
.SH NAME
cgsnapshot \- generate the configuration file for given controllers
.SH SYNOPSIS
\fBcgsnapshot\fR [\fB-h\fR] [\fB-s\fR] [\fB-t\fR] [\fB-b\fR \fIfile\fR]
[\fB-w\fR \fIfile\fR] [\fB-f\fR \fIoutput_file\fR] [\fBcontroller\fR] [...]
.SH DESCRIPTION
\fBcgsnapshot\fR
generates the cgconfig compatible configuration file
for the given controllers.
If no controller is set, then
cgsnapshot shows all mounted hierarchies.
The output is in the same format as the
.B cgconfig.conf
configuration file.
.TP
.B -b file
Display only variables from the denylist.
The default location of the denylist is
.B /etc/cgsnapshot_denylist.conf.
This list contains all variables which should be ignored by the
.B cgsnapshot
.
If the variable is denylisted, it will not be displayed.
If it is not present on the denylist, the allowlist
is checked.
.TP
.B -h, --help
display this help and exit
.TP
.B -f, --file
Redirect the output to output_file
.TP
.B -s, --silent
Ignore all warnings
.TP
.B -t, --strict
Do not display the variables which are not on the allowlist
.TP
.B -w file
Set the denylist configuration file.
This list contains all variables which should be displayed by
.B cgsnapshot
.
If the variable is not denylisted, the allowlist is checked.
If the variable is on the allowlist, it is displayed by
.B cgsnapshot
.
If the variable is not on the allowlist,
the variable is displayed and a warning message is produced.
By default the allowlist is not used.
The warning message can be omitted using the
.B -s, --silent
flag.
If the
.B -t, --strict
flag is used, the variable which is not on the allowlist is
not displayed.
.TP
.B controller
defines the controller whose hierarchies will be
output
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH FILES
.TP
.B /etc/cgsnapshot_denylist.conf
default denylist
.TP
.B /etc/cgsnapshot_allowlist.conf
default allowlist
.TP
.B /etc/cgconfig.conf
default libcgroup configuration file
.SH EXAMPLES
.TP
.B cgsnapshot -s -f /etc/cgconfig.conf.cgsnapshot
create configuration file which contains all mounted controllers and all
control groups which are on the actual system
.TP
.B cgsnapshot -s -f /etc/cgconfig.conf.cgsnapshot cpu
create configuration file which contains hierarchy containing cpu controller and all its
control groups on the actual system
.SH SEE ALSO
cgconfig.conf (5)

View file

@ -1,127 +0,0 @@
.TH CGXGET 1 2022-08-03 "Linux" "libcgroup Manual"
.SH NAME
cgxget \- print parameter(s) of given group(s)
.SH SYNOPSIS
\fBcgxget\fR [\fB-1\fR] [\fB-2\fR] [\fB-i\fR] [\fB-n\fR] [\fB-v\fR] [\fB-b\fR] [\fB-r\fR <\fIname\fR>]
[\fB-g\fR <\fIcontroller\fR>] [\fB-a\fR] <\fBpath\fR> ...
.br
\fBcgxget\fR [\fB-1\fR] [\fB-2\fR] [\fB-i\fR] [\fB-n\fR] [\fB-v\fR] [\fB-b\fR] [\fB-r\fR <\fIname\fR>]
\fB-g\fR <\fIcontroller\fR>:<\fBpath\fR> ...
.SH DESCRIPTION
Prints the parameter(s) of input cgroup(s).
If neither controller nor variable are specified,
the values of all possible variables are displayed.
When the request's cgroup version differs from the system's cgroup version, \fBcgxget\fR will
attempt to translate from one version to the other.
If the request version and the system's version are the same, no translation is done and
\fBcgxget\fR will behave like \fBcgget\fR.
If no version is specified by the user (either [\fB-1\fR] or [\fB-2\fR]), the behavior is
undefined.
.TP
.B <path>
is the name of the cgroup which should be read.
This parameter can be used multiple times.
.TP
.B -1, --v1
data in/out of \fBcgxget\fR is in cgroup v1 format.
In this mode, the user will provide values in cgroup v1 format and receive values in v1 format.
format.
If the system is running in cgroup v2 mode, libcgroup will convert the data as necessary
.TP
.B -2, --v2
data in/out of \fBcgxget\fR is in cgroup v2 format.
In this mode, the user will provide values in cgroup v2 format and receive values in v2 format.
If the system is running in cgroup v1 mode, libcgroup will convert the data as necessary
.TP
.B -a, --all
print the variables for all controllers which consist in the given cgroup
.TP
.B -b
ignores the default systemd delegated hierarchy path and constructs the path of the control groups
relative to the cgroup root hierarchy.
.TP
.B -g <controller>
defines controllers whose values should be displayed.
This option can be used multiple times.
.TP
.B -g <controller>:<path>
defines control groups whose values should be displayed.
This option can be used multiple times.
.TP
.B -h, --help
display help and exit
.TP
.B -i, --ignore-unmappable
ignore errors for values that cannot be converted from v1 to v2 or vice versa
.TP
.B -n
do not print headers, i.e. names of groups.
.TP
.B -r, --variable <name>
defines parameter to display.
This option can be used multiple times.
.TP
.B -v, --values-only
print only values, not parameter names.
.SH EXAMPLES
.nf
$ cgxget -1 -r cpuset.cpus -r cpuset.mems first second
first:
cpuset.cpus=0-1
cpuset.mems=0
second:
cpuset.cpus=0
cpuset.mems=0
$ cgxget -1 -n -r cpuset.cpus -r cpuset.mems first second
cpuset.cpus=0-1
cpuset.mems=0
cpuset.cpus=0
cpuset.mems=0
$ cgxget -1 -nv -r cpuset.cpus -r cpuset.mems first second
0-1
0
0
0
$ cgxget -1 -n -g cpu /
cpu.rt_period_us=1000000
cpu.rt_runtime_us=950000
cpu.shares=1024
$ cgxget -2 -r cpu.max first
first:
cpu.max: max 100000
.fi
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH AUTHOR
Tom Hromatka <tom.hromatka@oracle.com>
.SH SEE ALSO
cgrules.conf (1), cgcreate (1), cgget (1), cgset (1), cgxset (1)

View file

@ -1,81 +0,0 @@
.TH CGXSET 1 2022-08-03 "Linux" "libcgroup Manual"
.SH NAME
cgxset \- set the parameters of given cgroup(s)
.SH SYNOPSIS
\fBcgxset\fR [\fB-1\fR] [\fB-2\fR] [\fB-i\fR] [\fB-b\fR] [\fB-r\fR <\fIname=value\fR>] <\fBcgroup_path\fR> ...
.br
\fBcgxset\fR [\fB-b\fR] \fB--copy-from\fR <\fIsource_cgroup_path\fR> <\fBcgroup_path\fR> ...
.SH DESCRIPTION
Set the parameters of input cgroups.
When the request's cgroup version differs from the system's cgroup version, \fBcgxset\fR will
attempt to translate from one version to the other.
If the request version and the system's version are the same, no translation is done and
\fBcgxset\fR will behave like \fBcgset\fR.
If no version is specified by the user (either [\fB-1\fR] or [\fB-2\fR]) and the [\fB-r\fR] flag
is specified, the behavior is undefined.
\fB--copy-from\fR does not require the cgroup version to be specified.
.TP
.B <path>
is the name of the cgroup which should be changed.
This parameter can be used multiple times.
.TP
.B -1, --v1
data in/out of \fBcgxset\fR is in cgroup v1 format.
In this mode, the user will provide values in cgroup v1 format and receive values in v1 format.
format.
If the system is running in cgroup v2 mode, libcgroup will convert the data as necessary
.TP
.B -2, --v2
data in/out of \fBcgxset\fR is in cgroup v2 format.
In this mode, the user will provide values in cgroup v2 format and receive values in v2 format.
If the system is running in cgroup v1 mode, libcgroup will convert the data as necessary
.TP
.B -b
ignores the default systemd delegated hierarchy path and constructs the path of the control groups
relative to the cgroup root hierarchy.
.TP
.B -i, --ignore-unmappable
ignore errors for values that cannot be converted from v1 to v2 or vice versa
.TP
.B -r <name=value>
defines the name of the file to set and
the value which should be written to that file.
This parameter can be used multiple times.
.TP
.B --copy-from <source_cgroup_path>
defines the name of the cgroup whose parameters will be
copied to the input cgroup.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH EXAMPLES
.TP
.B cgxset -1 -r cpuset.cpus=0-1 student
set variable cpus in control group student (controller cpuset) to 0-1
.TP
.B cgxset -2 -r cpu.weight=42 first
set variable weight in control group first (controller cpu) to 42
.TP
.B cgxset --copy-from group1/ group2/
copy all parameters of group group1 to group group2
(for all path where both cgroups are defined)
.SH SEE ALSO
cgrules.conf (1), cgcreate (1), cgget (1), cgset (1), cgxget (1)

View file

@ -1,49 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Hutarova Varekova <varekova@redhat.com>
.TH LSCGROUP 1 2009-11-05 "Linux" "libcgroup Manual"
.SH NAME
lscgroup \- list all cgroups
.SH SYNOPSIS
\fBlscgroup\fR [[\fB-g\fR] <\fIcontrollers>:<path\fR>] [...]
.br
\fBlscgroup\fR [\fB-h|--help\fR]
.SH DESCRIPTION
List all/chosen cgroups.
.TP
.B <controllers>:<path>
defines the control groups whose subgroups will be shown.
If this parameter is not used, the command will
list all existing cgroups.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.SH EXAMPLES
.TP
.B lscgroup -g cpu:/
list all cgroups which are in hierarchy containing cpu controller
.TP
.B lscgroup -g cpu:/student
list all cgroups which are in hierarchy containing cpu controller
in subgroup student
.TP
.B lscgroup
list all cgroups which in all hierarchies
.SH NOTES
.TP
lscgroup is currently supported on cgroups v1 only.
.SH SEE ALSO
lssubsys (1), cgcreate (1), cgdelete (1),
cgconfig.conf (5)

View file

@ -1,101 +0,0 @@
.\" Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
.\" Written by Ivana Hutarova Varekova <varekova@redhat.com>
.TH LSSUBSYS 1 2009-11-05 "Linux" "libcgroup Manual"
.SH NAME
lssubsys \- list hierarchies containing given subsystem
.SH SYNOPSIS
\fBlssubsys\fR [\fB-m|--mount-points\fR] [\fB-M|--all-mount-points\fR]
[\fIcontroller\fR] [...]
.br
\fBlssubsys\fR [\fB-m|--mount-points\fR] [\fB-M|--all-mount-points\fR]
[\fB-i|--hierarchies\fR] [\fB-a|--all\fR]
.br
\fBlssubsys\fR [\fB-h|--help\fR]
.SH DESCRIPTION
\fBlssubsys\fR list the hierarchies containing
the given subsystem(s). If no subsystem is defined, it
displays all mounted hierarchies.
.TP
.B controller
defines the subsystem whose hierarchy is shown.
If this parameter is not used, the command will
list all mounted subsystems.
.TP
.B -m, --mount-points
Display mount points. Only the first mount points of shown hierarchies are displayed.
.TP
.B -M, --all-mount-points
Display mount points. All mount points of shown hierarchies are displayed, each on
separate line.
.TP
.B -a, --all
Display all subsystems (including unmounted ones).
.TP
.B -i, --hierarchies
Display the attached hierarchy number if the subsystem is in a hierarchy.
If the option
.B -m
is also used, the hierarchy number is shown only for unmounted hierarchies.
.TP
.B -h, --help
Display help and exit.
.SH EXAMPLE
The command
.B lssubsys -am
lists all subsystems which are present in the system,
mounted ones will be shown with their mount point:
.RS
.nf
$ lssubsys -am
ns
cpuset
cpu,devices
cpuacct /cgroup/cpuacct
memory /cgroup/memory
freezer /cgroup/freezer
net_cls /cgroup/net_cls
.fi
.RE
.LP
The command
.B lssubsys -ami
lists all subsystems which are present in the system,
mounted subsystems are listed with their mount points,
unmounted ones which are in a hierarchy are listed with their hierarchy number:
.RS
.nf
$ lssubsys -ami
ns
cpuset 5
cpu,devices 6
cpuacct /cgroup/cpuacct
memory /cgroup/memory
freezer /cgroup/freezer
net_cls /cgroup/net_cls
.fi
.SH NOTES
.TP
lssubsys is currently supported on cgroups v1 only.
.SH ENVIRONMENT VARIABLES
.TP
.B CGROUP_LOGLEVEL
controls verbosity of the tool. Allowed values are \fBDEBUG\fR,
\fBINFO\fR, \fBWARNING\fR or \fBERROR\fR.
.RE
.SH SEE ALSO
lscgroup (1), cgcreate (1), cgdelete (1),
cgconfig.conf (5)

View file

@ -1,9 +0,0 @@
# Using 'nobase_', we what groups.h in /usr/include/libcgroup/ directory
nobase_include_HEADERS = libcgroup.h libcgroup/error.h libcgroup/init.h \
libcgroup/groups.h libcgroup/tasks.h \
libcgroup/iterators.h libcgroup/config.h \
libcgroup/log.h libcgroup/tools.h
if WITH_SYSTEMD
nobase_include_HEADERS += libcgroup/systemd.h
endif

View file

@ -1,43 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
/**
* Copyright IBM Corporation. 2007
*
* Author: Balbir Singh <balbir@linux.vnet.ibm.com>
*/
#ifndef _LIBCGROUP_H
#define _LIBCGROUP_H
#define _LIBCGROUP_H_INSIDE
#include <libcgroup/error.h>
#include <libcgroup/init.h>
#include <libcgroup/iterators.h>
#include <libcgroup/groups.h>
#include <libcgroup/tasks.h>
#include <libcgroup/config.h>
#include <libcgroup/log.h>
#include <libcgroup/tools.h>
#include <libcgroup/systemd.h>
#undef _LIBCGROUP_H_INSIDE
/*! \mainpage libcgroup
*
* \section intro_sec Introduction
*
* @c libcgroup is a library that abstracts the control group file system in Linux.
* It comes with various command-line tools and configuration files, see
* their man pages for details.
*
* This documentation provides description of @c libcgroup API. Read following
* sections, preferably in this order:
* -# @ref group_init "Initialization"
* -# @ref group_groups "Control Groups"
* -# @ref group_iterators "Iterators"
* -# @ref group_tasks "Manipulation with tasks"
* -# @ref group_config "Configuration"
* -# @ref group_errors "Error Handling"
*/
#endif /* _LIBCGROUP_H */

View file

@ -1,138 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_CONFIG_H
#define _LIBCGROUP_CONFIG_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup group_config 5. Configuration
* @{
*
* @name Configuration file
* @{
*
* @c libcgroup can mount and create control groups and set their parameters as
* specified in a configuration file.
*
* @todo add this description?: These functions are mostly intended
* to be used by internal @c libcgroup tools, however they are fully supported
* and applications can benefit from them.
*/
/**
* Load configuration file and mount and create control groups described there.
* See cgconfig.conf man page for format of the file.
* @param pathname Name of the configuration file to load.
*/
int cgroup_config_load_config(const char *pathname);
/**
* Delete all control groups and unmount all hierarchies.
*/
int cgroup_unload_cgroups(void);
/**
* Delete all cgroups and unmount all mount points defined in specified config
* file.
*
* The groups are either removed recursively or only the empty ones, based
* on given flags. Mount point are always umounted only if they are empty,
* regardless of any flags.
*
* The groups are sorted before they are removed, so the removal of empty ones
* actually works (i.e. subgroups are removed first).
*
* @param pathname Name of the configuration file to unload.
* @param flags Combination of CGFLAG_DELETE_* flags, which indicate what and
* how to delete.
*/
int cgroup_config_unload_config(const char *pathname, int flags);
/**
* Sets default permissions of groups created by subsequent
* cgroup_config_load_config() calls. If a config file contains a 'default {}'
* section, the default permissions from the config file is then used.
*
* Use cgroup_new_cgroup() to create a dummy group and cgroup_set_uid_gid() and
* cgroup_set_permissions() to set its permissions. Use NO_UID_GID instead of
* GID/UID and NO_PERMS instead of file/directory permissions to let kernel
* decide the default permissions where you don't want specific user and/or
* permissions. Kernel then uses current user/group and permissions from umask
* then.
*
* @param new_default New default permissions from this group are copied to
* libcgroup internal structures. I.e., this group can be freed immediatelly
* after this function returns.
*/
int cgroup_config_set_default(struct cgroup *new_default);
/**
* Initializes the templates cache and load it from file pathname.
*/
int cgroup_init_templates_cache(char *pathname);
/**
* Reloads the templates list from file pathname.
*/
int cgroup_reload_cached_templates(char *pathname);
/**
* Load the templates cache from files. Before calling this function,
* cgroup_templates_cache_set_source_files has to be called first.
* @param file_index index of file which was unable to be parsed
* @return 0 on success, > 0 on error
*/
int cgroup_load_templates_cache_from_files(int *file_index);
/**
* Setting source files of templates. This function has to be called before
* any call of cgroup_load_templates_cache_from_files.
* @param tmpl_files
*/
struct cgroup_string_list;
void cgroup_templates_cache_set_source_files(
struct cgroup_string_list *tmpl_files);
/**
* Physically create a new control group in kernel, based on given control
* group template and configuration file. If given template is not set in
* configuration file, then the procedure works create the control group
* using cgroup_create_cgroup() function
*
* Templates are loaded using cgroup_load_templates_cache_from_files
* function, which must be preceded by cgroup_templates_cache_set_source_files
* call.
*
* The flags can alter the behavior of this function:
* CGFLAG_USE_TEMPLATE_CACHE: Use cached templates instead of
* parsing the config file
*
* @param pathname Name of the configuration file with template definitions
* @param cgroup Wanted control group - contains substitute name and wanted
* controllers.
* @param template_name Template name used for cgroup setting
* @param flags Bit flags to change the behavior
*/
int cgroup_config_create_template_group(
struct cgroup *cgroup, char *template_name,
int flags);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*_LIBCGROUP_CONFIG_H*/

View file

@ -1,111 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_ERROR_H
#define _LIBCGROUP_ERROR_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup group_errors 6. Error handling
* @{
*
* @name Error handling
* @{
* Unless states otherwise in documentation of a function, all functions
* return @c int, which is zero (0) when the function succeeds, and positive
* number if the function fails.
*
* The returned integer is one of the ECG* values described below. Value
* #ECGOTHER means that the error was caused by underlying OS and the real
* cause can be found by calling cgroup_get_last_errno().
*/
enum {
ECGROUPNOTCOMPILED = 50000,
ECGROUPNOTMOUNTED, /* 50001 */
ECGROUPNOTEXIST, /* 50002 */
ECGROUPNOTCREATED, /* 50003 */
ECGROUPSUBSYSNOTMOUNTED, /* 50004 */
ECGROUPNOTOWNER, /* 50005 */
/** Controllers bound to different mount points */
ECGROUPMULTIMOUNTED, /* 50006 */
/* This is the stock error. Default error. @todo really? */
ECGROUPNOTALLOWED, /* 50007 */
ECGMAXVALUESEXCEEDED, /* 50008 */
ECGCONTROLLEREXISTS, /* 50009 */
ECGVALUEEXISTS, /* 50010 */
ECGINVAL, /* 50011 */
ECGCONTROLLERCREATEFAILED, /* 50012 */
ECGFAIL, /* 50013 */
ECGROUPNOTINITIALIZED, /* 50014 */
ECGROUPVALUENOTEXIST, /* 50015 */
/**
* Represents error coming from other libraries like glibc. @c libcgroup
* users need to check cgroup_get_last_errno() upon encountering this
* error.
*/
ECGOTHER, /* 50016 */
ECGROUPNOTEQUAL, /* 50017 */
ECGCONTROLLERNOTEQUAL, /* 50018 */
/** Failed to parse rules configuration file. */
ECGROUPPARSEFAIL, /* 50019 */
/** Rules list does not exist. */
ECGROUPNORULES, /* 50020 */
ECGMOUNTFAIL, /* 50021 */
/**
* Not an real error, it just indicates that iterator has come to end
* of sequence and no more items are left.
*/
ECGEOF = 50023,
/** Failed to parse config file (cgconfig.conf). */
ECGCONFIGPARSEFAIL, /* 50024 */
ECGNAMESPACEPATHS, /* 50025 */
ECGNAMESPACECONTROLLER, /* 50026 */
ECGMOUNTNAMESPACE, /* 50027 */
ECGROUPUNSUPP, /* 50028 */
ECGCANTSETVALUE, /* 50029 */
/** Removing of a group failed because it was not empty. */
ECGNONEMPTY, /* 50030 */
/** Failed to convert from cgroup v1 to/from cgroup v2 */
ECGNOVERSIONCONVERT, /* 50031 */
};
/**
* Legacy definition of ECGRULESPARSEFAIL error code.
*/
#define ECGRULESPARSEFAIL ECGROUPPARSEFAIL
/**
* Format error code to a human-readable English string. No internationalization
* is currently done. Returned pointer leads to @c libcgroup memory and
* must not be freed nor modified. The memory is rewritten by subsequent
* call to this function.
* @param code Error code for which the corresponding error string is
* returned. When #ECGOTHER is used, text with glibc's description of
* cgroup_get_last_errno() value is returned.
*/
const char *cgroup_strerror(int code);
/**
* Return last errno, which caused ECGOTHER error.
*/
int cgroup_get_last_errno(void);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_INIT_H */

View file

@ -1,706 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_GROUPS_H
#define _LIBCGROUP_GROUPS_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#include <sys/types.h>
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum cg_version_t {
CGROUP_UNK = 0,
CGROUP_V1,
CGROUP_V2,
CGROUP_DISK = 0xFF,
};
enum cg_setup_mode_t {
CGROUP_MODE_UNK = 0,
CGROUP_MODE_LEGACY,
CGROUP_MODE_HYBRID,
CGROUP_MODE_UNIFIED,
};
/**
* Flags for cgroup_delete_cgroup_ext().
*/
enum cgroup_delete_flag {
/**
* Ignore errors caused by migration of tasks to parent group.
*/
CGFLAG_DELETE_IGNORE_MIGRATION = 1,
/**
* Recursively delete all child groups.
*/
CGFLAG_DELETE_RECURSIVE = 2,
/**
* Delete the cgroup only if it is empty, i.e. it has no subgroups and
* no processes inside. This flag cannot be used with
* CGFLAG_DELETE_RECURSIVE.
*/
CGFLAG_DELETE_EMPTY_ONLY = 4,
};
/**
* @defgroup group_groups 2. Group manipulation API
* @{
*
* @name Basic infrastructure
* @{
* <tt>struct cgroup*</tt> is the heart of @c libcgroup API.
* The structure is opaque to applications, all access to the structure is
* through appropriate functions.
*
* The most important information is that <b> one <tt>struct cgroup*</tt> can
* represent zero, one or more real control groups in kernel</b>.
* The <tt>struct cgroup*</tt> is identified by name of the group, which must be
* set by cgroup_new_cgroup(). Multiple controllers (aka subsystems) can be
* attached to one <tt>struct cgroup*</tt> using cgroup_add_controller(). These
* controllers <b>can belong to different hierarchies</b>.
*
* This approach is different to the one in the Linux kernel - a control group
* must be part of exactly one hierarchy there. In @c libcgroup, a group can be
* part of multiple hierarchies, as long as the group name is the same.
*
* @par Example:
* Let there be following control groups:
* @code
* cpu,cpuacct:/
* cpu,cpuacct:/foo
* cpu,cpuacct:/bar
* freezer:/
* freezer:/foo
* @endcode
* I.e. there is @c cpu and @c cpuacct controller mounted together in one
* hierarchy, with @c foo and @c bar groups. In addition, @c freezer is
* mounted as separate hierarchy, with only one @c foo group.
*
* @par
* Following code creates <tt>struct cgroup*</tt> structure, which represents
* one group <tt>cpu,cpuacct:/foo</tt>:
* @code
* struct cgroup *foo = cgroup_new_cgroup("foo");
* cgroup_add_controller(foo, "cpu");
* @endcode
* Now, you can call e.g. cgroup_delete_cgroup() and the group is deleted from
* the hierarchy. You can note that it's enough to add only one controller to
* the group to fully identify a group in <tt>cpu,cpuacct</tt> hierarchy.
*
* @par
* Following code creates <tt>struct cgroup*</tt> structure, which represents
* @b two groups, <tt>cpu,cpuacct:/foo</tt> and <tt>freezer:/foo</tt>:
* @code
* struct cgroup *foo = cgroup_new_cgroup("foo");
* cgroup_add_controller(foo, "cpu");
* cgroup_add_controller(foo, "freezer");
* @endcode
* Now, if you call e.g. cgroup_delete_cgroup(), the group gets deleted from
* @b both hierarchies.
*
* @todo add some propaganda what's so great on this approach... I personally
* think it is broken and confusing (see TODOs below).
*
* Following functions are provided to create/destroy various libcgroup
* structures. Please note that none of these functions actually create or
* delete a cgroup in kernel!
*/
/**
* @struct cgroup
*
* Structure describing one or more control groups. The structure is opaque to
* applications.
*/
struct cgroup;
/**
* @struct cgroup_controller
* Structure describing a controller attached to one struct @c cgroup, including
* parameters of the group and their values. The structure is opaque to
* applications.
* @see groups
*/
struct cgroup_controller;
/**
* Uninitialized file/directory permissions used for task/control files.
*/
#define NO_PERMS (-1U)
/**
* Uninitialized UID/GID used for task/control files.
*/
#define NO_UID_GID (-1U)
/**
* Allocate new cgroup structure. This function itself does not create new
* control group in kernel, only new <tt>struct cgroup</tt> inside libcgroup!
*
* @param name Path to the group, relative from root group. Use @c "/" or @c "."
* for the root group itself and @c "/foo/bar/baz" or @c "foo/bar/baz" for
* subgroups.
* @todo suggest one preferred way, either "/foo" or "foo".
* @returns Created group or NULL on error.
*/
struct cgroup *cgroup_new_cgroup(const char *name);
/**
* Attach new controller to cgroup. This function just modifies internal
* libcgroup structure, not the kernel control group.
*
* @param cgroup
* @param name The name of the controller, e.g. "freezer".
* @return Created controller or NULL on error.
*/
struct cgroup_controller *cgroup_add_controller(struct cgroup *cgroup,
const char *name);
/**
* Attach all mounted controllers to given cgroup. This function just modifies
* internal libcgroup structure, not the kernel control group.
*
* @param cgroup
* @return zero or error number
*/
int cgroup_add_all_controllers(struct cgroup *cgroup);
/**
* Return appropriate controller from given group.
* The controller must be added before using cgroup_add_controller() or loaded
* from kernel using cgroup_get_cgroup().
* @param cgroup
* @param name The name of the controller, e.g. "freezer".
*/
struct cgroup_controller *cgroup_get_controller(struct cgroup *cgroup,
const char *name);
/**
* Free internal @c cgroup structure. This function frees also all controllers
* attached to the @c cgroup, including all parameters and their values.
* @param cgroup
*/
void cgroup_free(struct cgroup **cgroup);
/**
* Free internal list of controllers from the group.
* @todo should this function be public???
* @param cgroup
*/
void cgroup_free_controllers(struct cgroup *cgroup);
/**
* @}
* @name Group manipulation API
* Using following functions you can create and remove control groups and
* change their parameters.
* @note All access to kernel is through previously mounted cgroup filesystems.
* @c libcgroup does not mount/unmount anything for you.
* @{
*/
/**
* Physically create a control group in kernel. The group is created in all
* hierarchies, which cover controllers added by cgroup_add_controller().
* All parameters set by cgroup_add_value_* functions are written.
* The created groups has owner which was set by cgroup_set_uid_gid() and
* permissions set by cgroup_set_permissions.
* @param cgroup
* @param ignore_ownership When nozero, all errors are ignored when setting
* owner of the group and/or its tasks file.
* @todo what is ignore_ownership good for?
* @retval #ECGROUPNOTEQUAL if not all specified controller parameters
* were successfully set.
*/
int cgroup_create_cgroup(struct cgroup *cgroup, int ignore_ownership);
/**
* Physically create new control group in kernel, with all parameters and values
* copied from its parent group. The group is created in all hierarchies, where
* the parent group exists. I.e. following code creates subgroup in all
* hierarchies, because all of them have root (=parent) group.
* @code
* struct cgroup *foo = cgroup_new_cgroup("foo");
* cgroup_create_cgroup_from_parent(foo, 0);
* @endcode
* @todo what is this good for? Why the list of controllers added by
* cgroup_add_controller() is not used, like in cgroup_create_cgroup()? I can't
* crate subgroup of root group in just one hierarchy with this function!
*
* @param cgroup The cgroup to create. Only it's name is used, everything else
* is discarded.
* @param ignore_ownership When nozero, all errors are ignored when setting
* owner of the group and/or its tasks file.
* @todo what is ignore_ownership good for?
* @retval #ECGROUPNOTEQUAL if not all inherited controller parameters
* were successfully set (this is expected).
*/
int cgroup_create_cgroup_from_parent(struct cgroup *cgroup,
int ignore_ownership);
/**
* Physically modify a control group in kernel. All parameters added by
* cgroup_add_value_ or cgroup_set_value_ are written.
* Currently it's not possible to change and owner of a group.
*
* @param cgroup
*/
int cgroup_modify_cgroup(struct cgroup *cgroup);
/**
* Physically remove a control group from kernel. The group is removed from
* all hierarchies, which cover controllers added by cgroup_add_controller()
* or cgroup_get_cgroup(). All tasks inside the group are automatically moved
* to parent group.
*
* The group being removed must be empty, i.e. without subgroups. Use
* cgroup_delete_cgroup_ext() for recursive delete.
*
* @param cgroup
* @param ignore_migration When nozero, all errors are ignored when migrating
* tasks from the group to the parent group.
* @todo what is ignore_migration good for? rmdir() will fail if tasks were not moved.
*/
int cgroup_delete_cgroup(struct cgroup *cgroup, int ignore_migration);
/**
* Physically remove a control group from kernel.
* All tasks are automatically moved to parent group.
* If #CGFLAG_DELETE_IGNORE_MIGRATION flag is used, the errors that occurred
* during the task movement are ignored.
* #CGFLAG_DELETE_RECURSIVE flag specifies that all subgroups should be removed
* too. If root group is being removed with this flag specified, all subgroups
* are removed but the root group itself is left undeleted.
* @see cgroup_delete_flag.
*
* @param cgroup
* @param flags Combination of CGFLAG_DELETE_* flags, which indicate what and
* how to delete.
*/
int cgroup_delete_cgroup_ext(struct cgroup *cgroup, int flags);
/**
* @}
* @name Other functions
* @{
* Helper functions to manipulate with control groups.
*/
/**
* Read all information regarding the group from kernel.
* Based on name of the group, list of controllers and all parameters and their
* values are read from all hierarchies, where a group with given name exists.
* All existing controllers are replaced. I.e. following code will fill @c root
* with controllers from all hierarchies, because the root group is available in
* all of them.
* @code
* struct cgroup *root = cgroup_new_cgroup("/");
* cgroup_get_cgroup(root);
* @endcode
*
* @todo what is this function good for? Why is not considered only the list of
* controllers attached by cgroup_add_controller()? What owners will return
* cgroup_get_uid_gid() if the group is in multiple hierarchies, each with
* different owner of tasks file?
*
* @param cgroup The cgroup to load. Only it's name is used, everything else
* is replaced.
*/
int cgroup_get_cgroup(struct cgroup *cgroup);
/**
* Copy all controllers, their parameters and values. Group name, permissions
* and ownerships are not coppied. All existing controllers
* in the source group are discarded.
*
* @param dst Destination group.
* @param src Source group.
*/
int cgroup_copy_cgroup(struct cgroup *dst, struct cgroup *src);
/**
* Compare names, owners, controllers, parameters and values of two groups.
*
* @param cgroup_a
* @param cgroup_b
*
* @retval 0 if the groups are the same.
* @retval #ECGROUPNOTEQUAL if the groups are not the same.
* @retval #ECGCONTROLLERNOTEQUAL if the only difference are controllers,
* parameters or their values.
*/
int cgroup_compare_cgroup(struct cgroup *cgroup_a, struct cgroup *cgroup_b);
/**
* Compare names, parameters and values of two controllers.
*
* @param cgca
* @param cgcb
*
* @retval 0 if the controllers are the same.
* @retval #ECGCONTROLLERNOTEQUAL if the controllers are not equal.
*/
int cgroup_compare_controllers(struct cgroup_controller *cgca,
struct cgroup_controller *cgcb);
/**
* Set owner of the group control files and the @c tasks file. This function
* modifies only @c libcgroup internal @c cgroup structure, use
* cgroup_create_cgroup() afterwards to create the group with given owners.
*
* @param cgroup
* @param tasks_uid UID of the owner of group's @c tasks file.
* @param tasks_gid GID of the owner of group's @c tasks file.
* @param control_uid UID of the owner of group's control files (i.e.
* parameters).
* @param control_gid GID of the owner of group's control files (i.e.
* parameters).
*/
int cgroup_set_uid_gid(struct cgroup *cgroup, uid_t tasks_uid, gid_t tasks_gid,
uid_t control_uid, gid_t control_gid);
/**
* Return owners of the group's @c tasks file and control files.
* The data is read from @c libcgroup internal @c cgroup structure, use
* cgroup_set_uid_gid() or cgroup_get_cgroup() to fill it.
*/
int cgroup_get_uid_gid(struct cgroup *cgroup, uid_t *tasks_uid,
gid_t *tasks_gid, uid_t *control_uid,
gid_t *control_gid);
/**
* Stores given file permissions of the group's control and tasks files
* into the @c cgroup data structure. Use NO_PERMS if permissions shouldn't
* be changed or a value which applicable to chmod(2). Please note that
* the given permissions are masked with the file owner's permissions.
* For example if a control file has permissions 640 and control_fperm is
* 471 the result will be 460.
* @param cgroup
* @param control_dperm Directory permission for the group.
* @param control_fperm File permission for the control files.
* @param task_fperm File permissions for task file.
*/
void cgroup_set_permissions(struct cgroup *cgroup,
mode_t control_dperm, mode_t control_fperm,
mode_t task_fperm);
/**
* @}
* @name Group parameters
* These are functions can read or modify parameter of a group.
* @note All these functions read/write parameters to @c libcgorup internal
* structures. Use cgroup_get_cgroup() to load parameters from kernel to these
* internal structures and cgroup_modify_cgroup() or cgroup_create_cgroup() to
* write changes to kernel.
* @{
*/
/**
* Add parameter and its value to internal @c libcgroup structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*
*/
int cgroup_add_value_string(struct cgroup_controller *controller,
const char *name, const char *value);
/**
* Add parameter and its value to internal @c libcgroup structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
* Content of the value is copied to internal structures and is not needed
* after return from the function.
*
* @param controller
* @param name The name of the parameter.
* @param value
*
*/
int cgroup_add_value_int64(struct cgroup_controller *controller,
const char *name, int64_t value);
/**
* Add parameter and its value to internal @c libcgroup structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*
*/
int cgroup_add_value_uint64(struct cgroup_controller *controller,
const char *name, u_int64_t value);
/**
* Add parameter and its value to internal @c libcgroup structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*
*/
int cgroup_add_value_bool(struct cgroup_controller *controller,
const char *name, bool value);
/**
* Read a parameter value from @c libcgroup internal structures.
* Use @c cgroup_get_cgroup() to fill these structures with data from kernel.
* It's up to the caller to free returned value.
*
* This function works only for 'short' parameters. Use
* cgroup_read_stats_begin(), cgroup_read_stats_next() and
* cgroup_read_stats_end() to read @c stats parameter, which can be longer
* than libcgroup's internal buffers.
* @todo rephrase, it's too vague... How big is the buffer actually?
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_get_value_string(struct cgroup_controller *controller,
const char *name, char **value);
/**
* Read a parameter value from @c libcgroup internal structures.
* Use @c cgroup_get_cgroup() to fill these structures with data from kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_get_value_int64(struct cgroup_controller *controller,
const char *name, int64_t *value);
/**
* Read a parameter value from @c libcgroup internal structures.
* Use @c cgroup_get_cgroup() to fill these structures with data from kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_get_value_uint64(struct cgroup_controller *controller,
const char *name, u_int64_t *value);
/**
* Read a parameter value from @c libcgroup internal structures.
* Use @c cgroup_get_cgroup() to fill these structures with data from kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_get_value_bool(struct cgroup_controller *controller,
const char *name, bool *value);
/**
* Set a parameter value in @c libcgroup internal structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_set_value_string(struct cgroup_controller *controller,
const char *name, const char *value);
/**
* Set a parameter value in @c libcgroup internal structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
* Content of the value is copied to internal structures and is not needed
* after return from the function.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_set_value_int64(struct cgroup_controller *controller,
const char *name, int64_t value);
/**
* Set a parameter value in @c libcgroup internal structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_set_value_uint64(struct cgroup_controller *controller,
const char *name, u_int64_t value);
/**
* Set a parameter value in @c libcgroup internal structures.
* Use cgroup_modify_cgroup() or cgroup_create_cgroup() to write it to kernel.
*
* @param controller
* @param name The name of the parameter.
* @param value
*/
int cgroup_set_value_bool(struct cgroup_controller *controller,
const char *name, bool value);
/**
* Return the number of variables for the specified controller in @c libcgroup
* internal structures. Use cgroup_get_cgroup() to fill these structures with
* data from kernel. Use this function together with cgroup_get_value_name()
* to list all parameters of a group.
*
* @param controller
* @return Count of the parameters or -1 on error.
*/
int cgroup_get_value_name_count(struct cgroup_controller *controller);
/**
* Return the name of parameter of controller at given index.
* The index goes from 0 to cgroup_get_value_name_count()-1.
* Use this function to list all parameter of the controller.
*
* @note The returned value is pointer to internal @c libcgroup structure,
* do not free it.
*
* @param controller
* @param index The index of the parameter.
* @return Name of the parameter.
*/
char *cgroup_get_value_name(struct cgroup_controller *controller, int index);
/**
* Get the list of process in a cgroup. This list is guaranteed to
* be sorted. It is not necessary that it is unique.
* @param name The name of the cgroup
* @param controller The name of the controller
* @param pids The list of pids. Should be uninitialized when passed
* to the API. Should be freed by the caller using free.
* @param size The size of the pids array returned by the API.
*/
int cgroup_get_procs(char *name, char *controller, pid_t **pids, int *size);
/**
* Change permission of files and directories of given group
* @param cgroup The cgroup which permissions should be changed
* @param dir_mode The permission mode of group directory
* @param dirm_change Denotes whether the directory change should be done
* @param file_mode The permission mode of group files
* @param filem_change Denotes whether the directory change should be done
*/
int cg_chmod_recursive(struct cgroup *cgroup, mode_t dir_mode,
int dirm_change, mode_t file_mode, int filem_change);
/**
* Get the name of the cgroup from a given cgroup
* @param cgroup The cgroup whose name is needed
*/
char *cgroup_get_cgroup_name(struct cgroup *cgroup);
/*
* Convert from one cgroup version to another version
*
* @param out_cgroup Destination cgroup
* @param out_version Destination cgroup version
* @param in_cgroup Source cgroup
* @param in_version Source cgroup version, only used if set to v1 or v2
*
* @return 0 on success
* ECGFAIL conversion failed
* ECGCONTROLLERNOTEQUAL incorrect controller version provided
*/
int cgroup_convert_cgroup(struct cgroup * const out_cgroup,
enum cg_version_t out_version,
const struct cgroup * const in_cgroup,
enum cg_version_t in_version);
/**
* List the mount paths, that matches the specified version
*
* @param cgrp_version The cgroup type/version
* @param mount_paths Holds the list of mount paths
* @return 0 success and list of mounts paths in mount_paths
* ECGOTHER on failure and mount_paths is NULL.
*/
int cgroup_list_mount_points(const enum cg_version_t cgrp_version,
char ***mount_paths);
/**
* Get the cgroup version of a controller. Version is set to CGROUP_UNK
* if the version cannot be determined.
*
* @param controller The controller of interest
* @param version The version of the controller
*/
int cgroup_get_controller_version(const char * const controller,
enum cg_version_t * const version);
/**
* Get the current group setup mode (legacy/unified/hybrid)
*
* @return CGROUP_MODE_UNK on failure and setup mode on success
*/
enum cg_setup_mode_t cgroup_setup_mode(void);
/**
* Return the number of controllers for the specified cgroup in libcgroup
* internal structures.
*
* @param cgroup
* @return Count of the controllers or -1 on error.
*/
int cgroup_get_controller_count(struct cgroup *cgroup);
/**
* Return requested controller from given group
*
* @param cgroup
* @param index The index into the cgroup controller list
*/
struct cgroup_controller *cgroup_get_controller_by_index(struct cgroup *cgroup, int index);
/**
* Given a controller pointer, get the name of the controller
*
* @param controller
* @return controller name string, NULL if there's an error
*/
char *cgroup_get_controller_name(struct cgroup_controller *controller);
/**
* Return true if cgroup setup mode is cgroup v1 (legacy), else
* returns false.
*/
bool is_cgroup_mode_legacy(void);
/**
* Return true if cgroup setup mode is cgroup v1/v2 (hybrid), else
* returns false.
*/
bool is_cgroup_mode_hybrid(void);
/**
* Return true if cgroup setup mode is cgroup v2 (unified), else
* returns false.
*/
bool is_cgroup_mode_unified(void);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_GROUPS_H */

View file

@ -1,86 +0,0 @@
#ifndef _LIBCGROUP_INIT_H
#define _LIBCGROUP_INIT_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define CGROUP_VER_MAJOR @LIBRARY_VERSION_MAJOR@
#define CGROUP_VER_MINOR @LIBRARY_VERSION_MINOR@
#define CGROUP_VER_RELEASE @LIBRARY_VERSION_RELEASE@
struct cgroup_library_version {
unsigned int major;
unsigned int minor;
unsigned int release;
};
/**
* Query the library version information
*
* This function returns a pointer to a populated cgroup_library_version
* struct. The caller does not need to free the structure when finished.
*
*/
const struct cgroup_library_version *cgroup_version(void);
/**
* @defgroup group_init 1. Initialization
* @{
*
* @name Initialization
* @{
* Application must initialize @c libcgroup using cgroup_init() before any
* other @c libcgroup function can be called. @c libcgroup caches information
* about mounted hierarchies (just what's mounted where, not the control groups
* themselves) at this time. There is currently no way to refresh this cache,
* i.e. all subsequent mounts/remounts/unmounts are not reflected in this cache
* and @c libcgroup may produce unexpected results.
*
* In addition, there is no way how to clean the cache on application exit.
*
* @todo this is very bad... There should be at least way how to refresh the
* cache and/or an option to refresh it automatically (does kernel provide
* any indication, when a filesystem is mounted/unmounted?). Dtto the cleanup
* on exit.
*/
/**
* Initialize libcgroup. Information about mounted hierarchies are examined
* and cached internally (just what's mounted where, not the groups themselves).
*
* If the cgroup logging was not set using cgroup_set_logger() or
* cgroup_set_default_logger() before calling cgroup_init(), the default logger
* is automatically set, logging CGROUP_LOG_ERROR messages.
*/
int cgroup_init(void);
/**
* Returns path where is mounted given controller. Applications should rely on
* @c libcgroup API and not call this function directly.
* Only the first mount point is returned, use
* cgroup_get_subsys_mount_point_begin(), cgroup_get_subsys_mount_point_next()
* and cgroup_get_subsys_mount_point_end() to get all of them.
* @param controller Name of the controller
* @param mount_point The string where the mount point location is stored.
* Please note, the caller must free the mount_point.
*/
int cgroup_get_subsys_mount_point(const char *controller, char **mount_point);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_INIT_H */

View file

@ -1,435 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_ITERATORS_H
#define _LIBCGROUP_ITERATORS_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <sys/types.h>
#include <stdio.h>
#include <features.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup group_iterators 3. Iterators
* @{
* So-called iterators are a code pattern to retrieve various data from
* libcgroup in distinct chunks, for example when an application needs to read
* list of groups in a hierarchy, it uses iterator to get one group at a time.
* Iterator is opaque to the application, the application sees only
* <tt>void* handle</tt> pointer, which is managed internally by @c libcgroup.
* Each iterator provides at least these functions:
* - <tt>int <i>iterator_name</i>_begin(void **handle, my_type *item)</tt>
* - Initialize the iterator, store pointer to it into the @c handle.
* - Return the first element in the iterator, let's say it's @c my_type.
* - Return @c 0, if the operation succeeded.
* - Return #ECGEOF, if the operation succeeded, but the iterator is empty.
* The value of @c item is undefined in this case.
* - Return any other error code on error.
* - <tt>int <i>iterator_name</i>_next(void **handle, my_type *item)</tt>
* - Advance to next element in the iterator and return it.
* - Return @c 0, if the operation succeeded.
* - Return #ECGEOF, if there is no item to advance to, i.e. the iterator
* is already at its end. The value of @c item is undefined in this case.
* - Return any other error code on error.
* - <tt>void <i>iterator_name</i>_end(void **handle)</tt>
* - Free any data associated with the iterator. This function must be
* called even when <tt><i>iterator_name</i>_begin()</tt> fails.
*
* @todo not all iterators follow this pattern, e.g. cgroup_walk_tree_begin()
* can result both in a state that cgroup_walk_tree_end() is not needed
* and will sigsegv and in a state that cgroup_walk_tree_end() is needed
* to free allocated memory. Complete review is needed!
* @par Example of iterator usage:
* @code
* void *handle; // our iterator handle
* my_type item; // the data returned by the iterator
* int ret;
* ret = iterator_name_begin(&handle, &item);
* while (ret == 0) {
* // process the item here
* ret = iterator_name_begin(&handle, &item);
* }
* if (ret != ECGEOF) {
* // process the error here
* }
* iterator_name_end(&handle);
* @endcode
*
* @name Walk through control group filesystem
* @{
* This iterator returns all subgroups of given control group. It can be used
* to return all groups in given hierarchy, when root control group is provided.
*/
/**
* Type of the walk.
*/
enum cgroup_walk_type {
/**
* Pre-order directory walk, return a directory first and then its
* subdirectories.
* E.g. directories would be returned in this order:
* @code
* /
* /group
* /group/subgroup1
* /group/subgroup1/subsubgroup
* /group/subgroup2
* @endcode
*/
CGROUP_WALK_TYPE_PRE_DIR = 0x1,
/**
* Post-order directory walk, return subdirectories of a directory
* first and then the directory itself.
* E.g. directories would be returned in this order:
* @code
* /group/subgroup1/subsubgroup
* /group/subgroup1
* /group/subgroup2
* /group
* /
* @endcode
*/
CGROUP_WALK_TYPE_POST_DIR = 0x2,
};
/**
* Type of returned entity.
*/
enum cgroup_file_type {
CGROUP_FILE_TYPE_FILE, /**< File. */
CGROUP_FILE_TYPE_DIR, /**< Directory. */
CGROUP_FILE_TYPE_OTHER, /**< Directory. @todo really? */
};
/**
* Information about found directory (= a control group).
*/
struct cgroup_file_info {
/** Type of the entity. */
enum cgroup_file_type type;
/** Name of the entity. */
const char *path;
/** Name of its parent. */
const char *parent;
/**
* Full path to the entity. To get path relative to the root of the
* walk, you must store its @c full_path (or its length)
* and calculate the relative path by yourself.
*/
const char *full_path;
/**
* Depth of the entity, how many directories below the root of
* walk it is.
*/
short depth;
};
/**
* Walk through the directory tree for the specified controller.
* The directory representing @c base_path is returned in @c info.
* Use cgroup_walk_tree_set_flags() to specify, in which order should be next
* directories returned.
* @param controller Name of the controller, for which we want to walk
* the directory tree.
* @param base_path Begin walking from this path. Use "/" to walk through
* full hierarchy.
* @param depth The maximum depth to which the function should walk, 0
* implies all the way down.
* @param handle The handle to be used during iteration.
* @param info The info filled and returned about directory information.
* @param base_level Opaque integer which you must pass to subsequent
* cgroup_walk_tree_next.
* @todo why base_level is not hidden in **handle?
* @return #ECGEOF when there is no node.
*/
int cgroup_walk_tree_begin(const char *controller, const char *base_path, int depth,
void **handle, struct cgroup_file_info *info,
int *base_level);
/**
* Get the next directory in the walk.
* @param depth The maximum depth to which the function should walk, 0
* implies all the way down.
* @param handle The handle to be used during iteration.
* @param info The info filled and returned about the next directory.
* @param base_level Value of base_level returned by cgroup_walk_tree_begin().
* @return #ECGEOF when we are done walking through the nodes.
*/
int cgroup_walk_tree_next(int depth, void **handle,
struct cgroup_file_info *info, int base_level);
/**
* Release the iterator.
*/
int cgroup_walk_tree_end(void **handle);
/**
* Set the flags for walk_tree. Currently available flags are in
* #cgroup_walk_type enum.
* @param handle The handle of the iterator.
* @param flags
*/
int cgroup_walk_tree_set_flags(void **handle, int flags);
/**
* Read the value of the given variable for the specified
* controller and control group.
* The value is read up to newline character or at most max-1 characters,
* whichever comes first (i.e. similar to fgets()).
* @param controller Name of the controller for which stats are requested.
* @param path The path to control group, relative to hierarchy root.
* @param name is variable name.
* @param handle The handle to be used during iteration.
* @param buffer The buffer to read the value into.
* The buffer is always zero-terminated.
* @param max Maximal lenght of the buffer
* @return #ECGEOF when the stats file is empty.
*/
int cgroup_read_value_begin(const char * const controller, const char *path,
const char * const name, void **handle,
char *buffer, int max);
/**
* Read the next string from the given variable handle
* which is generated by cgroup_read_stats_begin() function.
* the value is read up to newline character or at most max-1 characters,
* whichever comes first (i.e. similar to fgets()) per
* cgroup_read_stats_next() call
* @param handle The handle to be used during iteration.
* @param data returned the string.
* @param buffer The buffer to read the value into.
* The buffer is always zero-terminated.
* @param max Maximal lenght of the buffer
* @return #ECGEOF when the iterator finishes getting the list of stats.
*/
int cgroup_read_value_next(void **handle, char *buffer, int max);
/**
* Release the iterator.
*/
int cgroup_read_value_end(void **handle);
/**
* @}
*
* @name Read group stats
* libcgroup's cgroup_get_value_string() reads only relatively short parametrs
* of a group. Use following functions to read @c stats parameter, which can
* be quite long.
*/
/**
* Maximum length of a value in stats file.
*/
#define CG_VALUE_MAX 100
/**
* One item in stats file.
*/
struct cgroup_stat {
char name[FILENAME_MAX];
char value[CG_VALUE_MAX];
};
/**
* Read the statistics values (= @c stats parameter) for the specified
* controller and control group. One line is returned per
* cgroup_read_stats_begin() and cgroup_read_stats_next() call.
* @param controller Name of the controller for which stats are requested.
* @param path The path to control group, relative to hierarchy root.
* @param handle The handle to be used during iteration.
* @param stat Returned first item in the stats file.
* @return #ECGEOF when the stats file is empty.
*/
int cgroup_read_stats_begin(const char *controller, const char *path, void **handle,
struct cgroup_stat *stat);
/**
* Read the next stat value.
* @param handle The handle to be used during iteration.
* @param stat Returned next item in the stats file.
* @return #ECGEOF when the iterator finishes getting the list of stats.
*/
int cgroup_read_stats_next(void **handle, struct cgroup_stat *stat);
/**
* Release the iterator.
*/
int cgroup_read_stats_end(void **handle);
/**
* @}
*
* @name List all tasks in a group
* Use following functions to read @c tasks file of a group.
* @{
*/
/**
* Read the tasks file to get the list of tasks in a cgroup.
* @param cgroup Name of the cgroup.
* @param controller Name of the cgroup subsystem.
* @param handle The handle to be used in the iteration.
* @param pid The pid read from the tasks file.
* @return #ECGEOF when the group does not contain any tasks.
*/
int cgroup_get_task_begin(const char *cgroup, const char *controller, void **handle,
pid_t *pid);
/**
* Read the next task value.
* @param handle The handle used for iterating.
* @param pid The variable where the value will be stored.
*
* @return #ECGEOF when the iterator finishes getting the list of tasks.
*/
int cgroup_get_task_next(void **handle, pid_t *pid);
/**
* Release the iterator.
*/
int cgroup_get_task_end(void **handle);
/**
* @}
*
* @name List mounted controllers
* Use following function to list mounted controllers and to see, how they
* are mounted together in hierarchies.
* Use cgroup_get_all_controller_begin() (see later) to list all controllers,
* including those which are not mounted.
* @{
*/
/**
* Information about mounted controller.
*/
struct cgroup_mount_point {
/** Name of the controller. */
char name[FILENAME_MAX];
/** Mount point of the controller. */
char path[FILENAME_MAX];
};
/**
* Read the mount table to give a list where each controller is
* mounted.
* @param handle The handle to be used for iteration.
* @param info The variable where the path to the controller is stored.
* @return #ECGEOF when no controllers are mounted.
*/
int cgroup_get_controller_begin(void **handle, struct cgroup_mount_point *info);
/**
* Read the next mounted controller.
* While walking through the mount table, the controllers are
* returned in order of their mount points, i.e. controllers mounted together
* in one hierarchy are returned next to each other.
* @param handle The handle to be used for iteration.
* @param info The variable where the path to the controller is stored.
* @return #ECGEOF when all controllers were already returned.
*/
int cgroup_get_controller_next(void **handle, struct cgroup_mount_point *info);
/**
* Release the iterator.
*/
int cgroup_get_controller_end(void **handle);
/**
* @}
*
* @name List all controllers
* Use following functions to list all controllers, including those which are
* not mounted. The controllers are returned in the same order as in
* /proc/cgroups file, i.e. mostly random.
*/
/**
* Detailed information about available controller.
*/
struct controller_data {
/** Controller name. */
char name[FILENAME_MAX];
/**
* Hierarchy ID. Controllers with the same hierarchy ID
* are mounted together as one hierarchy. Controllers with
* ID 0 are not currently mounted anywhere.
*/
int hierarchy;
/** Number of groups. */
int num_cgroups;
/** Enabled flag. */
int enabled;
};
/**
* Read the first of controllers from /proc/cgroups.
* @param handle The handle to be used for iteration.
* @param info The structure which will be filled with controller data.
*/
int cgroup_get_all_controller_begin(void **handle,
struct controller_data *info);
/**
* Read next controllers from /proc/cgroups.
* @param handle The handle to be used for iteration.
* @param info The structure which will be filled with controller data.
*/
int cgroup_get_all_controller_next(void **handle, struct controller_data *info);
/**
* Release the iterator
*/
int cgroup_get_all_controller_end(void **handle);
/**
* @}
*
* @name List all mount points of a controller.
* Use following functions to list all mount points of a hierarchy with given
* controller.
*/
/**
* Read the first mount point of the hierarchy with given controller.
* The first is the same as the mount point returned by
* cgroup_get_subsys_mount_point().
* @param handle The handle to be used for iteration.
* @param controller The controller name.
* @param path Buffer to fill the path into. The buffer must be at least
* FILENAME_MAX characters long.
*/
int cgroup_get_subsys_mount_point_begin(const char *controller, void **handle,
char *path);
/**
* Read next mount point of the hierarchy with given controller.
* @param handle The handle to be used for iteration.
* @param path Buffer to fill the path into. The buffer must be at least
* FILENAME_MAX characters long.
*/
int cgroup_get_subsys_mount_point_next(void **handle, char *path);
/**
* Release the iterator.
*/
int cgroup_get_subsys_mount_point_end(void **handle);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_ITERATORS_H */

View file

@ -1,158 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_LOG_H
#define _LIBCGROUP_LOG_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#endif
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup group_log 7. Logging
* @{
*
* @name Logging
* @{
* Libcgroup allows applications to register a callback function which
* libcgroup will call when it wants to log something. Each log message
* has associated a log level. As described in previous chapter, most libcgroup
* functions return an error code, which described root cause of the failure
* and log messages might provide further details about these failures and other
* notable events.
*
* @par
* The logging callback can be set at any time, but setting the callback before
* any other libcgroup function (including cgroup_init()) is highly recommended.
* If no logger is set before cgroup_init() is called, default logger is
* automatically set, logging CGROUP_LOG_ERROR messages to stdout.
*
* @par Setting log level
* Some of the functions below set the log level as integer.
* Application can set directly a value of enum #cgroup_log_level or use
* value <tt>-1</tt> to set the log level automatically. In this case, libcgroup
* inspects environment variable <tt>CGROUP_LOGLEVEL</tt> if it is set
* and contains any of these values: <tt>ERROR</tt>, <tt>WARNING</tt>,
* <tt>INFO</tt>, <tt>DEBUG</tt> or integer number representing value from
* enum #cgroup_log_level. If <tt>CGROUP_LOGLEVEL</tt> is not set or its value
* is not valid, <tt>CGROUP_LOG_ERROR</tt> is set as default log level.
*
* @par Example:
* Following short example shows custom libcgroup logger sending all log
* messages to <tt>stderr</tt>:
* @code
* static void my_logger(void *userdata, int level, const char *fmt, va_list ap)
* {
* vfprintf(stderr, fmt, ap);
* }
*
* int main(int argc, char **argv)
* {
* int ret;
*
* cgroup_set_logger(my_logger, -1, NULL);
* ret = cgroup_init();
* if (ret) {
* ...
* }
* ...
* @endcode
*/
/**
* Level of importance of a log message.
*/
enum cgroup_log_level {
/**
* Continue printing the log message, with the previous log level.
* Used to print log messages without the line break.
*/
CGROUP_LOG_CONT = 0,
/**
* Something serious happened and libcgroup failed to perform requested
* operation.
*/
CGROUP_LOG_ERROR,
/**
* Something bad happened but libcgroup recovered from the error.
*/
CGROUP_LOG_WARNING,
/**
* Something interesting happened and the message might be useful to the
* user.
*/
CGROUP_LOG_INFO,
/**
* Debugging messages useful to libcgroup developers.
*/
CGROUP_LOG_DEBUG,
};
typedef void (*cgroup_logger_callback)(void *userdata, int level,
const char *fmt, va_list ap);
/**
* Set libcgroup logging callback. All log messages with equal or lower log
* level will be sent to the application's callback. There can be only
* one callback logger set, the previous callback is replaced with the new one
* by calling this function.
* Use NULL as the logger callback to completely disable libcgroup logging.
*
* @param logger The callback.
* @param loglevel The log level. Use value -1 to automatically discover the
* level from CGROUP_LOGLEVEL environment variable.
* @param userdata Application's data which will be provided back to the
* callback.
*/
extern void cgroup_set_logger(cgroup_logger_callback logger, int loglevel,
void *userdata);
/**
* Set libcgroup logging to stdout. All messages with the given loglevel
* or below will be sent to standard output. Previous logger set by
* cgroup_set_logger() is replaced.
*
* @param loglevel The log level. Use value -1 to automatically discover the
* level from CGROUP_LOGLEVEL environment variable.
*/
extern void cgroup_set_default_logger(int loglevel);
/**
* Change current loglevel.
* @param loglevel The log level. Use value -1 to automatically discover the
* level from CGROUP_LOGLEVEL environment variable.
*/
extern void cgroup_set_loglevel(int loglevel);
/**
* Libcgroup log function. This is for applications which are too lazy to set
* up their own complex logging and miss-use libcgroup for that purpose.
* I.e. this function should be used only by simple command-line tools.
* This logging automatically benefits from CGROUP_LOGLEVEL env. variable.
*/
extern void cgroup_log(int loglevel, const char *fmt, ...);
/**
* Parse levelstr string for information about desired loglevel. The levelstr
* is usually a value of the CGROUP_LOGLEVEL environment variable.
* @param levelstr String containing desired loglevel.
*/
extern int cgroup_parse_log_level_str(const char *levelstr);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_LOG_H */

View file

@ -1,140 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_SYSTEMD_H
#define _LIBCGROUP_SYSTEMD_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifdef __cplusplus
extern "C" {
#endif
enum cgroup_systemd_mode_t {
CGROUP_SYSTEMD_MODE_FAIL = 0,
CGROUP_SYSTEMD_MODE_REPLACE,
CGROUP_SYSTEMD_MODE_ISOLATE,
CGROUP_SYSTEMD_MODE_IGNORE_DEPS,
CGROUP_SYSTEMD_MODE_IGNORE_REQS,
CGROUP_SYSTEMD_MODE_CNT,
CGROUP_SYSTEMD_MODE_DFLT = CGROUP_SYSTEMD_MODE_REPLACE
};
/**
* Options associated with creating a systemd scope
*/
struct cgroup_systemd_scope_opts {
/** should systemd delegate this cgroup or not. 1 == yes, 0 == no */
int delegated;
/** systemd behavior when the scope already exists */
enum cgroup_systemd_mode_t mode;
/** pid to be placed in the cgroup. if 0, libcgroup will create a dummy process */
pid_t pid;
};
/*
* cgroup systemd settings
*/
struct cgroup_systemd_opts {
char slice_name[FILENAME_MAX];
char scope_name[FILENAME_MAX];
int setdefault;
pid_t pid;
struct cgroup_systemd_opts *next;
};
/**
* Populate the scope options structure with default values
*
* @param opts Scope creation options structure instance. Must already be allocated
*
* @return 0 on success and > 0 on error
*/
int cgroup_set_default_scope_opts(struct cgroup_systemd_scope_opts * const opts);
/**
* Create a systemd scope under the specified slice
*
* @param scope_name Name of the scope, must end in .scope
* @param slice_name Name of the slice, must end in .slice
* @param opts Scope creation options structure instance
*
* @return 0 on success and > 0 on error
*/
int cgroup_create_scope(const char * const scope_name, const char * const slice_name,
const struct cgroup_systemd_scope_opts * const opts);
/**
* Create a systemd scope
*
* @param cgroup
* @param ignore_ownership When nonzero, all errors are ignored when setting owner of the group
* owner of the group and/or its tasks file
* @param opts Scope creation options structure instance
*
* @return 0 on success and > 0 on error
*
* @note The cgroup->name field should be of the form "foo.slice/bar.scope"
*/
int cgroup_create_scope2(struct cgroup *cgroup, int ignore_ownership,
const struct cgroup_systemd_scope_opts * const opts);
/**
* Parse the systemd default cgroup's relative path from
* /var/run/libcgroup/systemd and set it as default delegation cgroup
* path, if available.
*
* The path is relative to cgroup root (default: /sys/fs/cgroup)
*
* @return 1 if a valid default slice/scope is set, 0 in all other cases
*/
int cgroup_set_default_systemd_cgroup(void);
/**
* Parse the systemd delegation settings from the configuration file
* and allocate a new cgroup_systemd_opts object.
* This function internally calls cgroup_add_systemd_opts() to add the conf and
* value to the newly allocated cgroup_systemd_opts object.
*
* @param conf Name of the systemd delegate setting read from configuration file.
* @param value The value of the conf systemd delegate setting.
*
* @return 1 on success and 0 on error
*/
int cgroup_alloc_systemd_opts(const char * const conf, const char * const value);
/**
* Parse the systemd delegation settings from the configuration file
* and add the conf and value to the last allocated cgroup_systemd_opts object
* (tail) allocated by cgroup_alloc_systemd_opts()
*
* @param conf Name of the systemd delegate setting read from configuration file.
* @param value The value of the conf systemd delegate setting.
*
* @return 1 on success and 0 on error
*/
int cgroup_add_systemd_opts(const char * const conf, const char * const value);
/**
* Free the cgroup_systemd_opts objects allocated by cgroup_alloc_systemd_opts()
*/
void cgroup_cleanup_systemd_opts(void);
/*
* Write the specified slice and scope to the libcgroup systemd run file. This
* slice and scope will then be used as the default cgroup root. Subsequent
* libcgroup commands, cgget, etc., will utilize this slice and scope when
* constructing the libcgroup path
*
* @param slice Slice name, e.g. libcgroup.slice
* @param scope Scope name, e.g. database.scope
*/
int cgroup_write_systemd_default_cgroup(const char * const slice,
const char * const scope);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_SYSTEMD_H */

View file

@ -1,214 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
#ifndef _LIBCGROUP_TASKS_H
#define _LIBCGROUP_TASKS_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#include <libcgroup/groups.h>
#ifndef SWIG
#include <features.h>
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Flags for cgroup_change_cgroup_uid_gid(). */
enum cgflags {
/** Use cached rules, do not read rules from disk. */
CGFLAG_USECACHE = 0x01,
/** Use cached templates, do not read templates from disk. */
CGFLAG_USE_TEMPLATE_CACHE = 0x02,
};
/** Flags for cgroup_register_unchanged_process(). */
enum cgroup_daemon_type {
/**
* The daemon must not touch the given task, i.e. it never moves it
* to any controlgroup.
*/
CGROUP_DAEMON_UNCHANGE_CHILDREN = 0x1,
CGROUP_DAEMON_CANCEL_UNCHANGE_PROCESS = 0x2,
};
/**
* @defgroup group_tasks 4. Manipulation with tasks
* @{
*
* @name Simple task assignment
* @{
* Applications can use following functions to simply put a task into given
* control group and find a groups where given tasks is.
*/
/**
* Move current task (=thread) to given control group.
* @param cgroup Destination control group.
*/
int cgroup_attach_task(struct cgroup *cgroup);
/**
* Move given task (=thread) to given control group.
* @param cgroup Destination control group.
* @param tid The task to move.
*/
int cgroup_attach_task_pid(struct cgroup *cgroup, pid_t tid);
/**
* Changes the cgroup of a task based on the path provided. In this case,
* the user must already know into which cgroup the task should be placed and
* no rules will be parsed.
*
* @param path Name of the destination group.
* @param pid The task to move.
* @param controllers List of controllers.
*
* @todo should this function be really public?
*/
int cgroup_change_cgroup_path(const char *path, pid_t pid,
const char * const controllers[]);
/**
* Get the current control group path where the given task is.
* @param pid The task to find.
* @param controller The controller (hierarchy), where to find the task.
* @param current_path The path to control group, where the task has been found.
* The patch is relative to the root of the hierarchy. The caller must
* free this memory.
*/
int cgroup_get_current_controller_path(pid_t pid, const char *controller,
char **current_path);
/**
* @}
*
* @name Rules
* @{
* @c libcgroup can move tasks to control groups using simple rules, loaded
* from configuration file. See cgrules.conf man page to see format of the file.
* Following functions can be used to load these rules from a file.
*/
/**
* Initializes the rules cache and load it from /etc/cgrules.conf.
* @todo add parameter with the filename?
*/
int cgroup_init_rules_cache(void);
/**
* Reloads the rules list from /etc/cgrules.conf. This function
* is probably NOT thread safe (calls cgroup_parse_rules_config()).
*/
int cgroup_reload_cached_rules(void);
/**
* Print the cached rules table. This function should be called only after
* first calling cgroup_parse_config(), but it will work with an empty rule
* list.
* @param fp Destination file, where the rules will be printed.
*/
void cgroup_print_rules_config(FILE *fp);
/**
* @}
* @name Rule based task assignment
* @{
* @c libcgroup can move tasks to control groups using simple rules, loaded
* from configuration file. See cgrules.conf man page to see format of the file.
* Applications can move tasks to control groups based on these rules using
* following functions.
*/
/**
* Changes the cgroup of all running PIDs based on the rules in the config
* file. If a rules exists for a PID, then the PID is placed in the correct
* group.
*
* This function may be called after creating new control groups to move
* running PIDs into the newly created control groups.
* @return 0 on success, < 0 on error
*/
int cgroup_change_all_cgroups(void);
/**
* Changes the cgroup of a program based on the rules in the config file.
* If a rule exists for the given UID, GID or PROCESS NAME, then the given
* PID is placed into the correct group. By default, this function parses
* the configuration file each time it is called.
*
* The flags can alter the behavior of this function:
* CGFLAG_USECACHE: Use cached rules instead of parsing the config file
* CGFLAG_USE_TEMPLATE_CACHE: Use cached templates instead of
* parsing the config file
*
* This function may NOT be thread safe.
* @param uid The UID to match.
* @param gid The GID to match.
* @param procname The PROCESS NAME to match.
* @param pid The PID of the process to move.
* @param flags Bit flags to change the behavior, as defined in enum #cgflags.
* @todo Determine thread-safeness and fix of not safe.
*/
int cgroup_change_cgroup_flags(uid_t uid, gid_t gid,
const char *procname, pid_t pid, int flags);
/**
* Changes the cgroup of a program based on the rules in the config file. If a
* rule exists for the given UID or GID, then the given PID is placed into the
* correct group. By default, this function parses the configuration file each
* time it is called.
*
* This function may NOT be thread safe.
* @param uid The UID to match.
* @param gid The GID to match.
* @param pid The PID of the process to move.
* @param flags Bit flags to change the behavior, as defined in enum #cgflags.
* @todo Determine thread-safeness and fix if not safe.
*/
int cgroup_change_cgroup_uid_gid_flags(uid_t uid, gid_t gid,
pid_t pid, int flags);
/**
* Provides backwards-compatibility with older versions of the API. This
* function is deprecated, and cgroup_change_cgroup_uid_gid_flags() should be
* used instead. In fact, this function simply calls the newer one with flags
* set to 0 (none).
* @param uid The UID to match.
* @param gid The GID to match.
* @param pid The PID of the process to move.
*/
int cgroup_change_cgroup_uid_gid(uid_t uid, gid_t gid, pid_t pid);
/**
* @}
* @name Communication with cgrulesengd daemon
* @{
* Users can use cgrulesengd daemon to move tasks to groups based on the rules
* automatically when they change their UID, GID or executable name.
* The daemon allows tasks to be 'sticky', i.e. all rules are ignored for these
* tasks and the daemon never moves them.
*/
/**
* Register the unchanged process to a cgrulesengd daemon. This process
* is never moved to another control group by the daemon.
* If the daemon does not work, this function returns 0 as success.
* @param pid The task id.
* @param flags Bit flags to change the behavior, as defined in
* #cgroup_daemon_type
*/
int cgroup_register_unchanged_process(pid_t pid, int flags);
/**
* @}
* @}
*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_TASKS_H */

View file

@ -1,61 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
/**
* Libcgroup tools header file
*
* Copyright (c) 2021-2022 Oracle and/or its affiliates.
* Author: Tom Hromatka <tom.hromatka@oracle.com>
*/
#ifndef _LIBCGROUP_TOOLS_H
#define _LIBCGROUP_TOOLS_H
#ifndef _LIBCGROUP_H_INSIDE
#error "Only <libcgroup.h> should be included directly."
#endif
#ifndef SWIG
#include <features.h>
#include <sys/types.h>
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* Read the setting-value pairs in the cgroup sysfs for param cg.
* cgroup_cgxget() will perform the necessary conversions to match
* the "on-disk" format and then convert the data back to the
* requested version. If successful, cg will be populated with
* the setting-value pairs.
*
* @param cg Input/Output cgroup. Must be initialized and freed by the caller
* @param version Cgroup version of cg If set to CGROUP_UNK, the versions
* stored within each controller will be used. Otherwise this
* value will be used to override the cg param's controller
* versions
* @param ignore_unmappable Ignore failures due to settings that cannot be
* converted from one cgroup version to another
*/
int cgroup_cgxget(struct cgroup **cg,
enum cg_version_t version, bool ignore_unmappable);
/**
* Write the setting-value pairs in *cg to the cgroup sysfs.
* cgroup_cgxset() will perform the necessary conversions to match the
* "on-disk" format prior to writing to the cgroup sysfs.
*
* @param cg cgroup instance that will be written to the cgroup sysfs
* @param version Cgroup version of *cg
* @param ignore_unmappable Ignore failures due to settings that cannot be
* converted from one cgroup version to another
*/
int cgroup_cgxset(const struct cgroup * const cg,
enum cg_version_t version, bool ignore_unmappable);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _LIBCGROUP_TOOLS_H */

File diff suppressed because it is too large Load diff

View file

@ -1,10 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libcgroup
Description: Control Group Configuration Library
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lcgroup
Cflags: -I${includedir}

View file

@ -1,264 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_code_coverage.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CODE_COVERAGE()
#
# DESCRIPTION
#
# Defines CODE_COVERAGE_CPPFLAGS, CODE_COVERAGE_CFLAGS,
# CODE_COVERAGE_CXXFLAGS and CODE_COVERAGE_LIBS which should be included
# in the CPPFLAGS, CFLAGS CXXFLAGS and LIBS/LIBADD variables of every
# build target (program or library) which should be built with code
# coverage support. Also defines CODE_COVERAGE_RULES which should be
# substituted in your Makefile; and $enable_code_coverage which can be
# used in subsequent configure output. CODE_COVERAGE_ENABLED is defined
# and substituted, and corresponds to the value of the
# --enable-code-coverage option, which defaults to being disabled.
#
# Test also for gcov program and create GCOV variable that could be
# substituted.
#
# Note that all optimisation flags in CFLAGS must be disabled when code
# coverage is enabled.
#
# Usage example:
#
# configure.ac:
#
# AX_CODE_COVERAGE
#
# Makefile.am:
#
# @CODE_COVERAGE_RULES@
# my_program_LIBS = ... $(CODE_COVERAGE_LIBS) ...
# my_program_CPPFLAGS = ... $(CODE_COVERAGE_CPPFLAGS) ...
# my_program_CFLAGS = ... $(CODE_COVERAGE_CFLAGS) ...
# my_program_CXXFLAGS = ... $(CODE_COVERAGE_CXXFLAGS) ...
#
# This results in a "check-code-coverage" rule being added to any
# Makefile.am which includes "@CODE_COVERAGE_RULES@" (assuming the module
# has been configured with --enable-code-coverage). Running `make
# check-code-coverage` in that directory will run the module's test suite
# (`make check`) and build a code coverage report detailing the code which
# was touched, then print the URI for the report.
#
# In earlier versions of this macro, CODE_COVERAGE_LDFLAGS was defined
# instead of CODE_COVERAGE_LIBS. They are both still defined, but use of
# CODE_COVERAGE_LIBS is preferred for clarity; CODE_COVERAGE_LDFLAGS is
# deprecated. They have the same value.
#
# This code was derived from Makefile.decl in GLib, originally licenced
# under LGPLv2.1+.
#
# LICENSE
#
# Copyright (c) 2012, 2016 Philip Withnall
# Copyright (c) 2012 Xan Lopez
# Copyright (c) 2012 Christian Persch
# Copyright (c) 2012 Paolo Borelli
# Copyright (c) 2012 Dan Winship
# Copyright (c) 2015 Bastien ROUCARIES
#
# This library is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or (at
# your option) any later version.
#
# This library is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#serial 20
AC_DEFUN([AX_CODE_COVERAGE],[
dnl Check for --enable-code-coverage
AC_REQUIRE([AC_PROG_SED])
# allow to override gcov location
AC_ARG_WITH([gcov],
[AS_HELP_STRING([--with-gcov[=GCOV]], [use given GCOV for coverage (GCOV=gcov).])],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=$with_gcov],
[_AX_CODE_COVERAGE_GCOV_PROG_WITH=gcov])
AC_MSG_CHECKING([whether to build with code coverage support])
AC_ARG_ENABLE([code-coverage],
AS_HELP_STRING([--enable-code-coverage],
[Whether to enable code coverage support]),,
enable_code_coverage=no)
AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
AC_MSG_RESULT($enable_code_coverage)
AS_IF([ test "$enable_code_coverage" = "yes" ], [
# check for gcov
AC_CHECK_TOOL([GCOV],
[$_AX_CODE_COVERAGE_GCOV_PROG_WITH],
[:])
AS_IF([test "X$GCOV" = "X:"],
[AC_MSG_ERROR([gcov is needed to do coverage])])
AC_SUBST([GCOV])
dnl Check if gcc is being used
AS_IF([ test "$GCC" = "no" ], [
AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
])
AC_CHECK_PROG([LCOV], [lcov], [lcov])
AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
AS_IF([ test -z "$LCOV" ], [
AC_MSG_ERROR([To enable code coverage reporting you must have lcov installed])
])
AS_IF([ test -z "$GENHTML" ], [
AC_MSG_ERROR([Could not find genhtml from the lcov package])
])
dnl Build the code coverage flags
dnl Define CODE_COVERAGE_LDFLAGS for backwards compatibility
CODE_COVERAGE_CPPFLAGS="-DNDEBUG"
CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_CXXFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
CODE_COVERAGE_LIBS="-lgcov"
CODE_COVERAGE_LDFLAGS="$CODE_COVERAGE_LIBS"
AC_SUBST([CODE_COVERAGE_CPPFLAGS])
AC_SUBST([CODE_COVERAGE_CFLAGS])
AC_SUBST([CODE_COVERAGE_CXXFLAGS])
AC_SUBST([CODE_COVERAGE_LIBS])
AC_SUBST([CODE_COVERAGE_LDFLAGS])
[CODE_COVERAGE_RULES_CHECK='
-$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k check
$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
']
[CODE_COVERAGE_RULES_CAPTURE='
$(code_coverage_v_lcov_cap)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(call code_coverage_sanitize,$(PACKAGE_NAME)-$(PACKAGE_VERSION))" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_OPTIONS)
$(code_coverage_v_lcov_ign)$(LCOV) $(code_coverage_quiet) $(addprefix --directory ,$(CODE_COVERAGE_DIRECTORY)) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_LCOV_SHOPTS) $(CODE_COVERAGE_LCOV_RMOPTS)
-@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
$(code_coverage_v_genhtml)LANG=C $(GENHTML) $(code_coverage_quiet) $(addprefix --prefix ,$(CODE_COVERAGE_DIRECTORY)) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
@echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
']
[CODE_COVERAGE_RULES_CLEAN='
clean: code-coverage-clean
distclean: code-coverage-clean
code-coverage-clean:
-$(LCOV) --directory $(top_builddir) -z
-rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
-find . \( -name "*.gcda" -o -name "*.gcno" -o -name "*.gcov" \) -delete
']
], [
[CODE_COVERAGE_RULES_CHECK='
@echo "Need to reconfigure with --enable-code-coverage"
']
CODE_COVERAGE_RULES_CAPTURE="$CODE_COVERAGE_RULES_CHECK"
CODE_COVERAGE_RULES_CLEAN=''
])
[CODE_COVERAGE_RULES='
# Code coverage
#
# Optional:
# - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
# Multiple directories may be specified, separated by whitespace.
# (Default: $(top_builddir))
# - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
# by lcov for code coverage. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
# - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
# reports to be created. (Default:
# $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
# - CODE_COVERAGE_BRANCH_COVERAGE: Set to 1 to enforce branch coverage,
# set to 0 to disable it and leave empty to stay with the default.
# (Default: empty)
# - CODE_COVERAGE_LCOV_SHOPTS_DEFAULT: Extra options shared between both lcov
# instances. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_LCOV_SHOPTS: Extra options to shared between both lcov
# instances. (Default: $CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
# - CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH: --gcov-tool pathtogcov
# - CODE_COVERAGE_LCOV_OPTIONS_DEFAULT: Extra options to pass to the
# collecting lcov instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
# - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the collecting lcov
# instance. (Default: $CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
# - CODE_COVERAGE_LCOV_RMOPTS_DEFAULT: Extra options to pass to the filtering
# lcov instance. (Default: empty)
# - CODE_COVERAGE_LCOV_RMOPTS: Extra options to pass to the filtering lcov
# instance. (Default: $CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
# - CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT: Extra options to pass to the
# genhtml instance. (Default: based on $CODE_COVERAGE_BRANCH_COVERAGE)
# - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
# instance. (Default: $CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT)
# - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
#
# The generated report will be titled using the $(PACKAGE_NAME) and
# $(PACKAGE_VERSION). In order to add the current git hash to the title,
# use the git-version-gen script, available online.
# Optional variables
CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
CODE_COVERAGE_BRANCH_COVERAGE ?=
CODE_COVERAGE_LCOV_SHOPTS_DEFAULT ?= $(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc lcov_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_LCOV_SHOPTS ?= $(CODE_COVERAGE_LCOV_SHOPTS_DEFAULT)
CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH ?= --gcov-tool "$(GCOV)"
CODE_COVERAGE_LCOV_OPTIONS_DEFAULT ?= $(CODE_COVERAGE_LCOV_OPTIONS_GCOVPATH)
CODE_COVERAGE_LCOV_OPTIONS ?= $(CODE_COVERAGE_LCOV_OPTIONS_DEFAULT)
CODE_COVERAGE_LCOV_RMOPTS_DEFAULT ?=
CODE_COVERAGE_LCOV_RMOPTS ?= $(CODE_COVERAGE_LCOV_RMOPTS_DEFAULT)
CODE_COVERAGE_GENHTML_OPTIONS_DEFAULT ?=\
$(if $(CODE_COVERAGE_BRANCH_COVERAGE),\
--rc genhtml_branch_coverage=$(CODE_COVERAGE_BRANCH_COVERAGE))
CODE_COVERAGE_GENHTML_OPTIONS ?= $(CODE_COVERAGE_GENHTML_OPTIONS_DEFAULTS)
CODE_COVERAGE_IGNORE_PATTERN ?=
code_coverage_v_lcov_cap = $(code_coverage_v_lcov_cap_$(V))
code_coverage_v_lcov_cap_ = $(code_coverage_v_lcov_cap_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_cap_0 = @echo " LCOV --capture"\
$(CODE_COVERAGE_OUTPUT_FILE);
code_coverage_v_lcov_ign = $(code_coverage_v_lcov_ign_$(V))
code_coverage_v_lcov_ign_ = $(code_coverage_v_lcov_ign_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_lcov_ign_0 = @echo " LCOV --remove /tmp/*"\
$(CODE_COVERAGE_IGNORE_PATTERN);
code_coverage_v_genhtml = $(code_coverage_v_genhtml_$(V))
code_coverage_v_genhtml_ = $(code_coverage_v_genhtml_$(AM_DEFAULT_VERBOSITY))
code_coverage_v_genhtml_0 = @echo " GEN " $(CODE_COVERAGE_OUTPUT_DIRECTORY);
code_coverage_quiet = $(code_coverage_quiet_$(V))
code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
code_coverage_quiet_0 = --quiet
# sanitizes the test-name: replaces with underscores: dashes and dots
code_coverage_sanitize = $(subst -,_,$(subst .,_,$(1)))
# Use recursive makes in order to ignore errors during check
check-code-coverage:'"$CODE_COVERAGE_RULES_CHECK"'
# Capture code coverage data
code-coverage-capture: code-coverage-capture-hook'"$CODE_COVERAGE_RULES_CAPTURE"'
# Hook rule executed before code-coverage-capture, overridable by the user
code-coverage-capture-hook:
'"$CODE_COVERAGE_RULES_CLEAN"'
GITIGNOREFILES ?=
GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
A''M_DISTCHECK_CONFIGURE_FLAGS ?=
A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
']
AC_SUBST([CODE_COVERAGE_RULES])
m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([CODE_COVERAGE_RULES])])
])

View file

@ -1,2 +0,0 @@
DIST_SUBDIRS = config c python cmdline
SUBDIRS = $(DIST_SUBDIRS)

View file

@ -1,33 +0,0 @@
AM_CPPFLAGS = -I$(top_srcdir)/include
LDADD = $(top_builddir)/src/.libs/libcgroup.la
if WITH_SAMPLES
noinst_PROGRAMS = setuid walk_test read_stats walk_task get_controller \
get_mount_point proctest get_all_controller \
get_variable_names test_named_hierarchy \
get_procs wrapper_test logger empty_cgroup_v2 \
get_setup_mode
if WITH_SYSTEMD
noinst_PROGRAMS += create_systemd_scope
endif
setuid_SOURCES=setuid.c
walk_test_SOURCES=walk_test.c
read_stats_SOURCES=read_stats.c
walk_task_SOURCES=walk_task.c
get_controller_SOURCES=get_controller.c
get_mount_point_SOURCES=get_mount_point.c
proctest_SOURCES=proctest.c
get_all_controller_SOURCES=get_all_controller.c
get_variable_names_SOURCES=get_variable_names.c
test_named_hierarchy_SOURCES=test_named_hierarchy.c
get_procs_SOURCES=get_procs.c
wrapper_test_SOURCES=wrapper_test.c
logger_SOURCES=logger.c
empty_cgroup_v2_SOURCES=empty_cgroup_v2.c
get_setup_mode_SOURCES=get_setup_mode.c
create_systemd_scope_SOURCES=create_systemd_scope.c
endif

View file

@ -1,613 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/**
* Sample program that shows how to use libcgroup to create a systemd scope
*
* This program is designed to meet the requirements outlined in the systemd
* cmdline example [1] via the libcgroup C APIs.
*
* [1] https://github.com/libcgroup/libcgroup/blob/main/samples/cmdline/systemd-with-idle-process.md
*
* Copyright (c) 2023 Oracle and/or its affiliates.
* Author: Tom Hromatka <tom.hromatka@oracle.com>
*/
/*
* To compile and link this program:
* (From the root of the libcgroup source code directory)
* $ ./bootstrap
* $ ./configure --sysconfdir=/etc --localstatedir=/var \
* --enable-opaque-hierarchy="name=systemd" --enable-systemd \
* --enable-python --enable-samples
* $ make
*
* Add the libcgroup idle thread to your PATH. (Some distros restrict the
* modification of the $PATH environment variable when invoking sudo, so you
* will need to manually copy the executable to your path.)
* $ sudo cp src/libcgroup_systemd_idle_thread /a/path/in/your/sudo/path
*
* To run this program:
* $ # Note that there are more options. Run `create_systemd_scope -h` for more info
* $ sudo LD_LIBRARY_PATH=src/.libs ./samples/c/create_systemd_scope \
* --slice <yourslicename> --scope <yourscopename>
*/
/*
*/
#include <libcgroup.h>
#include <sys/wait.h>
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#define TMP_CGNAME "tmp"
#define HIGH_CGNAME "high-priority"
#define MED_CGNAME "medium-priority"
#define LOW_CGNAME "low-priority"
struct example_opts {
char slice[FILENAME_MAX];
char scope[FILENAME_MAX];
struct cgroup_systemd_scope_opts systemd_opts;
bool debug;
};
static const struct option long_opts[] = {
{"delegated", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"pid", required_argument, NULL, 'p'},
{"scope", required_argument, NULL, 's'},
{"slice", required_argument, NULL, 't'},
{"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};
static void usage(const char * const program_name)
{
printf("Usage: %s -s <scope> -t <slice> [-p <pid>]\n", program_name);
printf("Create a systemd scope using the libcgroup C APIs\n");
printf(" -d, --delegated Instruct systemd to create a delegated scope\n");
printf(" -p, --pid PID to be placed in the scope, if not provided,\n");
printf(" libcgroup will place a default idle PID in the scope\n");
printf(" -s, --scope Scope name, must end in .scope\n");
printf(" -t, --slice Slice name, must end in .slice\n");
printf(" -v, --verbose Enable libcgroup debug messages\n");
}
static int parse_opts(int argc, char *argv[], struct example_opts * const opts)
{
int c;
while ((c = getopt_long(argc, argv, "hs:t:p:dv", long_opts, NULL)) > 0) {
switch (c) {
case 'd':
opts->systemd_opts.delegated = true;
break;
case 'h':
usage(argv[0]);
exit(0);
case 'p':
opts->systemd_opts.pid = atoi(optarg);
if (opts->systemd_opts.pid <= 1) {
usage(argv[0]);
exit(1);
}
break;
case 's':
strncpy(opts->scope, optarg, FILENAME_MAX - 1);
break;
case 't':
strncpy(opts->slice, optarg, FILENAME_MAX - 1);
break;
case 'v':
opts->debug = true;
break;
default:
usage(argv[0]);
exit(1);
break;
}
}
return 0;
}
static int create_scope(const struct example_opts * const opts)
{
int ret;
printf("\n----------------------------------------------------------------\n");
printf("Creating systemd scope, %s/%s,\n", opts->slice, opts->scope);
if (opts->systemd_opts.pid > 1)
printf("and placing PID, %d, in the scope\n", opts->systemd_opts.pid);
else
printf("and libcgroup will place an idle process in the scope\n");
printf("----------------------------------------------------------------\n\n");
ret = cgroup_create_scope(opts->scope, opts->slice, &opts->systemd_opts);
if (ret == ECGINVAL) {
printf("An invalid parameter was passed into cgroup_create_scope()\n"
"Check your scope name, slice name, and systemd options carefully\n");
goto error;
} else if (ret == ECGOTHER) {
printf("Libcgroup typically returns ECGOTHER when a system call fails.\n"
"These failures could be caused by being out of memory, lack of\n"
"permissions, etc. Enabling libcgroup debug messages may help\n"
"root cause the issue; pass in '-v' to this program\n");
printf("The failing system call returned an errno of %d\n",
cgroup_get_last_errno());
goto error;
} else if (ret > 0) {
printf("An unspecified error occurred - likely in the formation or\n"
"sending/receiving of the message to systemd to create the scope.\n"
"Ensure that this application has the requisite permissions and\n"
"capabilities to create a scope. Enabling libcgroup debug\n"
"messages may help root cause the failing instruction; pass in\n"
"'-v' to this program\n");
printf("Libcgroup returned %d\n", ret);
goto error;
}
/*
* Counterintuitively, this function returns 1 on success
*/
ret = cgroup_write_systemd_default_cgroup(opts->slice, opts->scope);
if (ret != 1) {
printf("Failed to set the libcgroup default scope/slice: %d: %s\n",
ret, cgroup_strerror(ret));
ret = ECGFAIL;
goto error;
}
/*
* cgroup_set_default_systemd_cgroup() will return 1 if a default slice/scope are
* set, and will return 0 otherwise. Ensure that a default slice/scope are set.
* This is critical because subsequent code in this example is assuming a default,
* and if the default is not set, then calls will be operating on the root cgroup.
*/
ret = cgroup_set_default_systemd_cgroup();
if (ret != 1) {
printf("The default slice/scope are not properly set\n");
ret = ECGFAIL;
goto error;
}
ret = 0;
error:
return ret;
}
static int create_tmp_cgroup(const struct example_opts * const opts)
{
struct cgroup *cg;
int ret = 0;
cg = cgroup_new_cgroup(TMP_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
goto error;
}
ret = cgroup_create_cgroup(cg, 1);
if (ret) {
printf("Failed to write the cgroup to /sys/fs/cgroup: %d: %s\n",
ret, cgroup_strerror(ret));
goto error;
}
error:
if (cg)
cgroup_free(&cg);
return ret;
}
static int move_pids_to_tmp_cgroup(const struct example_opts * const opts)
{
struct cgroup *cg = NULL;
int ret, pid_cnt, i;
pid_t *pids = NULL;
int saved_ret = 0;
/*
* Since we told libcgroup that our slice and scope are the default, we can
* operate with that as our "root" directory. If we hadn't set them as the
* default, then we would have had to build up the relative path -
* <slice>/<scope>.
*/
ret = cgroup_get_procs("/", NULL, &pids, &pid_cnt);
if (ret) {
printf("Failed to get the pids in %s: %d: %s\n", opts->scope,
ret, cgroup_strerror(ret));
goto error;
}
cg = cgroup_new_cgroup(TMP_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
goto error;
}
for (i = 0; i < pid_cnt; i++) {
ret = cgroup_attach_task_pid(cg, pids[i]);
if (ret) {
printf("Failed to attach pid %d to %s\n", pids[i], TMP_CGNAME);
/*
* Instead of failing, let's save off the return code and continue
* moving processes to the new cgroup. Perhaps the failing PID was
* killed between when we read cgroup.procs and when we tried to
* move it
*/
saved_ret = ret;
}
}
error:
if (pids)
free(pids);
if (cg)
cgroup_free(&cg);
if (ret == 0 && saved_ret)
ret = saved_ret;
return ret;
}
static int create_high_priority_cgroup(const struct example_opts * const opts)
{
struct cgroup_controller *ctrl;
struct cgroup *cg;
int ret = 0;
cg = cgroup_new_cgroup(HIGH_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
ret = ECGFAIL;
goto error;
}
ctrl = cgroup_add_controller(cg, "cpu");
if (!ctrl) {
printf("Failed to add the cpu controller to the %s cgroup struct\n",
HIGH_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "cpu.weight", "600");
if (ret) {
printf("Failed to set %s's cpu.weight: %d: %s\n", HIGH_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ctrl = cgroup_add_controller(cg, "memory");
if (!ctrl) {
printf("Failed to add the memory controller to the %s cgroup struct\n",
HIGH_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "memory.low", "1G");
if (ret) {
printf("Failed to set %s's memory.low: %d: %s\n", HIGH_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ret = cgroup_create_cgroup(cg, 0);
if (ret) {
printf("Failed to write the %s cgroup to /sys/fs/cgroup: %d: %s\n",
HIGH_CGNAME, ret, cgroup_strerror(ret));
goto error;
}
error:
if (cg)
cgroup_free(&cg);
return ret;
}
static int create_medium_priority_cgroup(const struct example_opts * const opts)
{
struct cgroup_controller *ctrl;
struct cgroup *cg;
int ret = 0;
cg = cgroup_new_cgroup(MED_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
ret = ECGFAIL;
goto error;
}
ctrl = cgroup_add_controller(cg, "cpu");
if (!ctrl) {
printf("Failed to add the cpu controller to the %s cgroup struct\n",
MED_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "cpu.weight", "300");
if (ret) {
printf("Failed to set %s's cpu.weight: %d: %s\n", MED_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ctrl = cgroup_add_controller(cg, "memory");
if (!ctrl) {
printf("Failed to add the memory controller to the %s cgroup struct\n",
MED_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "memory.high", "3G");
if (ret) {
printf("Failed to set %s's memory.high: %d: %s\n", MED_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ret = cgroup_create_cgroup(cg, 0);
if (ret) {
printf("Failed to write the %s cgroup to /sys/fs/cgroup: %d: %s\n",
MED_CGNAME, ret, cgroup_strerror(ret));
goto error;
}
error:
if (cg)
cgroup_free(&cg);
return ret;
}
static int create_low_priority_cgroup(const struct example_opts * const opts)
{
struct cgroup_controller *ctrl;
struct cgroup *cg;
int ret = 0;
cg = cgroup_new_cgroup(LOW_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
ret = ECGFAIL;
goto error;
}
ctrl = cgroup_add_controller(cg, "cpu");
if (!ctrl) {
printf("Failed to add the cpu controller to the %s cgroup struct\n",
LOW_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "cpu.weight", "100");
if (ret) {
printf("Failed to set %s's cpu.weight: %d: %s\n", LOW_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ctrl = cgroup_add_controller(cg, "memory");
if (!ctrl) {
printf("Failed to add the memory controller to the %s cgroup struct\n",
LOW_CGNAME);
ret = ECGFAIL;
goto error;
}
ret = cgroup_set_value_string(ctrl, "memory.max", "2G");
if (ret) {
printf("Failed to set %s's memory.high: %d: %s\n", LOW_CGNAME, ret,
cgroup_strerror(ret));
goto error;
}
ret = cgroup_create_cgroup(cg, 0);
if (ret) {
printf("Failed to write the %s cgroup to /sys/fs/cgroup: %d: %s\n",
LOW_CGNAME, ret, cgroup_strerror(ret));
goto error;
}
error:
if (cg)
cgroup_free(&cg);
return ret;
}
static int create_process(pid_t * const pid, const char * const cgname)
{
int ret = 0;
*pid = fork();
if (*pid < 0) {
printf("Failed to create the process: %d\n", errno);
ret = ECGFAIL;
goto error;
} else if (*pid == 0) {
/*
* This is the child process. Move it to the requested cgroup
*/
ret = cgroup_change_cgroup_path(cgname, getpid(), NULL);
if (ret)
exit(0);
while (true)
sleep(10);
}
error:
if (ret)
*pid = -1;
return ret;
}
static int delete_tmp_cgroup(void)
{
struct cgroup *cg = NULL;
int ret, pid_cnt, i;
int saved_errno = 0;
pid_t *pids = NULL;
ret = cgroup_get_procs(TMP_CGNAME, NULL, &pids, &pid_cnt);
if (ret) {
printf("Failed to get the pids in %s: %d: %s\n", TMP_CGNAME,
ret, cgroup_strerror(ret));
goto error;
}
for (i = 0; i < pid_cnt; i++) {
ret = kill(pids[i], SIGTERM);
if (ret < 0) {
saved_errno = errno;
printf("Kill failed: %d\n", errno);
/*
* Do not bail out here as there may be other PIDS to process
*/
}
}
cg = cgroup_new_cgroup(TMP_CGNAME);
if (!cg) {
printf("Failed to allocate the cgroup struct. Are we out of memory?\n");
goto error;
}
ret = cgroup_delete_cgroup(cg, 1);
if (ret)
printf("Failed to delete the %s cgroup: %d: %s\n", TMP_CGNAME, ret,
cgroup_strerror(ret));
error:
if (pids)
free(pids);
if (cg)
cgroup_free(&cg);
if (ret == 0 && saved_errno)
ret = ECGFAIL;
return ret;
}
static void wait_for_child(pid_t pid)
{
int wstatus;
(void)waitpid(pid, &wstatus, 0);
if (WIFEXITED(wstatus))
printf("pid %d exited with status %d\n", pid, WEXITSTATUS(wstatus));
else if (WIFSIGNALED(wstatus))
printf("pid %d exited due to signal %d\n", pid, WTERMSIG(wstatus));
}
int main(int argc, char *argv[])
{
pid_t high_pid, med_pid, low_pid;
struct example_opts opts = {0};
int ret = 0;
if (argc < 3) {
usage(argv[0]);
exit(1);
}
ret = cgroup_set_default_scope_opts(&opts.systemd_opts);
if (ret) {
printf("Failed to set the default systemd options: %d\n", ret);
goto error;
}
ret = parse_opts(argc, argv, &opts);
if (ret) {
printf("Failed to parse the command line options: %d\n", ret);
goto error;
}
if (opts.debug)
cgroup_set_default_logger(CGROUP_LOG_DEBUG);
ret = cgroup_init();
if (ret)
goto error;
ret = create_scope(&opts);
if (ret)
goto error;
ret = create_tmp_cgroup(&opts);
if (ret)
goto error;
ret = move_pids_to_tmp_cgroup(&opts);
if (ret)
goto error;
ret = create_high_priority_cgroup(&opts);
if (ret)
goto error;
ret = create_medium_priority_cgroup(&opts);
if (ret)
goto error;
ret = create_low_priority_cgroup(&opts);
if (ret)
goto error;
ret = create_process(&high_pid, HIGH_CGNAME);
if (ret)
goto error;
ret = create_process(&med_pid, MED_CGNAME);
if (ret)
goto error;
ret = create_process(&low_pid, LOW_CGNAME);
if (ret)
goto error;
ret = delete_tmp_cgroup();
if (ret)
goto error;
printf("\n----------------------------------------------------------------\n");
printf("Cgroup setup completed successfully\n");
printf("\t* The scope %s was placed under slice %s\n", opts.scope, opts.slice);
printf("\t* Libcgroup initially placed an idle process in the scope,\n"
"\t but it has been removed by this program\n");
printf("\t* PID %d has been placed in the %s cgroup\n", high_pid, HIGH_CGNAME);
printf("\t* PID %d has been placed in the %s cgroup\n", med_pid, MED_CGNAME);
printf("\t* PID %d has been placed in the %s cgroup\n", low_pid, LOW_CGNAME);
printf("\nThis program will wait for the aforementioned child processes to\n"
"exit before exiting itself. Systemd will automatically delete the\n"
"scope when there are no longer any processes running within the.\n"
"scope. Systemd will not automatically delete the slice.\n");
printf("----------------------------------------------------------------\n\n");
wait_for_child(high_pid);
wait_for_child(med_pid);
wait_for_child(low_pid);
error:
return ret;
}

View file

@ -1,40 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/**
* Simple program to add empty cgroup v2
*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Author: Kamalesh babulal <kamalesh.baulal@oracle.com>
*/
#include <libcgroup.h>
#include <stdlib.h>
#include <stdio.h>
#define CGRP_NAME "empty_cgrp"
int main(int argc, char **argv)
{
struct cgroup *cgroup = NULL;
int ret = 0;
ret = cgroup_init();
if (ret) {
fprintf(stderr, "cgroup_init failed\n");
exit(1);
}
cgroup = cgroup_new_cgroup(CGRP_NAME);
if (!cgroup) {
fprintf(stderr, "Failed to allocate cgroup %s\n", CGRP_NAME);
exit(1);
}
ret = cgroup_create_cgroup(cgroup, 0);
if (ret)
fprintf(stderr, "Failed to create cgroup %s\n", CGRP_NAME);
cgroup_free(&cgroup);
return ret;
}

View file

@ -1,36 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
struct controller_data info;
void *handle;
int error;
error = cgroup_init();
if (error) {
printf("cgroup_init failed with %s\n", cgroup_strerror(error));
exit(1);
}
error = cgroup_get_all_controller_begin(&handle, &info);
while (error != ECGEOF) {
printf("Controller %10s %5d %5d %5d\n", info.name,
info.hierarchy, info.num_cgroups, info.enabled);
error = cgroup_get_all_controller_next(&handle, &info);
if (error && error != ECGEOF) {
printf("cgroup_get_controller_next failed with %s\n",
cgroup_strerror(error));
exit(1);
}
}
error = cgroup_get_all_controller_end(&handle);
return 0;
}

View file

@ -1,34 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
struct cgroup_mount_point info;
void *handle;
int error;
error = cgroup_init();
if (error) {
printf("cgroup_init failed with %s\n", cgroup_strerror(error));
exit(1);
}
error = cgroup_get_controller_begin(&handle, &info);
while (error != ECGEOF) {
printf("Controller %s is mounted at %s\n",
info.name, info.path);
error = cgroup_get_controller_next(&handle, &info);
if (error && error != ECGEOF) {
printf("cgroup_get_controller_next failed with %s",
cgroup_strerror(error));
exit(1);
}
}
error = cgroup_get_controller_end(&handle);
return 0;
}

View file

@ -1,50 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
{
char *mount_point;
char string[100];
int ret;
strcpy(string, "cpu");
ret = cgroup_init();
if (ret) {
printf("cgroup_init failed with %s\n", cgroup_strerror(ret));
exit(3);
}
ret = cgroup_get_subsys_mount_point(string, &mount_point);
if (ret) {
printf("get_mount_point failed with %s\n",
cgroup_strerror(ret));
exit(3);
}
printf("The mount point is %s\n", mount_point);
free(mount_point);
strcpy(string, "obviouslynonexistsubsys");
ret = cgroup_get_subsys_mount_point(string, &mount_point);
if (!ret) {
printf("get_mount_point failed as it got a ");
printf("non existent subsys\n");
exit(3);
}
if (ret == ECGROUPNOTEXIST) {
printf("get_mount_point worked as expected\n");
return 0;
}
printf("get_mount_point failed with %s\n", cgroup_strerror(ret));
return 3;
}

View file

@ -1,37 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <stdio.h>
/*
* Assumes the cgroup is already mounted at /cgroup/memory/a
* Assumes some processes are already in the cgroup
* Assumes it is the memory controller is mounted in at that point
*/
int main(void)
{
pid_t *pids;
int size;
int ret;
int i;
ret = cgroup_init();
if (ret) {
printf("FAIL: cgroup_init failed with %s\n",
cgroup_strerror(ret));
exit(3);
}
ret = cgroup_get_procs("a", "memory", &pids, &size);
if (ret) {
printf("FAIL: cgroup_get_procs failed with %s\n",
cgroup_strerror(ret));
exit(3);
}
for (i = 0; i < size; i++)
printf("%u\n", pids[i]);
return 0;
}

View file

@ -1,44 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/*
* Copyright (c) 2023 Oracle and/or its affiliates
*
* Author: Kamalesh Babulal <kamalesh.babulal@oracle.com>
*
* Description: This file contains the sample code to demonstrate usage of
* cgroup_setup_mode() API.
*/
#include <stdio.h>
#include <stdlib.h>
#include <libcgroup.h>
int main(void)
{
enum cg_setup_mode_t setup_mode;
int ret;
ret = cgroup_init();
if (ret) {
printf("cgroup_init failed with %s\n", cgroup_strerror(ret));
exit(1);
}
setup_mode = cgroup_setup_mode();
switch(setup_mode) {
case CGROUP_MODE_LEGACY:
printf("cgroup mode: Legacy\n");
break;
case CGROUP_MODE_HYBRID:
printf("cgroup mode: Hybrid\n");
break;
case CGROUP_MODE_UNIFIED:
printf("cgroup mode: Unified\n");
break;
default:
printf("cgroup mode: Unknown\n");
break;
}
return 0;
}

View file

@ -1,61 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include "../src/libcgroup-internal.h"
#include <libcgroup.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
struct cgroup_controller *group_controller = NULL;
struct cgroup *group = NULL;
char group_name[] = "/";
char *name;
int count;
int ret;
int i, j;
if (argc < 2) {
printf("no list of groups provided\n");
return -1;
}
ret = cgroup_init();
if (ret) {
printf("cgroup_init failed with %s\n", cgroup_strerror(ret));
exit(1);
}
group = cgroup_new_cgroup(group_name);
if (group == NULL) {
printf("cannot create group '%s'\n", group_name);
return -1;
}
ret = cgroup_get_cgroup(group);
if (ret != 0) {
printf("cannot read group '%s': %s\n",
group_name, cgroup_strerror(ret));
}
for (i = 1; i < argc; i++) {
group_controller = cgroup_get_controller(group, argv[i]);
if (group_controller == NULL) {
printf("cannot find controller '%s' in group '%s'\n",
argv[i], group_name);
ret = -1;
continue;
}
count = cgroup_get_value_name_count(group_controller);
for (j = 0; j < count; j++) {
name = cgroup_get_value_name(group_controller, j);
if (name != NULL)
printf("%s\n", name);
}
}
return ret;
}

View file

@ -1,47 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/*
* Copyright Red Hat Inc., 2012
*
* Author: Jan Safranek <jsafrane@redhat.com>
*
* Description: This file contains the test code for libcgroup logging.
*/
#include "config.h"
#include "libcgroup.h"
#include "../src/libcgroup-internal.h"
#include <string.h>
#include <stdlib.h>
static void mylogger(void *userdata, int loglevel, const char *fmt, va_list ap)
{
printf("custom: ");
vprintf(fmt, ap);
}
int main(int argc, char **argv)
{
int loglevel = -1;
int custom = 0;
int i;
for (i = 1; i < argc; i++) {
if (strcmp("custom", argv[i]) == 0)
custom = 1;
else
loglevel = atoi(argv[i]);
}
if (custom)
cgroup_set_logger(mylogger, loglevel, NULL);
else
cgroup_set_default_logger(loglevel);
cgroup_dbg("DEBUG message\n");
cgroup_info("INFO message\n");
cgroup_warn("WARNING message\n");
cgroup_err("ERROR message\n");
return 0;
}

View file

@ -1,48 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/*
* Copyright NEC Soft Ltd. 2009
*
* Author: Ken'ichi Ohmichi <oomichi@mxs.nes.nec.co.jp>
*/
#include "../src/libcgroup-internal.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *procname;
pid_t pid;
uid_t uid;
gid_t gid;
int ret;
int i;
if (argc < 2) {
printf("Specify process-id.\n");
return 1;
}
printf(" Pid | Process name | Uid | Gid\n");
printf("-------+----------------------------------+-------+-------\n");
for (i = 1; i < argc; i++) {
pid = atoi(argv[i]);
ret = cgroup_get_uid_gid_from_procfs(pid, &uid, &gid);
if (ret) {
printf("%6d | ret = %d\n", pid, ret);
continue;
}
ret = cgroup_get_procname_from_procfs(pid, &procname);
if (ret) {
printf("%6d | ret = %d\n", pid, ret);
continue;
}
printf("%6d | %32s | %5d | %5d\n", pid, procname, uid, gid);
free(procname);
}
return 0;
}

View file

@ -1,86 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
int read_stats(char *path, char *controller)
{
struct cgroup_stat stat;
void *handle;
int ret;
ret = cgroup_read_stats_begin(controller, path, &handle, &stat);
if (ret != 0) {
fprintf(stderr, "stats read failed\n");
return -1;
}
printf("Stats for %s:\n", path);
printf("%s: %s", stat.name, stat.value);
while ((ret = cgroup_read_stats_next(&handle, &stat)) !=
ECGEOF) {
printf("%s: %s", stat.name, stat.value);
}
cgroup_read_stats_end(&handle);
printf("\n");
return 0;
}
int main(int argc, char *argv[])
{
struct cgroup_file_info info;
char cgroup_path[FILENAME_MAX];
char *controller;
int root_len;
void *handle;
int lvl;
int ret;
if (argc < 2) {
fprintf(stderr, "Usage %s: <controller name>\n",
argv[0]);
exit(EXIT_FAILURE);
}
controller = argv[1];
ret = cgroup_init();
if (ret != 0) {
fprintf(stderr, "init failed\n");
exit(EXIT_FAILURE);
}
ret = cgroup_walk_tree_begin(controller, "/", 0, &handle, &info, &lvl);
if (ret != 0) {
fprintf(stderr, "Walk failed\n");
exit(EXIT_FAILURE);
}
root_len = strlen(info.full_path) - 1;
strncpy(cgroup_path, info.path, FILENAME_MAX - 1);
ret = read_stats(cgroup_path, controller);
if (ret < 0)
exit(EXIT_FAILURE);
while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) !=
ECGEOF) {
if (info.type != CGROUP_FILE_TYPE_DIR)
continue;
strncpy(cgroup_path, info.full_path + root_len, FILENAME_MAX - 1);
strcat(cgroup_path, "/");
ret = read_stats(cgroup_path, controller);
if (ret < 0)
exit(EXIT_FAILURE);
}
cgroup_walk_tree_end(&handle);
return EXIT_SUCCESS;
}

View file

@ -1,74 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/*
* Copyright Red Hat Inc. 2008
*
* Author: Steve Olivieri <sjo@redhat.com>
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
/*
* This is just a simple program for changing a UID or a GID. Comment out
* whichever block you don't want to use.
*/
int main(int argc, char *argv[])
{
/* User data */
struct passwd *pwd;
/* UID of user */
uid_t uid;
/* Return codes */
int ret = 0;
if (argc < 2) {
printf("Usage: %s <uid_value>\n", argv[0]);
goto finished;
}
pwd = getpwnam(argv[1]);
if (!pwd) {
fprintf(stderr, "getpwnam() failed: %s\n",
strerror(errno));
ret = -errno;
goto finished;
}
uid = pwd->pw_uid;
fprintf(stdout, "Setting UID to %s (%d).\n", pwd->pw_name, uid);
ret = setuid(uid);
if (ret != 0) {
fprintf(stderr, "Call to setuid() failed with error: %s\n",
strerror(errno));
ret = -errno;
goto finished;
}
// while(1) {
// grp = getgrnam("root");
// gid = grp->gr_gid;
// fprintf(stdout, "Setting GID to %s (%d).\n",
// grp->gr_name, gid);
// if ((ret = setgid(gid))) {
// fprintf(stderr, "Call to setgid() failed with error:"
// " %s\n", strerror(errno));
// ret = -errno;
// goto finished;
// }
// }
while (1)
usleep(3000000);
finished:
return ret;
}

View file

@ -1,929 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
/*
* Copyright IBM Corporation. 2008
*
* Author: Sudhir Kumar <skumar@linux.vnet.ibm.com>
*
* Description: This file contains the functions for testing libcgroup apis.
*/
#include "libcgrouptest.h"
/* The messages that may be useful to the user */
char info[][SIZE] = {
" Parameter nullcgroup\n", /* NULLGRP */
" Parameter commoncgroup\n", /* COMMONGRP */
" Parameter not created group\n", /* NOTCRTDGRP */
" Parameter same cgroup\n", /* SAMEGRP */
" Task found in group/s\n", /* TASKINGRP */
" Task not found in group/s\n", /* TASKNOTINGRP */
" Task not found in all groups\n", /* TASKNOTINANYGRP */
" group found in filesystem\n", /* GRPINFS */
" group not found in filesystem\n", /* GRPNOTINFS */
" group found under both controllers\n", /* GRPINBOTHCTLS */
" group not found under second controller\n", /* GRPNOTIN2NDCTL */
" group not found under first controller\n", /* GRPNOTIN1STCTL */
" group modified under both controllers\n", /* GRPMODINBOTHCTLS */
" group not modified under second controller\n",/* GRPNOTMODIN2NDCTL */
" group not modified under any controller\n", /* GRPNOTMODINANYCTL */
" Group deleted from filesystem\n", /* GRPDELETEDINFS */
" Group not deleted from filesystem\n", /* GRPNOTDELETEDINFS */
" Group not deleted globally\n", /* GRPNOTDELETEDGLOBALY */
/* In case there is no extra info messages to be printed */
"\n", /* NOMESSAGE */
};
/**
* Tests the cgroup_init_cgroup() api under different scenarios
* @param retcode error code in case any error is expected from api
* @param i the test number
*/
void test_cgroup_init(int retcode, int i)
{
int retval;
retval = cgroup_init();
if (retval == retcode)
message(i, PASS, "init()\t", retval, info[NOMESSAGE]);
else
message(i, FAIL, "init()", retval, info[NOMESSAGE]);
}
/**
* Tests the cgroup_attach_cgroup() api under different scenarios
* @param retcode error code in case any error is expected from api
* @param cgrp the group to assign the task to
* @param group1 the name of the group under first (single) mountpoint
* @param group2 the name of the group under 2nd moutpoint for multimount
* @param i the test number
* @param k the message enum number to print the useful message
*/
void test_cgroup_attach_task(int retcode, struct cgroup *cgrp,
const char *group1, const char *group2, pid_t pid,
int k, int i)
{
char tasksfile[FILENAME_MAX], tasksfile2[FILENAME_MAX];
int retval;
/* Check, In case some error is expected due to a negative scenario */
if (retcode) {
if (pid)
retval = cgroup_attach_task_pid(cgrp, pid);
else
retval = cgroup_attach_task(cgrp);
if (retval == retcode)
message(i, PASS, "attach_task()", retval, info[k]);
else
message(i, FAIL, "attach_task()", retval, info[k]);
return;
}
/* Now there is no error and it is a genuine call */
if (pid)
retval = cgroup_attach_task_pid(cgrp, pid);
else
retval = cgroup_attach_task(cgrp);
/* API returned success, so perform check */
if (retval == 0) {
build_path(tasksfile, mountpoint, group1, "tasks");
if (check_task(tasksfile, 0)) {
if (fs_mounted == 2) {
/* multiple mounts */
build_path(tasksfile2, mountpoint2,
group2, "tasks");
if (check_task(tasksfile2, 0)) {
message(i, PASS, "attach_task()",
retval, info[TASKINGRP]);
} else {
message(i, FAIL, "attach_task()",
retval, info[TASKNOTINANYGRP]);
}
} else {
/* single mount */
message(i, PASS, "attach_task()",
retval, info[TASKINGRP]);
}
} else {
message(i, FAIL, "attach_task()", retval,
info[TASKNOTINGRP]);
}
} else {
message(i, FAIL, "attach_task()", retval, (char *)"\n");
}
}
/**
* This function creates a cgroup data structure
* This function is a bit ugly for now and need to be changed
* @param ctl the controller under which group is to be created
* @param grpname the name of the group
* @param value_type which value out of four types
* @param struct cval the control value structure
* @param struct ids the permissions struct
* @param the test number
*/
struct cgroup *create_new_cgroup_ds(int ctl, const char *grpname,
int value_type, struct cntl_val_t cval,
struct uid_gid_t ids, int i)
{
char controller_name[FILENAME_MAX], control_file[FILENAME_MAX];
char group[FILENAME_MAX];
int retval;
strncpy(group, grpname, sizeof(group) - 1);
retval = set_controller(ctl, controller_name, control_file);
if (retval) {
fprintf(stderr, "Setting controller failled\n");
return NULL;
}
switch (ctl) {
/*
* control values are controller specific, so will be set
* accordingly from the config file
*/
case CPU:
strncpy(cval.val_string, "260000", sizeof(cval.val_string));
break;
case MEMORY:
strncpy(cval.val_string, "7000064", sizeof(cval.val_string));
break;
/* To be added for other controllers */
default:
printf("Invalid controller name passed. Setting control ");
printf("value failed. Dependent tests may fail\n");
return NULL;
}
return new_cgroup(group, controller_name, control_file,
value_type, cval, ids, i);
}
/**
* Tests the cgroup_create_cgroup() api under different scenarios
* @param retcode error code in case any error is expected from api
* @param cgrp the group to be created
* @param name the name of the group
* @param common to test if group will be created under one or both mountpoints
* @param mpnt to test if group under mountpoint or mountpoint2
* @param ign parameter for api if to ignore the ownership
* @param the test number
*/
void test_cgroup_create_cgroup(int retcode, struct cgroup *cgrp,
const char *name, int common, int mpnt,
int ign, int i)
{
char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX];
int retval;
/* Check, In case some error is expected due to a negative scenario */
if (retcode) {
retval = cgroup_create_cgroup(cgrp, ign);
if (retval == retcode)
message(i, PASS, "create_cgroup()", retval,
info[NOMESSAGE]);
else
message(i, FAIL, "create_cgroup()", retval,
info[NOMESSAGE]);
return;
}
/* Now there is no error and it is a genuine call */
retval = cgroup_create_cgroup(cgrp, ign);
if (retval) {
message(i, FAIL, "create_cgroup()", retval, info[NOMESSAGE]);
return;
}
/* Let us now check if the group exist in file system */
if (!common) {
/* group only under one mountpoint */
if (mpnt == 1)
/* group under mountpoint */
build_path(path1_group, mountpoint, name, NULL);
else
/* group under mountpoint2 */
build_path(path1_group, mountpoint2, name, NULL);
if (group_exist(path1_group) == 0)
message(i, PASS, "create_cgroup()", retval,
info[GRPINFS]);
else
message(i, FAIL, "create_cgroup()", retval,
info[GRPNOTINFS]);
/* group under both mountpoints */
} else {
/* check if the group exists under both controllers */
build_path(path1_group, mountpoint, name, NULL);
if (group_exist(path1_group) == 0) {
build_path(path2_group, mountpoint2, name, NULL);
if (group_exist(path2_group) == 0)
message(i, PASS, "create_cgroup()",
retval, info[GRPINBOTHCTLS]);
else
message(i, FAIL, "create_cgroup()",
retval, info[GRPNOTIN2NDCTL]);
} else {
message(i, FAIL, "create_cgroup()", retval,
info[GRPNOTIN1STCTL]);
}
}
}
/**
* Tests the cgroup_delete_cgroup() api under different scenarios
* @param retcode error code in case any error is expected from api
* @param cgrp the group to be deleted
* @param name the name of the group
* @param common to test if group was created under one or both mountpoints
* @param mpnt to test if group under mountpoint or mountpoint2
* @param ign parameter for api if to ignore the ownership
* @param the test number
*/
void test_cgroup_delete_cgroup(int retcode, struct cgroup *cgrp,
const char *name, int common, int mpnt, int ign,
int i)
{
char path1_group[FILENAME_MAX], path2_group[FILENAME_MAX];
int retval;
/* Check, In case some error is expected due to a negative scenario */
if (retcode) {
retval = cgroup_delete_cgroup(cgrp, ign);
if (retval == retcode)
message(i, PASS, "delete_cgroup()", retval,
info[NOMESSAGE]);
else
message(i, FAIL, "delete_cgroup()", retval,
info[NOMESSAGE]);
return;
}
/* Now there is no error and it is a genuine call */
retval = cgroup_delete_cgroup(cgrp, ign);
if (retval) {
message(i, FAIL, "delete_cgroup()", retval, info[NOMESSAGE]);
return;
}
/* Let us now check if the group has been deleted from file system */
if (!common) {
/* check only under one mountpoint */
if (mpnt == 1)
/* check group under mountpoint */
build_path(path1_group, mountpoint, name, NULL);
else
/* check group under mountpoint2 */
build_path(path1_group, mountpoint2, name, NULL);
if (group_exist(path1_group) == ENOENT)
message(i, PASS, "delete_cgroup()", retval,
info[GRPDELETEDINFS]);
else
message(i, FAIL, "delete_cgroup()", retval,
info[GRPNOTDELETEDINFS]);
} else {
/* check group under both mountpoints */
/* Check if the group deleted under both mountpoints */
build_path(path1_group, mountpoint, name, NULL);
if (group_exist(path1_group) == ENOENT) {
build_path(path2_group, mountpoint2, name, NULL);
if (group_exist(path2_group) == ENOENT)
message(i, PASS, "delete_cgroup()",
retval, info[GRPDELETEDINFS]);
else
message(i, FAIL, "delete_cgroup()",
retval, info[GRPNOTDELETEDGLOBALY]);
} else {
message(i, FAIL, "delete_cgroup()", retval,
info[GRPNOTDELETEDINFS]);
}
}
}
/**
* The function tests if the given controller is enabled in kernel
* @param name the name of the controller to be checked
* @param exist set to 1 if the controller exists
*/
void is_subsystem_enabled(const char *name, int *exist)
{
int hierarchy, num_cgroups, enabled;
char subsys_name[FILENAME_MAX];
FILE *fd;
fd = fopen("/proc/cgroups", "r");
if (!fd)
return;
while (!feof(fd)) {
fscanf(fd, "%s, %d, %d, %d", subsys_name,
&hierarchy, &num_cgroups, &enabled);
if (strncmp(name, subsys_name, sizeof(*name)) == 0)
*exist = 1;
}
fclose(fd);
}
/**
* This function tests if the given group exists in filesystem
* @param path_group path to the group to be tested for existence
*/
int group_exist(char *path_group)
{
struct stat statbuf;
if (stat(path_group, &statbuf) == -1) {
/* Group deleted. OK */
if (errno == ENOENT)
return ENOENT;
/* There is some other failure */
printf("stat failed, return code is %d\n", errno);
return -1;
}
if (S_ISDIR(statbuf.st_mode))
return 0;
else
return -1;
}
/**
* Sets the controller name and control file name
* @param controller the enum for the name of the controller
* @param controller_name name of the controller
* @param control_file corresponding control file
*/
int set_controller(int controller, char *controller_name, char *control_file)
{
switch (controller) {
case MEMORY:
if (memory == 0)
return 1;
strncpy(controller_name, "memory", FILENAME_MAX);
strncpy(control_file, "memory.limit_in_bytes", FILENAME_MAX);
return 0;
case CPU:
if (cpu == 0)
return 1;
strncpy(controller_name, "cpu", FILENAME_MAX);
strncpy(control_file, "cpu.shares", FILENAME_MAX);
return 0;
case CPUSET:
strncpy(controller_name, "cpuset", FILENAME_MAX);
strncpy(control_file, "cpuset.cpus", FILENAME_MAX);
return 0;
/* Future controllers can be added here */
default:
printf("Invalid controller name passed. Setting controller");
printf(" failed. Dependent tests may fail\n");
return 1;
}
}
/**
* Tests if a group has been modified
* @param path_control_file path to the control file of the controller
* @param value_type which value out of four types
* @param struct cval the control value structure
*/
int group_modified(char *path_control_file, int value_type,
struct cntl_val_t cval)
{
u_int64_t uint64_val;
/* 100 char looks ok for a control value as string */
char string_val[100];
int64_t int64_val;
bool bool_val;
int error = 1;
FILE *fd;
int aux;
fd = fopen(path_control_file, "r");
if (!fd) {
fprintf(stderr, "Error in opening %s\n", path_control_file);
fprintf(stderr, "Skipping modified values check....\n");
return 1;
}
switch (value_type) {
case BOOL:
fscanf(fd, "%d", &aux);
bool_val = aux;
if (bool_val == cval.val_bool)
error = 0;
break;
case INT64:
fscanf(fd, "%" SCNi64, &int64_val);
if (int64_val == cval.val_int64)
error = 0;
break;
case UINT64:
fscanf(fd, "%" SCNu64, &uint64_val);
if (uint64_val == cval.val_uint64)
error = 0;
break;
case STRING:
fscanf(fd, "%s", string_val);
if (!strncmp(string_val, cval.val_string, strlen(string_val)))
error = 0;
break;
default:
fprintf(stderr, "Wrong value_type passed in %s\n", __func__);
fprintf(stderr, "Skipping modified values check....\n");
/* Can not report test result as failure */
error = 0;
break;
}
fclose(fd);
return error;
}
/**
* Adds the control value to a controller using wrapper apis
* @param newcontroller the controller to be added the value to
* @param control_file name of the control file of the controller
* @param wr the name of wrapper api
* @param value_type which value out of four types
* @param struct cval the control value structure
*/
int add_control_value(struct cgroup_controller *newcontroller,
char *control_file, char *wr, int value_type,
struct cntl_val_t cval)
{
int retval;
switch (value_type) {
case BOOL:
retval = cgroup_add_value_bool(newcontroller,
control_file, cval.val_bool);
snprintf(wr, SIZE, "add_value_bool()");
break;
case INT64:
retval = cgroup_add_value_int64(newcontroller,
control_file, cval.val_int64);
snprintf(wr, SIZE, "add_value_int64()");
break;
case UINT64:
retval = cgroup_add_value_uint64(newcontroller,
control_file, cval.val_uint64);
snprintf(wr, SIZE, "add_value_uint64()");
break;
case STRING:
retval = cgroup_add_value_string(newcontroller,
control_file, cval.val_string);
snprintf(wr, SIZE, "add_value_string()");
break;
default:
printf("ERROR: wrong value in %s\n", __func__);
return 1;
}
return retval;
}
/**
* This function creates and returns a cgroup data structure
* @param group the name of the group
* @param controller_name the name of the controller to be added to the group
* @param control_file name of the control file of the controller
* @param value_type which value out of four types
* @param struct cval the control value structure
* @param struct ids the permissions struct
* @param the test number
*/
struct cgroup *new_cgroup(char *group, char *controller_name,
char *control_file, int value_type,
struct cntl_val_t cval, struct uid_gid_t ids, int i)
{
struct cgroup_controller *newcontroller;
struct cgroup *newcgroup;
/* Names of wrapper apis */
char wr[SIZE];
int retval;
newcgroup = cgroup_new_cgroup(group);
if (newcgroup) {
retval = cgroup_set_uid_gid(newcgroup,
ids.tasks_uid, ids.tasks_gid,
ids.control_uid, ids.control_gid);
if (retval) {
snprintf(wr, SIZE, "set_uid_gid()");
message(i++, FAIL, wr, retval, info[NOMESSAGE]);
}
newcontroller = cgroup_add_controller(newcgroup,
controller_name);
if (newcontroller) {
retval = add_control_value(newcontroller,
control_file, wr, value_type, cval);
if (!retval) {
message(i++, PASS, __func__,
retval, info[NOMESSAGE]);
} else {
message(i++, FAIL, wr, retval,
info[NOMESSAGE]);
cgroup_free(&newcgroup);
return NULL;
}
} else {
/* Since these wrappers do not return an int so -1 */
message(i++, FAIL, "add_controller", -1,
info[NOMESSAGE]);
cgroup_free(&newcgroup);
return NULL;
}
} else {
message(i++, FAIL, "new_cgroup", -1, info[NOMESSAGE]);
return NULL;
}
return newcgroup;
}
/**
* Checks if the cgroup filesystem has been mounted
* @param multimnt to decide if check is for single mount or multimount
*/
int check_fsmounted(int multimnt)
{
struct mntent *entry = NULL, *tmp_entry = NULL;
/* Need a better mechanism to decide memory allocation size here */
char entry_buffer[FILENAME_MAX * 4];
FILE *proc_file = NULL;
int count = 0;
int ret = 1;
tmp_entry = (struct mntent *) malloc(sizeof(struct mntent));
if (!tmp_entry) {
perror("Error: failled to mallloc for mntent\n");
ret = errno;
goto error;
}
proc_file = fopen("/proc/mounts", "r");
if (!proc_file) {
printf("Error in opening /proc/mounts.\n");
ret = errno;
goto error;
}
while ((entry = getmntent_r(proc_file, tmp_entry, entry_buffer,
FILENAME_MAX*4)) != NULL) {
if (!strncmp(entry->mnt_type, "cgroup", strlen("cgroup"))) {
count++;
if (multimnt) {
if (count >= 2) {
printf("sanity check pass. %s\n",
entry->mnt_type);
ret = 0;
goto error;
}
} else {
printf("sanity check pass. %s\n",
entry->mnt_type);
ret = 0;
goto error;
}
}
}
error:
if (tmp_entry)
free(tmp_entry);
if (proc_file)
fclose(proc_file);
return ret;
}
/**
* Checks if the current task belongs to the given tasks file
* @param tasksfile the task file to be tested for the task
*/
int check_task(char *tasksfile, pid_t pid)
{
pid_t curr_tid, tid;
int pass = 0;
FILE *file;
file = fopen(tasksfile, "r");
if (!file) {
printf("ERROR: in opening %s\n", tasksfile);
printf("Exiting without running other testcases in this set\n");
exit(1);
}
if (pid)
curr_tid = pid;
else
curr_tid = cgrouptest_gettid();
while (!feof(file)) {
fscanf(file, "%u", &tid);
if (tid == curr_tid) {
pass = 1;
break;
}
}
fclose(file);
return pass;
}
/**
* Prints the test result in a readable format with some verbose messages
* @param num the test number
* @param pass test passed or failed
* @param api the name of the api tested
* @param retval the return value of the api
* @param extra the extra message to the user about the scenario tested
*/
void message(int num, int pass, const char *api, int retval, char *extra)
{
char buf[2*SIZE];
char res[10];
char res[10];
if (pass)
strncpy(res, "PASS :", 10);
else
strncpy(res, "FAIL :", 10);
/* Populate message buffer for the api */
snprintf(buf, sizeof(buf), "cgroup_%s\t\t Ret Value = ", api);
fprintf(stdout, "TEST%2d:%s %s%d\t%s", num, res, buf, retval, extra);
}
/**
* Builds the path to target file/group
* @param target to write the built path to
* @param mountpoint for which mountpoint the path to be built
* @param group the name of the group (directory)
* @param file what file under the group
*/
void
build_path(char *target, char *mountpoint, const char *group, const char *file)
{
if (!target)
return;
strncpy(target, mountpoint, FILENAME_MAX);
if (group) {
strncat(target, "/", FILENAME_MAX - strlen(target));
strncat(target, group, FILENAME_MAX - strlen(target));
}
if (file) {
strncat(target, "/", FILENAME_MAX - strlen(target));
strncat(target, file, FILENAME_MAX - strlen(target));
}
}
/**
* Tests the cgroup_compare_cgroup() api under different scenarios
* @param ctl1 controller 1 to be used for testing
* @param ctl2 controller 1 to be used for testing
* @param the test number
*/
void test_cgroup_compare_cgroup(int ctl1, int ctl2, int i)
{
char controller_name[FILENAME_MAX], control_file[FILENAME_MAX];
char wr[SIZE], extra[] = "in cgroup_compare_cgroup";
struct cgroup *cgroup1 = NULL, *cgroup2 = NULL;
struct cgroup_controller *controller = NULL;
struct cntl_val_t cval;
int retval;
cval.val_int64 = 0;
cval.val_uint64 = 0;
cval.val_bool = 0;
strcpy(cval.val_string, "5000");
retval = cgroup_compare_cgroup(NULL, NULL);
if (retval)
message(i++, PASS, "compare_cgroup()", retval, info[NULLGRP]);
else
message(i++, FAIL, "compare_cgroup()", retval, info[NULLGRP]);
cgroup1 = cgroup_new_cgroup("testgroup");
cgroup2 = cgroup_new_cgroup("testgroup");
cgroup_set_uid_gid(cgroup1, 0, 0, 0, 0);
cgroup_set_uid_gid(cgroup2, 0, 0, 0, 0);
retval = set_controller(ctl1, controller_name, control_file);
controller = cgroup_add_controller(cgroup1, controller_name);
if (controller) {
retval = add_control_value(controller,
control_file, wr, STRING, cval);
if (retval)
message(i++, FAIL, wr, retval, extra);
}
controller = cgroup_add_controller(cgroup2, controller_name);
if (controller) {
retval = add_control_value(controller,
control_file, wr, STRING, cval);
if (retval)
message(i++, FAIL, wr, retval, extra);
}
retval = cgroup_compare_cgroup(cgroup1, cgroup2);
if (retval)
message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]);
else
message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]);
/* Test the api by putting diff number of controllers in cgroups */
retval = set_controller(ctl2, controller_name, control_file);
controller = cgroup_add_controller(cgroup2, controller_name);
if (controller) {
retval = add_control_value(controller,
control_file, wr, STRING, cval);
if (retval)
message(i++, FAIL, wr, retval, extra);
}
retval = cgroup_compare_cgroup(cgroup1, cgroup2);
if (retval == ECGROUPNOTEQUAL)
message(i++, PASS, "compare_cgroup()", retval, info[NOMESSAGE]);
else
message(i++, FAIL, "compare_cgroup()", retval, info[NOMESSAGE]);
cgroup_free(&cgroup1);
cgroup_free(&cgroup2);
}
/**
* Tests the cgroup_get_cgroup() api under different scenarios
* @param ctl1 controller 1 to be used for testing
* @param ctl2 controller 1 to be used for testing
* @param struct ids the permissions struct
* @param the test number
*/
void test_cgroup_get_cgroup(int ctl1, int ctl2, struct uid_gid_t ids, int i)
{
struct cgroup *cgroup_filled = NULL, *cgroup_a = NULL, *cgroup_b = NULL;
char controller_name[FILENAME_MAX], control_file[FILENAME_MAX];
struct cgroup_controller *controller = NULL;
struct cntl_val_t cval = {0, 0, 0, "5000"};
int ret;
/*
* No need to test the next 3 scenarios separately for Multimnt
* so testing them only under single mount
*/
if (fs_mounted == FS_MOUNTED) {
/* 1. Test with nullcgroup first */
ret = cgroup_get_cgroup(NULL);
if (ret == ECGROUPNOTALLOWED)
message(i++, PASS, "get_cgroup()", ret, info[NULLGRP]);
else
message(i++, FAIL, "get_cgroup()", ret, info[NULLGRP]);
/* 2. Test with invalid name filled cgroup(non existing) */
cgroup_filled = cgroup_new_cgroup("nogroup");
if (!cgroup_filled)
message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]);
ret = cgroup_get_cgroup(cgroup_filled);
if (ret)
message(i++, PASS, "get_cgroup()", ret,
info[NOTCRTDGRP]);
else
message(i++, FAIL, "get_cgroup()", ret,
info[NOTCRTDGRP]);
/* Free the allocated cgroup before reallocation */
cgroup_free(&cgroup_filled);
/* 3.
* Test with name filled cgroup. Ensure the group group1 exists
* in the filesystem before calling this test function
*/
cgroup_filled = cgroup_new_cgroup("group1");
if (!cgroup_filled)
message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]);
ret = cgroup_get_cgroup(cgroup_filled);
if (!ret)
message(i++, PASS, "get_cgroup()", ret,
info[NOMESSAGE]);
else
message(i++, FAIL, "get_cgroup()", ret,
info[NOMESSAGE]);
}
/* SINGLE & MULTI MOUNT: Create, get and compare a cgroup */
/* get cgroup_a ds and create group_a in filesystem */
cgroup_a = create_new_cgroup_ds(ctl1, "group_a", STRING, cval, ids, 0);
if (fs_mounted == FS_MULTI_MOUNTED) {
/* Create under another controller also */
ret = set_controller(ctl2, controller_name, control_file);
controller = cgroup_add_controller(cgroup_a, controller_name);
if (controller)
message(i++, PASS, "cgroup_add_controller()",
0, info[NOMESSAGE]);
else
message(i++, FAIL, "cgroup_add_controller()",
-1, info[NOMESSAGE]);
}
test_cgroup_create_cgroup(0, cgroup_a, "group_a", 0, 1, 1, 00);
/* create group_b ds to be filled by cgroup_get_cgroup */
cgroup_b = cgroup_new_cgroup("group_a");
if (!cgroup_b)
message(i++, FAIL, "new_cgroup()", 0, info[NOMESSAGE]);
/* Fill the ds and compare the two */
ret = cgroup_get_cgroup(cgroup_b);
if (!ret) {
ret = cgroup_compare_cgroup(cgroup_a, cgroup_b);
if (ret == 0)
message(i++, PASS, "get_cgroup()", ret, info[SAMEGRP]);
else
message(i++, FAIL, "get_cgroup()", ret,
info[NOMESSAGE]);
} else {
message(i++, FAIL, "get_cgroup()", ret, info[NOMESSAGE]);
}
/* Delete this created group from fs to leave fs clean */
if (fs_mounted == FS_MULTI_MOUNTED)
test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 1, 1, 0, 0);
else
test_cgroup_delete_cgroup(0, cgroup_a, "group_a", 0, 1, 0, 0);
cgroup_free(&cgroup_a);
cgroup_free(&cgroup_b);
cgroup_free(&cgroup_filled);
}
/**
* Tests the cgroup_add_controller() and cgroup_free_controller() wrapper
* apis under different scenarios
* @param the test number
*/
void test_cgroup_add_free_controller(int i)
{
struct cgroup *cgroup1 = NULL, *cgroup2 = NULL;
struct cgroup_controller *cgctl1, *cgctl2;
/* Test with a Null cgroup */
cgctl1 = cgroup_add_controller(cgroup1, "cpu");
if (!cgctl1)
message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]);
else
message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]);
cgroup1 = cgroup_new_cgroup("testgroup");
cgctl1 = cgroup_add_controller(cgroup1, "cpuset");
if (cgctl1)
message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]);
else
message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]);
cgctl2 = cgroup_add_controller(cgroup1, "cpu");
if (cgctl2)
message(i++, PASS, "add_controller()", 0, info[NOMESSAGE]);
else
message(i++, FAIL, "add_controller()", -1, info[NOMESSAGE]);
cgroup_free(&cgroup1);
cgroup_free_controllers(cgroup2);
}
/**
* Returns the tid of the current thread
*/
pid_t cgrouptest_gettid(void)
{
return syscall(__NR_gettid);
}

View file

@ -1,50 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
/*
* Assumes cgroup is mounted at /cgroup using
* mount -t cgroup -o none,name=test none /cgroup
*/
int main(void)
{
struct cgroup_controller *cgc;
struct cgroup *cgroup;
int ret;
ret = cgroup_init();
if (ret) {
printf("FAIL: cgroup_init failed with %s\n",
cgroup_strerror(ret));
exit(3);
}
cgroup = cgroup_new_cgroup("test");
if (!cgroup) {
printf("FAIL: cgroup_new_cgroup failed\n");
exit(3);
}
cgc = cgroup_add_controller(cgroup, "name=test");
if (!cgc) {
printf("FAIL: cgroup_add_controller failed\n");
exit(3);
}
ret = cgroup_create_cgroup(cgroup, 1);
if (ret) {
printf("FAIL: cgroup_create_cgroup failed with %s\n",
cgroup_strerror(ret));
exit(3);
}
if (access("/cgroup/test", F_OK))
printf("PASS\n");
else
printf("Failed to create cgroup\n");
return 0;
}

View file

@ -1,51 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char *group = NULL;
void *handle;
int ret, i;
if (argc < 2) {
printf("No list of groups provided\n");
return -1;
}
ret = cgroup_init();
if (ret) {
printf("cgroup_init failed with %s\n", cgroup_strerror(ret));
return -1;
}
for (i = 1; i < argc; i++) {
pid_t pid;
group = strdup(argv[i]);
printf("Printing the details of groups %s\n", group);
ret = cgroup_get_task_begin(group, "cpu", &handle, &pid);
while (!ret) {
printf("Pid is %u\n", pid);
ret = cgroup_get_task_next(&handle, &pid);
if (ret && ret != ECGEOF) {
printf("cgroup_get_task_next failed with %s\n",
cgroup_strerror(ret));
if (ret == ECGOTHER)
printf("failure with %s\n",
strerror(errno));
return -1;
}
}
free(group);
group = NULL;
ret = cgroup_get_task_end(&handle);
}
return 0;
}

View file

@ -1,126 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include <libcgroup.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
void visit_node(struct cgroup_file_info *info, char *root)
{
if (info->type == CGROUP_FILE_TYPE_DIR) {
printf("path %s, parent %s, relative %s, full %s\n",
info->path, info->parent,
info->full_path + strlen(root) - 1,
info->full_path);
}
}
int main(int argc, char *argv[])
{
struct cgroup_file_info info;
char root[FILENAME_MAX];
char *controller;
void *handle;
int lvl, i;
int ret;
if (argc < 2) {
fprintf(stderr, "Usage %s: <controller name>\n",
argv[0]);
exit(EXIT_FAILURE);
}
controller = argv[1];
ret = cgroup_init();
if (ret != 0) {
fprintf(stderr, "Init failed\n");
exit(EXIT_FAILURE);
}
ret = cgroup_walk_tree_begin(controller, "/", 0, &handle, &info, &lvl);
if (ret != 0) {
fprintf(stderr, "Walk failed\n");
exit(EXIT_FAILURE);
}
strcpy(root, info.full_path);
printf("Begin pre-order walk\n");
printf("root is %s\n", root);
visit_node(&info, root);
while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) !=
ECGEOF) {
visit_node(&info, root);
}
cgroup_walk_tree_end(&handle);
printf("pre-order walk finished\n");
ret = cgroup_walk_tree_begin(controller, "/", 0, &handle, &info, &lvl);
if (ret != 0) {
fprintf(stderr, "Walk failed\n");
exit(EXIT_FAILURE);
}
ret = cgroup_walk_tree_set_flags(&handle, CGROUP_WALK_TYPE_POST_DIR);
if (ret) {
fprintf(stderr, "Walk failed with %s\n", cgroup_strerror(ret));
exit(EXIT_FAILURE);
}
strcpy(root, info.full_path);
printf("Begin post-order walk\n");
printf("root is %s\n", root);
visit_node(&info, root);
while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) !=
ECGEOF) {
visit_node(&info, root);
}
cgroup_walk_tree_end(&handle);
printf("post order walk finished\n");
ret = cgroup_walk_tree_begin(controller, "/a", 2, &handle, &info, &lvl);
if (ret != 0) {
fprintf(stderr, "Walk failed\n");
exit(EXIT_FAILURE);
}
strcpy(root, info.full_path);
printf("root is %s\n", root);
visit_node(&info, root);
while ((ret = cgroup_walk_tree_next(2, &handle, &info, lvl)) !=
ECGEOF) {
visit_node(&info, root);
}
cgroup_walk_tree_end(&handle);
/*
* Walk only the first five nodes
*/
i = 0;
printf("Walking the first 5 nodes\n");
ret = cgroup_walk_tree_begin(controller, "/", 0, &handle, &info, &lvl);
if (ret != 0) {
fprintf(stderr, "Walk failed\n");
exit(EXIT_FAILURE);
}
strcpy(root, info.full_path);
printf("root is %s\n", root);
visit_node(&info, root);
i++;
while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) !=
ECGEOF) {
visit_node(&info, root);
if (++i >= 5)
break;
}
cgroup_walk_tree_end(&handle);
return EXIT_SUCCESS;
}

View file

@ -1,46 +0,0 @@
// SPDX-License-Identifier: LGPL-2.1-only
#include "../src/libcgroup-internal.h"
#include <libcgroup.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
struct cgroup *cgroup;
struct cgroup_controller *cgc;
int fail = 0;
cgroup = cgroup_new_cgroup("test");
cgc = cgroup_add_controller(cgroup, "cpu");
cgroup_add_value_int64(cgc, "cpu.shares", 2048);
cgroup_add_value_uint64(cgc, "cpu.something", 1000);
cgroup_add_value_bool(cgc, "cpu.bool", 1);
if (!strcmp(cgroup->controller[0]->values[0]->name, "cpu.shares")) {
if (strcmp(cgroup->controller[0]->values[0]->value, "2048")) {
printf("FAIL for add_value_int\n");
fail = 1;
}
}
if (!strcmp(cgroup->controller[0]->values[1]->name, "cpu.something")) {
if (strcmp(cgroup->controller[0]->values[1]->value, "1000")) {
printf("FAIL for add_value_uint\n");
fail = 1;
}
}
if (!strcmp(cgroup->controller[0]->values[2]->name, "cpu.bool")) {
if (strcmp(cgroup->controller[0]->values[2]->value, "1")) {
printf("FAIL for add_value_bool\n");
fail = 1;
}
}
if (!fail)
printf("PASS!\n");
return fail;
}

View file

@ -1,13 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# libcgroup cmdline samples Makefile.am
#
# Copyright (c) 2023 Oracle and/or its affiliates.
# Author: Tom Hromatka <tom.hromatka@oracle.com>
#
if WITH_SAMPLES
EXTRA_DIST = systemd-with-idle-process.md
endif

View file

@ -1,222 +0,0 @@
_SPDX-License-Identifier: LGPL-2.1-only_
_Copyright (c) 2023 Oracle and/or its affiliates._
_Author: Tom Hromatka <<tom.hromatka@oracle.com>>_
# Creating a Systemd Scope and Child Hierarchy via Libcgroup Command Line
The goal of this document is to outline the steps required to create
a systemd scope and a child cgroup hierarchy using the libcgroup
command line tools.
The following steps are encapsulated in a
[C example](../c/create_systemd_scope.c) using the libcgroup C APIs.
The following steps are encapsulated in a
[libcgroup automated test](../../tests/ftests/086-sudo-systemd_cmdline_example.py).
## Requirements:
1. Create a cgroup hierarchy that obeys the
[single-writer rule](https://systemd.io/CGROUP_DELEGATION/)
1. The hierarchy should be cgroup v2
1. The hierarchy should be of the form
```
database.scope
├── high-priority
├── low-priority
└── medium-priority
```
1. The memory controller should be enabled for the entire tree
1. The `high-priority` cgroup should be guaranteed at least 1GB of RAM
1. The `low-priority` cgroup should be hard-limited to 2GB of RAM
1. The `medium-prioirty` cgroup should have a soft memory limit of 3 GB
1. The cpu controller should be enabled for the entire tree
1. The `high-priority` cgroup should be able to consume 60% of CPU cycles
1. The `medium-priority` cgroup should be able to consume 30% of CPU cycles
1. The `low-priority` cgroup should be able to consume 10% of CPU cycles
## Steps
1. Create a delegated
[scope](https://www.freedesktop.org/software/systemd/man/systemd.scope.html)
cgroup
```
sudo cgcreate -c -S -g cpu,memory:mycompany.slice/database.scope
```
This will create a
[transient](https://github.com/systemd/systemd/blob/main/docs/TRANSIENT-SETTINGS.md),
[delegated](https://systemd.io/CGROUP_DELEGATION/) scope. The `-c` flag
instructs libcgroup to create a systemd scope; libcgroup then instructs
systemd that this hierarchy is delegated, i.e. it is to be managed by
another process and _not_ by systemd. The `-S` flag notifies libcgroup
that we want `mycompany.scope/database.slice` to be the default base
path in libcgroup; this will significantly help in reducing typing in
follow-on commands. The `-g` flag tells libcgroup to create a cgroup
named `mycompany.slice/database.scope` and enable the cpu and memory
controllers within it.
<details>
<summary>Problems during this step?</summary>
Systemd should automatically remove scopes with no active processes
running within them. So, the first step would be to kill any processes
in the scope, wait to see if systemd removes the scope, and then try the
`cgcreate` operation again.
- Remove all processes in the scope
```
$ for PID in $(cgget -nvb -r cgroup.procs mycompany.slice/database.scope); do sudo kill -9 $PID;done
```
The above command could be simplified as
`for PID in $(cgget -nv -r cgroup.procs /); do sudo kill -9 $PID;done`,
but introduces some risk. If there is a typo or the default scope path
isn't set, then unconditionally killing processes in `/` could be
catastrophic.
Sometimes systemd's internal list of scopes gets out of sync with the
filesystem. You can purge the `database.scope` from its list by running
the following commands
- Remove `database.scope` from systemd's internal list
```
sudo systemctl kill database.scope
sudo systemctl stop database.scope
```
</details>
1. Create the child cgroups
```
$ sudo cgcreate -g cpu,memory:mycompany.slice/database.scope/high-priority
cgcreate: can't create cgroup mycompany.slice/database.scope/high-priority: Operation not supported
```
But... but... I did everything right. Why can't I create the
`high-priority` child cgroup? This operation failed due to the
[no-processes-in-inner-nodes](https://systemd.io/CGROUP_DELEGATION/) rule.
Since a process, `libcgroup_systemd_idle_thread`, resides in
`database.scope`, we are subject to the no-process-in-inner-nodes rule.
The kernel will let us create a child cgroup, but it will fail when we try
to enable controllers in `database.scope`'s `cgroup.subtree_control` file.
There are a few different ways to solve this failure; the easiest is
probably to create a temporary cgroup under `database.scope` and move the
`libcgroup_systemd_idle_thread` to this temporary cgroup. This allows
`database.scope` to operate as a legal inner node, and we can then create
the entire hierarchy.
1. Temporarily disable the cpu and memory controllers at the scope level
```
sudo cgset -r cgroup.subtree_control="-cpu -memory" /
```
Since we informed libcgroup that `mycompany.slice/database.scope` is the
default path, we can use `/`. Otherwise, we would have had to specify
the entire path. This pattern continues throughout this example.
1. Create a temporary cgroup and move the idle process
```
sudo cgcreate -g :tmp
sudo cgclassify -g :tmp $(cgget -nv -r cgroup.procs /)
```
1. Re-enable the cpu and memory controllers at the scope level
```
sudo cgset -r cgroup.subtree_control="+cpu +memory" /
```
Now we can finally get back to creating our child cgroups
```
sudo cgcreate -g cpu,memory:high-priority -g cpu,memory:medium-priority -g cpu,memory:low-priority
```
1. Configure the cgroups per the requirements
1. The `high-priority` cgroup should be guaranteed at least 1GB of RAM
```
sudo cgset -r memory.low=1G high-priority
```
1. The `low-priority` cgroup should be hard-limited to 2GB of RAM
```
sudo cgset -r memory.max=2G low-priority
```
1. The `medium-prioirty` cgroup should have a soft memory limit of 3 GB
```
sudo cgset -r memory.high=3G medium-priority
```
1. The `high-priority` cgroup should be able to consume 60% of CPU cycles
```
sudo cgset -r cpu.weight=600 high-priority
```
Note that I've (somewhat arbitrarily) chosen a total `cpu.weight` within
`database.scope` to be 1000. Thus, to meet the 60% requirement, we need
to allocate 600 shares to the `high-priority` cgroup.
1. The `medium-priority` cgroup should be able to consume 30% of CPU cycles
```
sudo cgset -r cpu.weight=300 medium-priority
```
1. The `low-priority` cgroup should be able to consume 10% of CPU cycles
```
sudo cgset -r cpu.weight=100 low-priority
```
1. Start up the application
- If the application is already running, then you can use `cgclassify` to
move the process(es) to the appropriate cgroups
- To start a fresh application, it is recommended to use `cgexec` to place
the application in the desired cgroup
- Finally, consider using `cgrulesengd` to automatically move processes to
the correct cgroups
1. Clean up
1. Now that there are other processes running within the scope, we can
remove the `libcgroup_systemd_idle_thread`
```
$ for PID in $(cgget -nv -r cgroup.procs tmp); do sudo kill -9 $PID;done
```
1. Delete the `tmp` cgroup
```
sudo cgdelete -g :tmp
```
1. Verify the cgroups were configured per the requirements
```
$ cgget -r cpu.weight -r memory.low -r memory.high -r memory.max high-priority medium-priority low-priority
high-priority:
cpu.weight: 600
memory.low: 1073741824
memory.high: max
memory.max: max
medium-priority:
cpu.weight: 300
memory.low: 0
memory.high: 3221225472
memory.max: max
low-priority:
cpu.weight: 100
memory.low: 0
memory.high: max
memory.max: 2147483648
```
1. Summary
This document outlines the steps for creating a delegated systemd scope and
configuring its child cgroups on a cgroup v2 system. Systemd and libcgroup
provide powerful tools to simplify these steps.

View file

@ -1,9 +0,0 @@
EXTRA_DIST = cgconfig.conf \
cgconfig.sysconfig \
cgred.conf \
cgrules.conf \
cgsnapshot_denylist.conf \
cgsnapshot_allowlist.conf \
invalid_namespace_config.conf \
invalid_namespace_mount_config.conf \
namespace_config.conf

View file

@ -1,42 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# Copyright IBM Corporation. 2007
#
# Authors: Balbir Singh <balbir@linux.vnet.ibm.com>
#
#group daemons/www {
# perm {
# task {
# uid = root;
# gid = webmaster;
# }
# admin {
# uid = root;
# gid = root;
# }
# }
# cpu {
# cpu.shares = 1000;
# }
#}
#
#group daemons/ftp {
# perm {
# task {
# uid = root;
# gid = ftpmaster;
# }
# admin {
# uid = root;
# gid = root;
# }
# }
# cpu {
# cpu.shares = 500;
# }
#}
#
#mount {
# cpu = /mnt/cgroups/cpu;
# cpuacct = /mnt/cgroups/cpuacct;
#}

View file

@ -1,12 +0,0 @@
# Service cgconfig can create a default group in all mounted hierarchies and
# move all processes there on boot. If no default rule is specified in
# /etc/cgrules.conf, the default group is named '/sysdefault'.
# This automatically created group(s) can be useful e.g. when using 'cpu'
# controller to limit cpu.shares of this default group and allowing some more
# important group take most of the CPU.
#
# By default, create these groups:
CREATE_DEFAULT=yes
# Uncomment following line to disable creation of the default group on startup:
# CREATE_DEFAULT=no

View file

@ -1,22 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# Copyright (c) 2023 Oracle and/or its affiliates.
# Author: Kamalesh Babulal <kamalesh.babulal@oracle.com>
#
#systemd {
# slice = database.slice;
# scope = db.scope;
# setdefault = yes;
#}
#
#systemd {
# slice = database.slice;
# scope = house_keeping.scope;
# pid = 3456;
#}
#
#systemd {
# slice = others.slice;
# scope = server.scope;
#}

View file

@ -1,27 +0,0 @@
# /etc/sysconfig/cgred.conf - CGroup Rules Engine Daemon configuration file
#
# The four options listed below (CONFIG_FILE, LOG_FILE, NODAEMON, LOG) are
# the only valid ones. Defining anything else in this file will cause the
# CGroup Rules Engine program to fail. So, don't do it.
# The pathname to the configuration file for CGroup Rules Engine
CONFIG_FILE="/etc/cgrules.conf"
# Uncomment the following line to log to specified file instead of syslog
#LOG_FILE="/var/log/cgrulesengd.log"
# Uncomment the second line to run CGroup Rules Engine in non-daemon mode
NODAEMON=""
#NODAEMON="--nodaemon"
# Set owner of cgred socket. 'cgexec' tool should have write access there
# (either using suid and/or sgid permissions or Linux capabilities).
SOCKET_USER=""
SOCKET_GROUP="cgred"
# Uncomment the second line to disable logging for CGroup Rules Engine
# Uncomment the third line to enable more verbose logging.
LOG=""
#LOG="--nolog"
#LOG="-v"

View file

@ -1,10 +0,0 @@
# /etc/cgrules.conf
#The format of this file is described in cgrules.conf(5)
#manual page.
#
# Example:
#<user> <controllers> <destination>
#@student cpu,memory usergroup/student/
#peter cpu test1/
#% memory test2/
# End of file

View file

@ -1,48 +0,0 @@
#cgsnapshot tool configuration file
#memory
memory.memsw.failcnt
memory.memsw.limit_in_bytes
memory.memsw.max_usage_in_bytes
memory.swappiness
memory.use_hierarchy
memory.failcnt
memory.soft_limit_in_bytes
memory.limit_in_bytes
memory.max_usage_in_bytes
memory.move_charge_at_immigrate
#cpu
cpu.rt_runtime_us
cpu.rt_period_us
#cpuacct
cpuacct.usage
#devices
devices.deny
devices.allow
devices.list
#cpuset
cpuset.memory_spread_slab
cpuset.memory_spread_page
cpuset.memory_migrate
cpuset.sched_relax_domain_level
cpuset.sched_load_balance
cpuset.mem_hardwall
cpuset.mem_exclusive
cpuset.cpu_exclusive
cpuset.mems
cpuset.cpus
#ns
#freezer
freezer.state
#net_cls
net_cls.classid
#blkio
blkio.weight

View file

@ -1,20 +0,0 @@
#cgsnapshot tool configuration file
#memory
memory.oom_control
#cpu
#cpuacct
#devices
#cpuset
#ns
#freezer
#net_cls
#blkio

View file

@ -1,53 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# Copyright IBM Corporation. 2009
#
# Authors: Dhaval Giani <dhaval@linux.vnet.ibm.com>
#
group www {
perm {
task {
uid = root;
gid = webmaster;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 1000;
}
cpuacct {
}
}
group ftp {
perm {
task {
uid = root;
gid = ftpmaster;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 500;
}
cpuacct {
}
}
mount {
cpu = /mnt/cgroups;
cpuacct = /mnt/cgroups;
}
namespace {
cpu = daemons;
#This is invalid since both cpu and cpuacct are mounted at the
#same place but have different namespace
cpuacct = network;
}

View file

@ -1,59 +0,0 @@
#
# Copyright IBM Corporation. 2009
#
# Authors: Dhaval Giani <dhaval@linux.vnet.ibm.com>
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2.1 of the GNU Lesser General Public License
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
group www {
perm {
task {
uid = root;
gid = root;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 1000;
}
cpuacct {
}
}
group ftp {
perm {
task {
uid = root;
gid = root;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 500;
}
cpuacct {
}
}
#This is invalid because we cannot have mount and namespace in the same
#configuration file.
mount {
cpu = /cgroups/cpu;
cpuacct = /cgroups/cpuacct;
}
namespace {
cpu = daemons;
cpuacct = daemons;
}

View file

@ -1,46 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# Copyright IBM Corporation. 2009
#
# Authors: Dhaval Giani <dhaval@linux.vnet.ibm.com>
#
group www {
perm {
task {
uid = root;
gid = root;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 1000;
}
cpuacct {
}
}
group ftp {
perm {
task {
uid = root;
gid = root;
}
admin {
uid = root;
gid = root;
}
}
cpu {
cpu.shares = 500;
}
cpuacct {
}
}
namespace {
cpu = daemons;
cpuacct = daemons;
}

View file

@ -1,18 +0,0 @@
# SPDX-License-Identifier: LGPL-2.1-only
#
# libcgroup python samples Makefile.am
#
# Copyright (c) 2023 Oracle and/or its affiliates.
# Author: Tom Hromatka <tom.hromatka@oracle.com>
#
if WITH_SAMPLES
EXTRA_DIST = create_systemd_scope.py
endif
clean-local: clean-local-check
.PHONY: clean-local-check
clean-local-check:
-rm -f *.pyc

View file

@ -1,185 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-only
#
# Sample program that shows how to use libcgroup to create a systemd scope
#
# This program is designed to meet the requirements outlined in the systemd
# cmdline example [1] via the libcgroup C APIs.
#
# [1] https://github.com/libcgroup/libcgroup/blob/main/samples/cmdline/systemd-with-idle-process.md
#
#
# Copyright (c) 2023 Oracle and/or its affiliates.
# Author: Tom Hromatka <tom.hromatka@oracle.com>
#
#
# To run this program:
# 1. Compile the libcgroup library
# $ ./bootstrap.sh
# $ make
# 2. Note the path to your libcgroup python library
# $ pushd src/python/build/lib*
# $ export TMPPATH=$(pwd)
# $ popd
# 2. Run the program
# $ # Note that there are more options. Run `create_systemd_scope.py -h`
# $ # for more info
# $ sudo PYTHONPATH=$TMPPATH \
# ./samples/python/create_systemd_scope.py \
# --slice <yourslicename> --scope <yourscopename>
#
from libcgroup import Cgroup, Version, LogLevel
import multiprocessing
import argparse
import signal
import time
import sys
import os
TMP_CGNAME = "tmp"
HIGH_CGNAME = "high-priority"
MED_CGNAME = "medium-priority"
LOW_CGNAME = "low-priority"
def parse_args():
parser = argparse.ArgumentParser('libcgroup sample program to create a systemd scope')
delegated_parser = parser.add_mutually_exclusive_group(required=False)
delegated_parser.add_argument('-d', '--delegated', help='Create a delegated scope',
action='store_true', dest='delegated')
delegated_parser.add_argument('-n', '--notdelegated',
help='Create a scope that is not delegated',
action='store_false', dest='delegated')
parser.set_defaults(delegated=True)
parser.add_argument('-p', '--pid', help='PID to place within the scope. If not provided,'
'libcgroup will place a temporary process in the scope',
required=False, type=int, default=None)
parser.add_argument('-s', '--scope', help='Name of the scope to be created',
required=True, type=str, default=None)
parser.add_argument('-t', '--slice', help='Name of the slice where the scope will reside',
required=True, type=str, default=None)
parser.add_argument('-v', '--verbose', help='Enable verbose logging within libcgroup',
required=False, action='store_true')
args = parser.parse_args()
return args
def create_scope(args):
print('\n----------------------------------------------------------------')
print('Creating systemd scope, {}/{},'.format(args.slice, args.scope))
if args.pid:
print('and placing PID, {}, in the scope'.format(args.pid))
else:
print('and libcgroup will place an idle process in the scope')
print('----------------------------------------------------------------\n')
Cgroup.create_scope(args.scope, args.slice, args.delegated, pid=args.pid)
Cgroup.write_default_systemd_scope(args.slice, args.scope, True)
def create_tmp_cgroup():
cg = Cgroup(TMP_CGNAME, Version.CGROUP_V2)
cg.create()
def move_pids_to_tmp_cgroup():
cg = Cgroup('/', Version.CGROUP_V2)
pids = cg.get_processes()
for pid in pids:
Cgroup.move_process(pid, TMP_CGNAME)
def create_high_priority_cgroup():
cg = Cgroup(HIGH_CGNAME, Version.CGROUP_V2)
cg.add_setting('cpu.weight', '600')
cg.add_setting('memory.low', '1G')
cg.create()
def create_medium_priority_cgroup():
cg = Cgroup(MED_CGNAME, Version.CGROUP_V2)
cg.add_setting('cpu.weight', '300')
cg.add_setting('memory.high', '3G')
cg.create()
def create_low_priority_cgroup():
cg = Cgroup(LOW_CGNAME, Version.CGROUP_V2)
cg.add_setting('cpu.weight', '100')
cg.add_setting('memory.max', '2G')
cg.create()
def __infinite_loop():
while True:
time.sleep(10)
def create_process_in_cgroup(cgname):
p = multiprocessing.Process(target=__infinite_loop, )
p.start()
Cgroup.move_process(p.pid, cgname)
return p.pid
def delete_tmp_cgroup():
cg = Cgroup(TMP_CGNAME, Version.CGROUP_V2)
pids = cg.get_processes()
for pid in pids:
os.kill(pid, signal.SIGKILL)
# I have observed "Device or resource busy" errors when deleting the
# cgroup immediately after the os.kill() instruction. Give the kill
# command a little time to succeed
time.sleep(1)
cg.delete()
def main(args):
if args.verbose:
Cgroup.log_level(LogLevel.CGROUP_LOG_DEBUG)
create_scope(args)
create_tmp_cgroup()
move_pids_to_tmp_cgroup()
create_high_priority_cgroup()
create_medium_priority_cgroup()
create_low_priority_cgroup()
high_pid = create_process_in_cgroup(HIGH_CGNAME)
med_pid = create_process_in_cgroup(MED_CGNAME)
low_pid = create_process_in_cgroup(LOW_CGNAME)
delete_tmp_cgroup()
print('\n----------------------------------------------------------------')
print('Cgroup setup completed successfully')
print('\t* The scope {} was placed under slice {}'.format(args.scope, args.slice))
print('\t* Libcgroup initially placed an idle process in the scope,\n'
'\t but it has been removed by this program')
print('\t* PID {} has been placed in the {} cgroup'.format(high_pid, HIGH_CGNAME))
print('\t* PID {} has been placed in the {} cgroup'.format(med_pid, MED_CGNAME))
print('\t* PID {} has been placed in the {} cgroup'.format(low_pid, LOW_CGNAME))
print('\nThis program will wait for the aforementioned child processes to\n'
'exit before exiting itself. Systemd will automatically delete the\n'
'scope when there are no longer any processes running within the\n'
'scope. Systemd will not automatically delete the slice.')
print('----------------------------------------------------------------\n')
if __name__ == '__main__':
args = parse_args()
sys.exit(main(args))
# vim: set et ts=4 sw=4:

View file

@ -1,11 +0,0 @@
EXTRA_DIST = init.d/cgconfig.in init.d/cgred.in
if WITH_INITSCRIPT_INSTALL
INITSCRIPTDIR=$(DESTDIR)$(sysconfdir)/rc.d/init.d
install-exec-hook:
$(INSTALL) -d $(INITSCRIPTDIR)
$(INSTALL_SCRIPT) init.d/cgconfig init.d/cgred $(INITSCRIPTDIR)
uninstall-hook:
rm -f $(INITSCRIPTDIR)/cgconfig $(INITSCRIPTDIR)/cgred
endif

View file

@ -1,221 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-only
#
# Start/Stop the workload manager
#
# Copyright IBM Corporation. 2008
#
# Authors: Balbir Singh <balbir@linux.vnet.ibm.com>
#
# cgconfig Control Groups Configuration Startup
# chkconfig: - 5 95
# description: This script runs the cgconfigparser utility to parse and setup
# the control group filesystem. It uses /etc/cgconfig.conf
# and parses the configuration specified in there.
### BEGIN INIT INFO
# Provides: cgconfig
# Required-Start:
# Required-Stop:
# Should-Start: ypbind
# Should-Stop: ypbind
# Short-Description: Create and setup control group filesystem(s)
# Description: Create and setup control group filesystem(s)
### END INIT INFO
# get correct location of binaries from configure
sbindir=@sbindir@
CGCONFIGPARSER_BIN=$sbindir/cgconfigparser
CONFIG_FILE=/etc/cgconfig.conf
CONFIG_DIR=/etc/cgconfig.d
servicename=cgconfig
lockfile=/run/lock/subsys/$servicename
#
# Source LSB routines
#
SYSLIBFILE=/lib/lsb/init-functions
OLDSYSLIBFILE=/etc/init.d/functions
if [[ -x $SYSLIBFILE ]] ; then
# shellcheck disable=SC1090
source $SYSLIBFILE
elif [[ -x $OLDSYSLIBFILE ]] ; then
# shellcheck disable=SC1090
source $OLDSYSLIBFILE
log_warning_msg() ( warning "$@" ; printf "\n" 1>&2 ; )
log_failure_msg() ( failure "$@" ; printf "\n" 1>&2 ; )
log_success_msg() ( success "$@" ; printf "\n" 1>&2 ; )
else
log_warning_msg() ( printf "warning:%s\n" "$@" 1>&2 ;)
log_failure_msg() ( printf "failure:%s\n" "$@" 1>&2 ;)
log_success_msg() ( printf "success:%s\n" "$@" 1>&2 ;)
fi
# read the config
CREATE_DEFAULT=yes
if [ -e /etc/sysconfig/cgconfig ]; then
# shellcheck disable=SC1091
source /etc/sysconfig/cgconfig
fi
lockfiledir=$(dirname "$lockfile")
create_default_groups() {
defaultcgroup=
if [ -f /etc/cgrules.conf ]; then
# shellcheck disable=SC2034
read -r user ctrl defaultcgroup <<< \
"$(grep -m1 '^\*[[:space:]]\+' /etc/cgrules.conf)"
if [[ ( -n "$defaultcgroup" ) && ( "$defaultcgroup" = "*" ) ]]; then
log_warning_msg "/etc/cgrules.conf incorrect"
log_warning_msg "Overriding it"
defaultcgroup=
fi
fi
if [[ -z "$defaultcgroup" ]]
then
defaultcgroup=sysdefault/
fi
#
# Find all mounted subsystems and create comma-separated list
# of controllers.
#
controllers=$(lssubsys 2>/dev/null | tr '\n' ',' | sed s/.$//)
#
# Create the default group, ignore errors when the default group
# already exists.
#
cgcreate -f 664 -d 775 -g "$controllers":"$defaultcgroup" 2>/dev/null
#
# special rule for cpusets
#
if echo "$controllers" | grep -q -w cpuset; then
cpus=$(cgget -nv -r cpuset.cpus /)
cgset -r cpuset.cpus="$cpus $defaultcgroup"
mems=$(cgget -nv -r cpuset.mems /)
cgset -r cpuset.mems="$mems $defaultcgroup"
fi
#
# Classify everything to default cgroup. Ignore errors, some processes
# may exit after ps is run and before cgclassify moves them.
#
cgclassify -g "$controllers:$defaultcgroup $(ps --no-headers -eL o tid)" \
2>/dev/null || :
}
start() {
printf "Starting %s service: " "$servicename"
if [[ -f "$lockfile" ]]; then
log_warning_msg "lock file already exists"
return 0
fi
if [[ ! -s "$CONFIG_FILE" ]]; then
log_failure_msg $CONFIG_FILE "is not configured"
return 6
fi
if ! "$CGCONFIGPARSER_BIN" -l "$CONFIG_FILE" -L "$CONFIG_DIR"
then
log_failure_msg "Failed to parse " "$CONFIG_FILE" "or" "$CONFIG_DIR"'/*'
return 1
fi
if [ $CREATE_DEFAULT = "yes" ]; then
create_default_groups
fi
if ! mkdir -p "$lockfiledir" ; then
log_failure_msg "Failed to mkdir $lockfiledir directory"
return 1
fi
if ! touch "$lockfile" ; then
log_failure_msg "Failed to touch $lockfile"
return 1
fi
log_success_msg "Started $servicename"
return 0
}
stop() {
printf "Stopping %s service is not supported!: " "$servicename"
log_failure_msg "Failed to stop $servicename"
return 1
}
trapped() {
#
# Do nothing
#
true
}
usage() {
echo "$0 <start|stop|restart|condrestart|status>"
exit 2
}
common() {
#
# main script work done here
#
trap "trapped ABRT" ABRT
trap "trapped QUIT" QUIT
trap "trapped TERM" TERM
trap "trapped INT" INT
}
restart() {
common
stop
start
}
RETVAL=0
case $1 in
'stop')
common
stop
RETVAL=$?
;;
'start')
common
start
RETVAL=$?
;;
'restart'|'reload')
restart
RETVAL=$?
;;
'condrestart')
if [[ -f "$lockfile" ]]; then
restart
RETVAL=$?
fi
;;
'status')
if [ -f "$lockfile" ]; then
echo "Running"
exit 0
else
echo "Stopped"
exit 3
fi
;;
*)
usage
;;
esac
exit $RETVAL

View file

@ -1,169 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-only
#
# Start/Stop the CGroups Rules Engine Daemon
#
# Copyright Red Hat Inc. 2008
#
# Authors: Steve Olivieri <sjo@redhat.com>
#
# cgred CGroups Rules Engine Daemon
# chkconfig: - 14 86
# description: This is a daemon for automatically classifying processes \
# into cgroups based on UID/GID.
#
# processname: cgrulesengd
# pidfile: /var/run/cgred.pid
#
### BEGIN INIT INFO
# Provides: cgrulesengd
# Required-Start: $local_fs $syslog $cgconfig
# Required-Stop: $local_fs $syslog
# Should-Start:
# Should-Stop:
# Short-Description: start and stop the cgroups rules engine daemon
# Description: CGroup Rules Engine is a tool for automatically using \
# cgroups to classify processes
### END INIT INFO
CGRED_BIN=/usr/sbin/cgrulesengd
# Sanity checks
[[ -x $CGRED_BIN ]] || exit 1
#
# Source LSB routines
#
SYSLIBFILE=/lib/lsb/init-functions
OLDSYSLIBFILE=/etc/init.d/functions
if [[ -x $SYSLIBFILE ]] ; then
# shellcheck disable=SC1090
source $SYSLIBFILE
elif [[ -x $OLDSYSLIBFILE ]] ; then
# shellcheck disable=SC1090
source $OLDSYSLIBFILE
log_warning_msg() ( warning "$@" ; printf "\n" 1>&2 ; )
log_failure_msg() ( failure "$@" ; printf "\n" 1>&2 ; )
log_success_msg() ( success "$@" ; printf "\n" 1>&2 ; )
else
log_warning_msg() ( printf "warning:%s\n" "$@" 1>&2 ;)
log_failure_msg() ( printf "failure:%s\n" "$@" 1>&2 ;)
log_success_msg() ( printf "success:%s\n" "$@" 1>&2 ;)
fi
# Read in configuration options.
if [[ -f "/etc/sysconfig/cgred.conf" ]] ; then
# shellcheck disable=SC1091
source /etc/sysconfig/cgred.conf
OPTIONS="$NODAEMON $LOG"
if [[ -n "$LOG_FILE" ]]; then
OPTIONS="$OPTIONS --logfile=$LOG_FILE"
fi
if [[ -n "$SOCKET_USER" ]]; then
OPTIONS="$OPTIONS -u $SOCKET_USER"
fi
if [[ -n "$SOCKET_GROUP" ]]; then
OPTIONS="$OPTIONS -g $SOCKET_GROUP"
fi
else
OPTIONS=""
fi
# For convenience
processname=cgrulesengd
servicename=cgred
lockfile="/var/lock/subsys/$servicename"
pidfile=/var/run/cgred.pid
start()
{
echo -n $"Starting CGroup Rules Engine Daemon: "
if [[ -f "$lockfile" ]]; then
log_failure_msg "$servicename is already running with PID $(cat ${pidfile})"
return 0
fi
num=$(grep "cgroup" /proc/mounts | awk '$3=="cgroup"' | wc -l)
if [[ "$num" -eq 0 ]]; then
echo
log_failure_msg $"Cannot find cgroups, is cgconfig service running?"
return 1
fi
daemon --check $servicename --pidfile $pidfile $CGRED_BIN $OPTIONS
retval=$?
echo
if [[ $retval -ne 0 ]]; then
return 7
fi
if ! touch "$lockfile"; then
return 1
fi
pidof "$processname" > $pidfile
return 0
}
stop()
{
echo -n $"Stopping CGroup Rules Engine Daemon..."
if [[ ! -f $pidfile ]]; then
log_success_msg
return 0
fi
killproc -p $pidfile -TERM "$processname"
retval=$?
echo
if [[ $retval -ne 0 ]]; then
return 1
fi
rm -f "$lockfile" "$pidfile"
return 0
}
RETVAL=0
# See how we are called
case "$1" in
start)
start
RETVAL=$?
;;
stop)
stop
RETVAL=$?
;;
status)
status -p $pidfile $servicename
RETVAL=$?
;;
restart)
stop
start
RETVAL=$?
;;
condrestart)
if [[ -f "$lockfile" ]]; then
stop
start
RETVAL=$?
fi
;;
reload|flash)
if [[ -f "$lockfile" ]]; then
echo $"Reloading rules configuration..."
kill -s 12 "$(cat ${pidfile})"
RETVAL=$?
if [[ $RETVAL -eq 0 ]] ; then
log_success_msg ""
else
log_failure_msg ""
fi
else
log_failure_msg "$servicename is not running."
fi
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
RETVAL=2
;;
esac
exit $RETVAL

Some files were not shown because too many files have changed in this diff Show more