Compare commits
No commits in common. "45f455831ceb4899ab9e4053b18b10475f40c910" and "7fd6727a6e00762a1c618b4ec9f89d0d5b739ea4" have entirely different histories.
45f455831c
...
7fd6727a6e
18 changed files with 888 additions and 826 deletions
|
@ -1,2 +0,0 @@
|
||||||
_release
|
|
||||||
_debug
|
|
24
.github/workflows/ci.yaml
vendored
24
.github/workflows/ci.yaml
vendored
|
@ -9,14 +9,6 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: sudo apt-get install -y make clang-format
|
|
||||||
- run: make lint
|
|
||||||
- run: git diff --exit-code
|
|
||||||
|
|
||||||
build-with-gcc:
|
build-with-gcc:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -24,35 +16,29 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: {fetch-depth: 0}
|
|
||||||
- run: sudo apt-get install -y build-essential
|
- run: sudo apt-get install -y build-essential
|
||||||
- run: make VERBOSE=1 CFG=${{ matrix.cfg}} -j$(nproc)
|
- run: make CFG=${{ matrix.cfg}} -j$(nproc)
|
||||||
- run: |
|
- run: _${{ matrix.cfg }}/inotify-info
|
||||||
_${{ matrix.cfg }}/inotify-info --version
|
|
||||||
_${{ matrix.cfg }}/inotify-info
|
|
||||||
|
|
||||||
build-with-zig:
|
build-with-zig:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: {fetch-depth: 0}
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
key: zig-sdk-and-cache-${{ hashFiles('.github/workflows/ci.yaml') }}
|
key: zig-sdk-and-cache-${{ hashFiles('.github/workflows/ci.yaml') }}
|
||||||
path: ~/.cache/zig
|
path: ~/.cache/zig
|
||||||
- run: |
|
- run: |
|
||||||
wget --progress=dot:mega \
|
wget --progress=dot:mega \
|
||||||
https://ziglang.org/download/0.13.0/zig-linux-$(uname -m)-0.13.0.tar.xz
|
https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz
|
||||||
tar -xJf zig-linux-*.tar.xz
|
tar -xJf zig-linux-*.tar.xz
|
||||||
rm zig-linux-*.xz
|
rm zig-linux-*.xz
|
||||||
mv zig-linux-* zig-sdk
|
mv zig-linux-* zig-sdk
|
||||||
- run: |
|
- run: |
|
||||||
make VERBOSE=1 -j$(nproc) \
|
make -j$(nproc) \
|
||||||
CC="zig-sdk/zig cc -target $(uname -m)-linux-musl" \
|
CC="zig-sdk/zig cc -target $(uname -m)-linux-musl" \
|
||||||
CXX="zig-sdk/zig c++ -target $(uname -m)-linux-musl"
|
CXX="zig-sdk/zig c++ -target $(uname -m)-linux-musl"
|
||||||
- run: |
|
- run: _release/inotify-info
|
||||||
_release/inotify-info --version
|
|
||||||
_release/inotify-info
|
|
||||||
|
|
||||||
build-with-docker:
|
build-with-docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
5
.github/workflows/release.yaml
vendored
5
.github/workflows/release.yaml
vendored
|
@ -8,10 +8,15 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Archive
|
||||||
|
run: make inotify-info-${{ github.ref_name }}.tar.gz
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
if: startsWith(github.ref, 'refs/tags/v')
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
with:
|
with:
|
||||||
|
files: inotify-info-${{ github.ref_name }}.tar.gz
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
draft: true
|
draft: true
|
||||||
prerelease: true
|
prerelease: true
|
||||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
||||||
_debug/
|
_debug/
|
||||||
_release/
|
_release/
|
||||||
|
|
||||||
/inotify-info-*.tar.gz
|
/inotify-info-v*.tar.gz
|
||||||
|
|
19
Dockerfile
19
Dockerfile
|
@ -1,14 +1,23 @@
|
||||||
FROM alpine:edge
|
FROM alpine
|
||||||
|
|
||||||
RUN apk add make zig git
|
# zig is installed from the upstream tarball, because:
|
||||||
|
# - as of writing, alpine has zig only in testing (which is cumbersome to use)
|
||||||
|
# - apk get zig pulls in libllvm, which is huge.
|
||||||
|
#
|
||||||
|
# Upstream tarball is statically linked, making it small and convenient to use.
|
||||||
|
RUN apk add make \
|
||||||
|
&& wget https://ziglang.org/download/0.11.0/zig-linux-$(uname -m)-0.11.0.tar.xz \
|
||||||
|
&& tar -xJf zig-linux-*.tar.xz \
|
||||||
|
&& rm zig-linux-*.xz \
|
||||||
|
&& mv zig-linux-* zig
|
||||||
|
|
||||||
WORKDIR inotify-info
|
WORKDIR inotify-info
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN CC="zig cc -target $(uname -m)-linux-musl" \
|
RUN CC="/zig/zig cc -target $(uname -m)-linux-musl" \
|
||||||
CXX="zig c++ -target $(uname -m)-linux-musl" \
|
CXX="/zig/zig c++ -target $(uname -m)-linux-musl" \
|
||||||
make VERBOSE=1
|
make
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
COPY --from=0 /inotify-info/_release/inotify-info /inotify-info
|
COPY --from=0 /inotify-info/_release/inotify-info /inotify-info
|
||||||
|
|
42
Makefile
42
Makefile
|
@ -20,16 +20,11 @@ ifeq ($(CFG), debug)
|
||||||
ASAN ?= 1
|
ASAN ?= 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
BINDIR := $(PREFIX)/bin
|
|
||||||
|
|
||||||
LD = $(CC)
|
LD = $(CC)
|
||||||
RM = rm -f
|
RM = rm -f
|
||||||
MKDIR = mkdir -p
|
MKDIR = mkdir -p
|
||||||
VERBOSE ?= 0
|
VERBOSE ?= 0
|
||||||
|
|
||||||
INOTIFYINFO_VERSION ?= $(shell git describe --tags --dirty 2>/dev/null || echo unknown)
|
|
||||||
|
|
||||||
COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
|
COMPILER = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc)
|
||||||
|
|
||||||
WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow
|
WARNINGS = -Wall -Wextra -Wpedantic -Wmissing-include-dirs -Wformat=2 -Wshadow
|
||||||
|
@ -38,15 +33,10 @@ ifneq ($(COMPILER),clang)
|
||||||
WARNINGS += -Wsuggest-attribute=format -Wall
|
WARNINGS += -Wsuggest-attribute=format -Wall
|
||||||
endif
|
endif
|
||||||
|
|
||||||
DEFINES = -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
|
CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
|
||||||
DEFINES += -DINOTIFYINFO_VERSION=\"$(INOTIFYINFO_VERSION)\"
|
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
|
||||||
|
CXXFLAGS = -fno-rtti -Woverloaded-virtual
|
||||||
CFLAGS += $(WARNINGS) $(DEFINES)
|
LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1
|
||||||
CFLAGS += -std=gnu99 -fno-exceptions
|
|
||||||
|
|
||||||
CXXFLAGS += $(WARNINGS) $(DEFINES)
|
|
||||||
CXXFLAGS += -std=c++11 -fno-exceptions -fno-rtti -Woverloaded-virtual
|
|
||||||
|
|
||||||
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
|
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
|
||||||
|
|
||||||
CFILES = \
|
CFILES = \
|
||||||
|
@ -69,7 +59,6 @@ ifeq ($(ASAN), 1)
|
||||||
ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses.
|
ASAN_FLAGS += -fsanitize=object-size # enable object size checking, detect various out-of-bounds accesses.
|
||||||
ASAN_FLAGS += -fsanitize=alignment # enable alignment checking, detect various misaligned objects;
|
ASAN_FLAGS += -fsanitize=alignment # enable alignment checking, detect various misaligned objects;
|
||||||
CFLAGS += $(ASAN_FLAGS)
|
CFLAGS += $(ASAN_FLAGS)
|
||||||
CXXFLAGS += $(ASAN_FLAGS)
|
|
||||||
LDFLAGS += $(ASAN_FLAGS)
|
LDFLAGS += $(ASAN_FLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -83,6 +72,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
PROJ = $(ODIR)/$(NAME)
|
PROJ = $(ODIR)/$(NAME)
|
||||||
|
$(info Building $(ODIR)/$(NAME)...)
|
||||||
|
|
||||||
ifeq ($(VERBOSE), 1)
|
ifeq ($(VERBOSE), 1)
|
||||||
VERBOSE_PREFIX=
|
VERBOSE_PREFIX=
|
||||||
|
@ -104,16 +94,12 @@ $(ODIR)/$(NAME): $(OBJS)
|
||||||
$(ODIR)/%.o: %.c Makefile
|
$(ODIR)/%.o: %.c Makefile
|
||||||
$(VERBOSE_PREFIX)echo "---- $< ----";
|
$(VERBOSE_PREFIX)echo "---- $< ----";
|
||||||
@$(MKDIR) $(dir $@)
|
@$(MKDIR) $(dir $@)
|
||||||
$(VERBOSE_PREFIX)$(CC) -MMD -MP $(CFLAGS) -o $@ -c $<
|
$(VERBOSE_PREFIX)$(CC) -MMD -MP -std=gnu99 $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
$(ODIR)/%.o: %.cpp Makefile
|
$(ODIR)/%.o: %.cpp Makefile
|
||||||
$(VERBOSE_PREFIX)echo "---- $< ----";
|
$(VERBOSE_PREFIX)echo "---- $< ----";
|
||||||
@$(MKDIR) $(dir $@)
|
@$(MKDIR) $(dir $@)
|
||||||
$(VERBOSE_PREFIX)$(CXX) -MMD -MP $(CXXFLAGS) -o $@ -c $<
|
$(VERBOSE_PREFIX)$(CXX) -MMD -MP -std=c++11 $(CFLAGS) $(CXXFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
.PHONY: lint
|
|
||||||
lint:
|
|
||||||
find . -name '*.h' -o -name '*.c' -o -name '*.cpp' | xargs clang-format -i --style=webkit
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
|
@ -124,18 +110,8 @@ clean:
|
||||||
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d)
|
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.d)
|
||||||
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo)
|
$(VERBOSE_PREFIX)$(RM) $(OBJS:.o=.dwo)
|
||||||
|
|
||||||
.PHONY: install
|
|
||||||
|
|
||||||
install: all
|
|
||||||
install -D $(PROJ) $(BINDIR)/$(NAME)
|
|
||||||
|
|
||||||
.PHONY: uninstall
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
$(RM) $(BINDIR)/$(NAME)
|
|
||||||
|
|
||||||
define RELEASE_RULES
|
define RELEASE_RULES
|
||||||
inotify-info-$(TAG).tar.gz:
|
inotify-info-$(TAG).tar.gz:
|
||||||
git archive --prefix=inotify-info-$(TAG)/ v$(TAG) | gzip -n > $$@
|
git archive --prefix=inotify-info-$(TAG)/ $(TAG) | gzip -n > $$@
|
||||||
endef
|
endef
|
||||||
$(foreach TAG,$(shell git tag 2>/dev/null | sed -n '/^v/ s/^v//p'),$(eval $(RELEASE_RULES)))
|
$(foreach TAG,$(shell git tag 2>/dev/null),$(eval $(RELEASE_RULES)))
|
||||||
|
|
21
README.md
21
README.md
|
@ -22,11 +22,17 @@ Building _debug/inotify-info...
|
||||||
Linking _debug/inotify-info...
|
Linking _debug/inotify-info...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install
|
Or you can build Docker image.
|
||||||
|
|
||||||
The resulting executable will be at `_release/inotify-info`. You are free to
|
```sh
|
||||||
copy the resulting executable to any suitable location in your `$PATH` or run
|
docker build . -t inotify-info
|
||||||
`make install` to install to `/usr/local/bin`.
|
```
|
||||||
|
|
||||||
|
## Install
|
||||||
|
You are free to copy the resulting executable to any suitable location in your `$PATH`.
|
||||||
|
```
|
||||||
|
cp _release/inotify-info /usr/local/bin/
|
||||||
|
```
|
||||||
|
|
||||||
## Run (Prints Summary)
|
## Run (Prints Summary)
|
||||||
```
|
```
|
||||||
|
@ -154,16 +160,12 @@ Searching '/' for listed inodes... (8 threads)
|
||||||
94111468 [10304h] /home/mikesart/.cache/xfce4/xfce4-appfinder/
|
94111468 [10304h] /home/mikesart/.cache/xfce4/xfce4-appfinder/
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run on Docker/podman
|
## Run on Docker
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker build . -t inotify-info
|
|
||||||
docker run --rm --privileged -v /proc:/proc inotify-info
|
docker run --rm --privileged -v /proc:/proc inotify-info
|
||||||
```
|
```
|
||||||
|
|
||||||
When running under [podman][podman] non-root mode, append `--ulimit
|
|
||||||
nofile=65535:65535` to the `podman build` command.
|
|
||||||
|
|
||||||
## Run on Nix(OS)
|
## Run on Nix(OS)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -179,4 +181,3 @@ nix run nixpkgs#inotify-info
|
||||||
[problem2]: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources
|
[problem2]: https://unix.stackexchange.com/questions/15509/whos-consuming-my-inotify-resources
|
||||||
[lfqueue]: https://github.com/Taymindis/lfqueue
|
[lfqueue]: https://github.com/Taymindis/lfqueue
|
||||||
[bsd]: https://github.com/Taymindis/lfqueue/blob/master/LICENSE
|
[bsd]: https://github.com/Taymindis/lfqueue/blob/master/LICENSE
|
||||||
[podman]: https://podman.io/
|
|
||||||
|
|
20
debian/changelog
vendored
20
debian/changelog
vendored
|
@ -1,23 +1,3 @@
|
||||||
inotify-info (0.0.3-1) sid; urgency=medium
|
|
||||||
|
|
||||||
* Uploading to sid.
|
|
||||||
* Merging upstream version 0.0.3.
|
|
||||||
* Removing manual debhelper install file, not needed anymore with new
|
|
||||||
upstream version.
|
|
||||||
* Enabling non-silent output during build.
|
|
||||||
|
|
||||||
-- Daniel Baumann <daniel.baumann@progress-linux.org> Sat, 13 Jul 2024 13:02:30 +0200
|
|
||||||
|
|
||||||
inotify-info (0.0.2-1) sid; urgency=medium
|
|
||||||
|
|
||||||
* Uploading to sid.
|
|
||||||
* Merging upstream version 0.0.2.
|
|
||||||
* Removing march.patch, not needed anymore.
|
|
||||||
* Removing dwz.patch, not needed anymore.
|
|
||||||
* Setting INOTIFYINFO_VERSION to debian package version.
|
|
||||||
|
|
||||||
-- Daniel Baumann <daniel.baumann@progress-linux.org> Mon, 03 Jun 2024 22:01:31 +0200
|
|
||||||
|
|
||||||
inotify-info (0.0.1-2) sid; urgency=medium
|
inotify-info (0.0.1-2) sid; urgency=medium
|
||||||
|
|
||||||
* Uploading to sid.
|
* Uploading to sid.
|
||||||
|
|
2
debian/copyright
vendored
2
debian/copyright
vendored
|
@ -1,7 +1,7 @@
|
||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
Upstream-Name: inotify-info
|
Upstream-Name: inotify-info
|
||||||
Upstream-Contact: https://github.com/mikesart/inotify-info/issues
|
Upstream-Contact: https://github.com/mikesart/inotify-info/issues
|
||||||
Source: https://github.com/mikesart/inotify-info/tags
|
Source: https://github.com/mikesart/inotify-info/releases
|
||||||
|
|
||||||
Files: *
|
Files: *
|
||||||
Copyright: 2021 Michael Sartain <mikesart@fastmail.com>
|
Copyright: 2021 Michael Sartain <mikesart@fastmail.com>
|
||||||
|
|
1
debian/inotify-info.install
vendored
Normal file
1
debian/inotify-info.install
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
_release/inotify-info /usr/bin
|
19
debian/patches/debian/0001-march.patch
vendored
Normal file
19
debian/patches/debian/0001-march.patch
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
|
||||||
|
Description: Building without -march=native (Closes: #1071076).
|
||||||
|
|
||||||
|
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
|
||||||
|
--- inotify-info.orig/Makefile
|
||||||
|
+++ inotify-info/Makefile
|
||||||
|
@@ -33,10 +33,10 @@ ifneq ($(COMPILER),clang)
|
||||||
|
WARNINGS += -Wsuggest-attribute=format -Wall
|
||||||
|
endif
|
||||||
|
|
||||||
|
-CFLAGS = $(WARNINGS) -march=native -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
|
||||||
|
+CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
|
||||||
|
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
|
||||||
|
CXXFLAGS = -fno-rtti -Woverloaded-virtual
|
||||||
|
-LDFLAGS = -march=native -gdwarf-4 -g2 -Wl,--build-id=sha1
|
||||||
|
+LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1
|
||||||
|
LIBS = -Wl,--no-as-needed -lm -ldl -lpthread -lstdc++
|
||||||
|
|
||||||
|
CFILES = \
|
15
debian/patches/debian/0002-dwz.patch
vendored
Normal file
15
debian/patches/debian/0002-dwz.patch
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Author: Daniel Baumann <daniel.baumann@progress-linux.org>
|
||||||
|
Description: Building without -gsplit-dwarf to workaround bug in dwz causing FTBFS (#1016936).
|
||||||
|
|
||||||
|
diff -Naurp inotify-info.orig/Makefile inotify-info/Makefile
|
||||||
|
--- inotify-info.orig/Makefile
|
||||||
|
+++ inotify-info/Makefile
|
||||||
|
@@ -33,7 +33,7 @@ ifneq ($(COMPILER),clang)
|
||||||
|
WARNINGS += -Wsuggest-attribute=format -Wall
|
||||||
|
endif
|
||||||
|
|
||||||
|
-CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames -gsplit-dwarf
|
||||||
|
+CFLAGS = $(WARNINGS) -fno-exceptions -gdwarf-4 -g2 -ggnu-pubnames
|
||||||
|
CFLAGS += -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64
|
||||||
|
CXXFLAGS = -fno-rtti -Woverloaded-virtual
|
||||||
|
LDFLAGS = -gdwarf-4 -g2 -Wl,--build-id=sha1
|
2
debian/patches/series
vendored
Normal file
2
debian/patches/series
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
debian/0001-march.patch
|
||||||
|
debian/0002-dwz.patch
|
8
debian/rules
vendored
8
debian/rules
vendored
|
@ -1,15 +1,7 @@
|
||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
export INOTIFYINFO_VERSION = $(shell dpkg-parsechangelog -SVersion)
|
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh ${@}
|
dh ${@}
|
||||||
|
|
||||||
execute_after_dh_auto_clean:
|
execute_after_dh_auto_clean:
|
||||||
rm -rf _release
|
rm -rf _release
|
||||||
|
|
||||||
override_dh_auto_build:
|
|
||||||
dh_auto_build -- VERBOSE=1
|
|
||||||
|
|
||||||
override_dh_auto_install:
|
|
||||||
dh_auto_install -- PREFIX=$(CURDIR)/debian/inotify-info/usr
|
|
||||||
|
|
359
inotify-info.cpp
359
inotify-info.cpp
|
@ -24,38 +24,34 @@
|
||||||
|
|
||||||
#define _GNU_SOURCE 1
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/statfs.h>
|
|
||||||
#include <sys/sysmacros.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/statfs.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "inotify-info.h"
|
#include "inotify-info.h"
|
||||||
#include "lfqueue/lfqueue.h"
|
#include "lfqueue/lfqueue.h"
|
||||||
|
|
||||||
#ifndef INOTIFYINFO_VERSION
|
|
||||||
#error INOTIFYINFO_VERSION must be set
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO
|
* TODO
|
||||||
* - Comments
|
* - Comments
|
||||||
|
@ -81,7 +77,8 @@ static std::vector<std::string> ignore_dirs;
|
||||||
/*
|
/*
|
||||||
* filename info
|
* filename info
|
||||||
*/
|
*/
|
||||||
struct filename_info_t {
|
struct filename_info_t
|
||||||
|
{
|
||||||
ino64_t inode; // Inode number
|
ino64_t inode; // Inode number
|
||||||
dev_t dev; // Device ID containing file
|
dev_t dev; // Device ID containing file
|
||||||
std::string filename;
|
std::string filename;
|
||||||
|
@ -90,7 +87,8 @@ struct filename_info_t {
|
||||||
/*
|
/*
|
||||||
* inotify process info
|
* inotify process info
|
||||||
*/
|
*/
|
||||||
struct procinfo_t {
|
struct procinfo_t
|
||||||
|
{
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
|
|
||||||
// uid
|
// uid
|
||||||
|
@ -116,7 +114,8 @@ struct procinfo_t {
|
||||||
std::unordered_map< dev_t, std::unordered_set< ino64_t > > dev_map;
|
std::unordered_map< dev_t, std::unordered_set< ino64_t > > dev_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
class lfqueue_wrapper_t {
|
class lfqueue_wrapper_t
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
lfqueue_wrapper_t() { lfqueue_init( &queue ); }
|
lfqueue_wrapper_t() { lfqueue_init( &queue ); }
|
||||||
~lfqueue_wrapper_t() { lfqueue_destroy( &queue ); }
|
~lfqueue_wrapper_t() { lfqueue_destroy( &queue ); }
|
||||||
|
@ -127,7 +126,8 @@ public:
|
||||||
public:
|
public:
|
||||||
typedef long long my_m256i __attribute__((__vector_size__(32), __aligned__(32)));
|
typedef long long my_m256i __attribute__((__vector_size__(32), __aligned__(32)));
|
||||||
|
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
lfqueue_t queue;
|
lfqueue_t queue;
|
||||||
my_m256i align_buf[4]; // Align to 128 bytes
|
my_m256i align_buf[4]; // Align to 128 bytes
|
||||||
};
|
};
|
||||||
|
@ -136,7 +136,8 @@ public:
|
||||||
/*
|
/*
|
||||||
* shared thread data
|
* shared thread data
|
||||||
*/
|
*/
|
||||||
class thread_shared_data_t {
|
class thread_shared_data_t
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
bool init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist );
|
bool init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist );
|
||||||
|
|
||||||
|
@ -150,12 +151,10 @@ public:
|
||||||
/*
|
/*
|
||||||
* thread info
|
* thread info
|
||||||
*/
|
*/
|
||||||
class thread_info_t {
|
class thread_info_t
|
||||||
public:
|
|
||||||
thread_info_t(thread_shared_data_t& tdata_in)
|
|
||||||
: tdata(tdata_in)
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
|
thread_info_t( thread_shared_data_t &tdata_in ) : tdata( tdata_in ) {}
|
||||||
~thread_info_t() {}
|
~thread_info_t() {}
|
||||||
|
|
||||||
void queue_directory( char *path );
|
void queue_directory( char *path );
|
||||||
|
@ -182,7 +181,8 @@ public:
|
||||||
* getdents64 syscall
|
* getdents64 syscall
|
||||||
*/
|
*/
|
||||||
GCC_DIAG_PUSH_OFF( pedantic )
|
GCC_DIAG_PUSH_OFF( pedantic )
|
||||||
struct linux_dirent64 {
|
struct linux_dirent64
|
||||||
|
{
|
||||||
uint64_t d_ino; // Inode number
|
uint64_t d_ino; // Inode number
|
||||||
int64_t d_off; // Offset to next linux_dirent
|
int64_t d_off; // Offset to next linux_dirent
|
||||||
unsigned short d_reclen; // Length of this linux_dirent
|
unsigned short d_reclen; // Length of this linux_dirent
|
||||||
|
@ -209,11 +209,13 @@ std::string string_formatv(const char* fmt, va_list ap)
|
||||||
std::string str;
|
std::string str;
|
||||||
int size = 512;
|
int size = 512;
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
str.resize( size );
|
str.resize( size );
|
||||||
int n = vsnprintf( ( char * )str.c_str(), size, fmt, ap );
|
int n = vsnprintf( ( char * )str.c_str(), size, fmt, ap );
|
||||||
|
|
||||||
if ((n > -1) && (n < size)) {
|
if ( ( n > -1 ) && ( n < size ) )
|
||||||
|
{
|
||||||
str.resize( n );
|
str.resize( n );
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +242,8 @@ static std::string get_link_name(const char* pathname)
|
||||||
char filename[ PATH_MAX + 1 ];
|
char filename[ PATH_MAX + 1 ];
|
||||||
|
|
||||||
ssize_t ret = readlink( pathname, filename, sizeof( filename ) );
|
ssize_t ret = readlink( pathname, filename, sizeof( filename ) );
|
||||||
if ((ret > 0) && (ret < (ssize_t)sizeof(filename))) {
|
if ( ( ret > 0 ) && ( ret < ( ssize_t )sizeof( filename ) ) )
|
||||||
|
{
|
||||||
filename[ ret ] = 0;
|
filename[ ret ] = 0;
|
||||||
Result = filename;
|
Result = filename;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +254,8 @@ static uid_t get_uid(const char* pathname)
|
||||||
{
|
{
|
||||||
int fd = open( pathname, O_RDONLY, 0 );
|
int fd = open( pathname, O_RDONLY, 0 );
|
||||||
|
|
||||||
if (fd >= 0) {
|
if ( fd >= 0 )
|
||||||
|
{
|
||||||
char buf[ 16 * 1024 ];
|
char buf[ 16 * 1024 ];
|
||||||
|
|
||||||
ssize_t len = read( fd, buf, sizeof( buf ) );
|
ssize_t len = read( fd, buf, sizeof( buf ) );
|
||||||
|
@ -259,11 +263,13 @@ static uid_t get_uid(const char* pathname)
|
||||||
close( fd );
|
close( fd );
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
if (len > 0) {
|
if ( len > 0 )
|
||||||
|
{
|
||||||
buf[ len - 1 ] = 0;
|
buf[ len - 1 ] = 0;
|
||||||
|
|
||||||
const char *uidstr = strstr( buf, "\nUid:" );
|
const char *uidstr = strstr( buf, "\nUid:" );
|
||||||
if (uidstr) {
|
if ( uidstr )
|
||||||
|
{
|
||||||
return atoll( uidstr + 5 );
|
return atoll( uidstr + 5 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -284,12 +290,14 @@ static uint32_t inotify_parse_fdinfo_file(procinfo_t& procinfo, const char* fdse
|
||||||
uint32_t watch_count = 0;
|
uint32_t watch_count = 0;
|
||||||
|
|
||||||
FILE *fp = fopen( fdset_name, "r" );
|
FILE *fp = fopen( fdset_name, "r" );
|
||||||
if (fp) {
|
if ( fp )
|
||||||
|
{
|
||||||
char line_buf[ 256 ];
|
char line_buf[ 256 ];
|
||||||
|
|
||||||
procinfo.fdset_filenames.push_back( fdset_name );
|
procinfo.fdset_filenames.push_back( fdset_name );
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
if ( !fgets( line_buf, sizeof( line_buf ), fp ) )
|
if ( !fgets( line_buf, sizeof( line_buf ), fp ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -301,13 +309,15 @@ static uint32_t inotify_parse_fdinfo_file(procinfo_t& procinfo, const char* fdse
|
||||||
* ino: 5865
|
* ino: 5865
|
||||||
* inotify wd:1 ino:80001 sdev:800011 mask:100 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01000800bc1b8c7c
|
* inotify wd:1 ino:80001 sdev:800011 mask:100 ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01000800bc1b8c7c
|
||||||
*/
|
*/
|
||||||
if (!strncmp(line_buf, "inotify ", 8)) {
|
if ( !strncmp( line_buf, "inotify ", 8 ) )
|
||||||
|
{
|
||||||
watch_count++;
|
watch_count++;
|
||||||
|
|
||||||
uint64_t inode_val = get_token_val( line_buf, "ino:" );
|
uint64_t inode_val = get_token_val( line_buf, "ino:" );
|
||||||
uint64_t sdev_val = get_token_val( line_buf, "sdev:" );
|
uint64_t sdev_val = get_token_val( line_buf, "sdev:" );
|
||||||
|
|
||||||
if (inode_val) {
|
if ( inode_val )
|
||||||
|
{
|
||||||
// https://unix.stackexchange.com/questions/645937/listing-the-files-that-are-being-watched-by-inotify-instances
|
// https://unix.stackexchange.com/questions/645937/listing-the-files-that-are-being-watched-by-inotify-instances
|
||||||
// Assuming that the sdev field is encoded according to Linux's so-called "huge
|
// Assuming that the sdev field is encoded according to Linux's so-called "huge
|
||||||
// encoding", which uses 20 bits (instead of 8) for minor numbers, in bitwise
|
// encoding", which uses 20 bits (instead of 8) for minor numbers, in bitwise
|
||||||
|
@ -335,16 +345,19 @@ static void inotify_parse_fddir(procinfo_t& procinfo)
|
||||||
if ( !dir_fd )
|
if ( !dir_fd )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
struct dirent *dp_fd = readdir( dir_fd );
|
struct dirent *dp_fd = readdir( dir_fd );
|
||||||
if ( !dp_fd )
|
if ( !dp_fd )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((dp_fd->d_type == DT_LNK) && isdigit(dp_fd->d_name[0])) {
|
if ( ( dp_fd->d_type == DT_LNK ) && isdigit( dp_fd->d_name[ 0 ] ) )
|
||||||
|
{
|
||||||
filename = string_format( "/proc/%d/fd/%s", procinfo.pid, dp_fd->d_name );
|
filename = string_format( "/proc/%d/fd/%s", procinfo.pid, dp_fd->d_name );
|
||||||
filename = get_link_name( filename.c_str() );
|
filename = get_link_name( filename.c_str() );
|
||||||
|
|
||||||
if (filename == "anon_inode:inotify" || filename == "inotify") {
|
if ( filename == "anon_inode:inotify" || filename == "inotify" )
|
||||||
|
{
|
||||||
filename = string_format( "/proc/%d/fdinfo/%s", procinfo.pid, dp_fd->d_name );
|
filename = string_format( "/proc/%d/fdinfo/%s", procinfo.pid, dp_fd->d_name );
|
||||||
|
|
||||||
procinfo.instances++;
|
procinfo.instances++;
|
||||||
|
@ -368,9 +381,11 @@ char* thread_info_t::dequeue_directory()
|
||||||
{
|
{
|
||||||
char *path = tdata.dirqueues[ idx ].dequeue_directory();
|
char *path = tdata.dirqueues[ idx ].dequeue_directory();
|
||||||
|
|
||||||
if (!path) {
|
if ( !path )
|
||||||
|
{
|
||||||
// Nothing on our queue, check queues on other threads
|
// Nothing on our queue, check queues on other threads
|
||||||
for (lfqueue_wrapper_t& dirq : tdata.dirqueues) {
|
for ( lfqueue_wrapper_t &dirq : tdata.dirqueues )
|
||||||
|
{
|
||||||
path = dirq.dequeue_directory();
|
path = dirq.dequeue_directory();
|
||||||
if ( path )
|
if ( path )
|
||||||
break;
|
break;
|
||||||
|
@ -388,8 +403,9 @@ struct statx mystatx(const char* filename, unsigned int mask = 0)
|
||||||
struct statx statxbuf;
|
struct statx statxbuf;
|
||||||
int flags = AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC;
|
int flags = AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC;
|
||||||
|
|
||||||
if (statx(0, filename, flags, mask, &statxbuf) == -1) {
|
if ( statx( 0, filename, flags, mask, &statxbuf ) == -1 )
|
||||||
printf("ERROR: statx-ino( %s ) failed. Errno: %d (%s)\n", filename, errno, strerror(errno));
|
{
|
||||||
|
printf( "ERROR: statx-ino( %s ) failed. Errno: %d\n", filename, errno );
|
||||||
memset( &statxbuf, 0, sizeof( statxbuf ) );
|
memset( &statxbuf, 0, sizeof( statxbuf ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,8 +433,9 @@ static dev_t stat_get_dev_t(const char* filename)
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
int ret = stat( filename, &statbuf );
|
int ret = stat( filename, &statbuf );
|
||||||
if (ret == -1) {
|
if ( ret == -1 )
|
||||||
printf("ERROR: stat-dev_t( %s ) failed. Errno: %d (%s)\n", filename, errno, strerror(errno));
|
{
|
||||||
|
printf( "ERROR: stat-dev_t( %s ) failed. Errno: %d\n", filename, errno );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return statbuf.st_dev;
|
return statbuf.st_dev;
|
||||||
|
@ -429,8 +446,9 @@ static uint64_t stat_get_ino(const char* filename)
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
int ret = stat( filename, &statbuf );
|
int ret = stat( filename, &statbuf );
|
||||||
if (ret == -1) {
|
if ( ret == -1 )
|
||||||
printf("ERROR: stat-ino( %s ) failed. Errno: %d (%s)\n", filename, errno, strerror(errno));
|
{
|
||||||
|
printf( "ERROR: stat-ino( %s ) failed. Errno: %d\n", filename, errno );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,14 +461,16 @@ void thread_info_t::add_filename(ino64_t inode, const char* path, const char* d_
|
||||||
{
|
{
|
||||||
auto it = tdata.inode_set.find( inode );
|
auto it = tdata.inode_set.find( inode );
|
||||||
|
|
||||||
if (it != tdata.inode_set.end()) {
|
if ( it != tdata.inode_set.end() )
|
||||||
|
{
|
||||||
const std::unordered_set< dev_t > &dev_set = it->second;
|
const std::unordered_set< dev_t > &dev_set = it->second;
|
||||||
|
|
||||||
std::string filename = std::string( path ) + d_name;
|
std::string filename = std::string( path ) + d_name;
|
||||||
dev_t dev = stat_get_dev_t( filename.c_str() );
|
dev_t dev = stat_get_dev_t( filename.c_str() );
|
||||||
|
|
||||||
// Make sure the inode AND device ID match before adding.
|
// Make sure the inode AND device ID match before adding.
|
||||||
if (dev_set.find(dev) != dev_set.end()) {
|
if ( dev_set.find( dev ) != dev_set.end() )
|
||||||
|
{
|
||||||
filename_info_t fname;
|
filename_info_t fname;
|
||||||
|
|
||||||
fname.filename = is_dir ? filename + "/" : filename;
|
fname.filename = is_dir ? filename + "/" : filename;
|
||||||
|
@ -464,7 +484,8 @@ void thread_info_t::add_filename(ino64_t inode, const char* path, const char* d_
|
||||||
|
|
||||||
static bool is_dot_dir( const char *dname )
|
static bool is_dot_dir( const char *dname )
|
||||||
{
|
{
|
||||||
if (dname[0] == '.') {
|
if ( dname[ 0 ] == '.' )
|
||||||
|
{
|
||||||
if ( !dname[ 1 ] )
|
if ( !dname[ 1 ] )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -490,8 +511,10 @@ static bool is_proc_dir(const char* path, const char* d_name)
|
||||||
struct statfs s;
|
struct statfs s;
|
||||||
std::string filename = std::string( path ) + d_name;
|
std::string filename = std::string( path ) + d_name;
|
||||||
|
|
||||||
if (statfs(filename.c_str(), &s) == 0) {
|
if ( statfs(filename.c_str(), &s ) == 0 )
|
||||||
switch (s.f_type) {
|
{
|
||||||
|
switch ( s.f_type )
|
||||||
|
{
|
||||||
case PROC_SUPER_MAGIC:
|
case PROC_SUPER_MAGIC:
|
||||||
case FUSE_SUPER_MAGIC:
|
case FUSE_SUPER_MAGIC:
|
||||||
return true;
|
return true;
|
||||||
|
@ -507,13 +530,17 @@ int thread_info_t::parse_dirqueue_entry()
|
||||||
char __attribute__( ( aligned( 16 ) ) ) buf[ 1024 ];
|
char __attribute__( ( aligned( 16 ) ) ) buf[ 1024 ];
|
||||||
|
|
||||||
char *path = dequeue_directory();
|
char *path = dequeue_directory();
|
||||||
if (!path) {
|
if ( !path )
|
||||||
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::string& dname : ignore_dirs) {
|
for ( std::string &dname : ignore_dirs )
|
||||||
if (dname == path) {
|
{
|
||||||
if (g_verbose > 1) {
|
if ( dname == path )
|
||||||
|
{
|
||||||
|
if ( g_verbose > 1 )
|
||||||
|
{
|
||||||
printf( "Ignoring '%s'\n", path );
|
printf( "Ignoring '%s'\n", path );
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -521,7 +548,8 @@ int thread_info_t::parse_dirqueue_entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = open( path, O_RDONLY | O_DIRECTORY, 0 );
|
int fd = open( path, O_RDONLY | O_DIRECTORY, 0 );
|
||||||
if (fd < 0) {
|
if ( fd < 0 )
|
||||||
|
{
|
||||||
free( path );
|
free( path );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -530,27 +558,32 @@ int thread_info_t::parse_dirqueue_entry()
|
||||||
|
|
||||||
size_t pathlen = strlen( path );
|
size_t pathlen = strlen( path );
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
int ret = sys_getdents64( fd, buf, sizeof( buf ) );
|
int ret = sys_getdents64( fd, buf, sizeof( buf ) );
|
||||||
|
|
||||||
if (ret < 0) {
|
if ( ret < 0 )
|
||||||
|
{
|
||||||
bool spew_error = true;
|
bool spew_error = true;
|
||||||
|
|
||||||
if ((errno == 5) && !strncmp(path, "/sys/kernel/", 12)) {
|
if ( ( errno == 5 ) && !strncmp( path, "/sys/kernel/", 12 ) )
|
||||||
|
{
|
||||||
// In docker container we can get permission denied errors in /sys/kernel. Ignore them.
|
// In docker container we can get permission denied errors in /sys/kernel. Ignore them.
|
||||||
// https://github.com/mikesart/inotify-info/issues/16
|
// https://github.com/mikesart/inotify-info/issues/16
|
||||||
spew_error = false;
|
spew_error = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spew_error) {
|
if ( spew_error )
|
||||||
printf("ERROR: sys_getdents64 failed on '%s': %d errno: %d (%s)\n", path, ret, errno, strerror(errno));
|
{
|
||||||
|
printf( "ERROR: sys_getdents64 failed on '%s': %d errno:%d\n", path, ret, errno );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( ret == 0 )
|
if ( ret == 0 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (int bpos = 0; bpos < ret;) {
|
for ( int bpos = 0; bpos < ret; )
|
||||||
|
{
|
||||||
struct linux_dirent64 *dirp = ( struct linux_dirent64 * )( buf + bpos );
|
struct linux_dirent64 *dirp = ( struct linux_dirent64 * )( buf + bpos );
|
||||||
const char *d_name = dirp->d_name;
|
const char *d_name = dirp->d_name;
|
||||||
|
|
||||||
|
@ -562,18 +595,22 @@ int thread_info_t::parse_dirqueue_entry()
|
||||||
|
|
||||||
// DT_REG This is a regular file.
|
// DT_REG This is a regular file.
|
||||||
// DT_LNK This is a symbolic link.
|
// DT_LNK This is a symbolic link.
|
||||||
if (dirp->d_type == DT_REG || dirp->d_type == DT_LNK) {
|
if ( dirp->d_type == DT_REG || dirp->d_type == DT_LNK )
|
||||||
|
{
|
||||||
add_filename( dirp->d_ino, path, d_name, false );
|
add_filename( dirp->d_ino, path, d_name, false );
|
||||||
}
|
}
|
||||||
// DT_DIR This is a directory.
|
// DT_DIR This is a directory.
|
||||||
else if (dirp->d_type == DT_DIR) {
|
else if ( dirp->d_type == DT_DIR )
|
||||||
if (!is_dot_dir(d_name) && !is_proc_dir(path, d_name)) {
|
{
|
||||||
|
if ( !is_dot_dir( d_name ) && !is_proc_dir( path, d_name ) )
|
||||||
|
{
|
||||||
add_filename( dirp->d_ino, path, d_name, true );
|
add_filename( dirp->d_ino, path, d_name, true );
|
||||||
|
|
||||||
size_t len = strlen( d_name );
|
size_t len = strlen( d_name );
|
||||||
char *newpath = ( char * )malloc( pathlen + len + 2 );
|
char *newpath = ( char * )malloc( pathlen + len + 2 );
|
||||||
|
|
||||||
if (newpath) {
|
if ( newpath )
|
||||||
|
{
|
||||||
strcpy( newpath, path );
|
strcpy( newpath, path );
|
||||||
strcpy( newpath + pathlen, d_name );
|
strcpy( newpath + pathlen, d_name );
|
||||||
newpath[ pathlen + len ] = '/';
|
newpath[ pathlen + len ] = '/';
|
||||||
|
@ -597,7 +634,8 @@ static void* parse_dirqueue_threadproc(void* arg)
|
||||||
{
|
{
|
||||||
thread_info_t *pthread_info = ( thread_info_t * )arg;
|
thread_info_t *pthread_info = ( thread_info_t * )arg;
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
// Loop until all the dequeue(s) fail
|
// Loop until all the dequeue(s) fail
|
||||||
if ( pthread_info->parse_dirqueue_entry() == -1 )
|
if ( pthread_info->parse_dirqueue_entry() == -1 )
|
||||||
break;
|
break;
|
||||||
|
@ -608,7 +646,8 @@ static void* parse_dirqueue_threadproc(void* arg)
|
||||||
|
|
||||||
static bool is_proc_in_cmdline_applist( const procinfo_t &procinfo, std::vector< std::string > &cmdline_applist )
|
static bool is_proc_in_cmdline_applist( const procinfo_t &procinfo, std::vector< std::string > &cmdline_applist )
|
||||||
{
|
{
|
||||||
for (const std::string& str : cmdline_applist) {
|
for ( const std::string &str : cmdline_applist )
|
||||||
|
{
|
||||||
// Check if our command line string is a subset of this appname
|
// Check if our command line string is a subset of this appname
|
||||||
if ( strstr( procinfo.appname.c_str(), str.c_str() ) )
|
if ( strstr( procinfo.appname.c_str(), str.c_str() ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -626,21 +665,25 @@ static bool watch_count_is_greater(procinfo_t elem1, procinfo_t elem2)
|
||||||
return elem1.watches > elem2.watches;
|
return elem1.watches > elem2.watches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool init_inotify_proclist( std::vector< procinfo_t > &inotify_proclist )
|
static bool init_inotify_proclist( std::vector< procinfo_t > &inotify_proclist )
|
||||||
{
|
{
|
||||||
DIR *dir_proc = opendir( "/proc" );
|
DIR *dir_proc = opendir( "/proc" );
|
||||||
|
|
||||||
if (!dir_proc) {
|
if ( !dir_proc )
|
||||||
printf("ERROR: opendir /proc failed: %d (%s)\n", errno, strerror(errno));
|
{
|
||||||
|
printf( "ERROR: opendir /proc failed: %d\n", errno );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
struct dirent *dp_proc = readdir( dir_proc );
|
struct dirent *dp_proc = readdir( dir_proc );
|
||||||
if ( !dp_proc )
|
if ( !dp_proc )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((dp_proc->d_type == DT_DIR) && isdigit(dp_proc->d_name[0])) {
|
if ( ( dp_proc->d_type == DT_DIR ) && isdigit( dp_proc->d_name[ 0 ] ) )
|
||||||
|
{
|
||||||
procinfo_t procinfo;
|
procinfo_t procinfo;
|
||||||
|
|
||||||
procinfo.pid = atoll( dp_proc->d_name );
|
procinfo.pid = atoll( dp_proc->d_name );
|
||||||
|
@ -649,12 +692,14 @@ static bool init_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
|
||||||
std::string status = string_format( "/proc/%d/status", procinfo.pid );
|
std::string status = string_format( "/proc/%d/status", procinfo.pid );
|
||||||
procinfo.uid = get_uid( status.c_str() );
|
procinfo.uid = get_uid( status.c_str() );
|
||||||
procinfo.executable = get_link_name( executable.c_str() );
|
procinfo.executable = get_link_name( executable.c_str() );
|
||||||
if (!procinfo.executable.empty()) {
|
if ( !procinfo.executable.empty() )
|
||||||
|
{
|
||||||
procinfo.appname = basename( (char*)procinfo.executable.c_str() );
|
procinfo.appname = basename( (char*)procinfo.executable.c_str() );
|
||||||
|
|
||||||
inotify_parse_fddir( procinfo );
|
inotify_parse_fddir( procinfo );
|
||||||
|
|
||||||
if (procinfo.instances) {
|
if ( procinfo.instances )
|
||||||
|
{
|
||||||
inotify_proclist.push_back( procinfo );
|
inotify_proclist.push_back( procinfo );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,7 +715,8 @@ static bool init_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
|
||||||
// https://stackoverflow.com/questions/1449805/how-to-format-a-number-using-comma-as-thousands-separator-in-c
|
// https://stackoverflow.com/questions/1449805/how-to-format-a-number-using-comma-as-thousands-separator-in-c
|
||||||
size_t str_format_uint32( char dst[16], uint32_t num )
|
size_t str_format_uint32( char dst[16], uint32_t num )
|
||||||
{
|
{
|
||||||
if (thousands_sep) {
|
if ( thousands_sep )
|
||||||
|
{
|
||||||
char src[16];
|
char src[16];
|
||||||
char *p_src = src;
|
char *p_src = src;
|
||||||
char *p_dst = dst;
|
char *p_dst = dst;
|
||||||
|
@ -678,7 +724,8 @@ size_t str_format_uint32(char dst[16], uint32_t num)
|
||||||
|
|
||||||
num_len = sprintf(src, "%u", num);
|
num_len = sprintf(src, "%u", num);
|
||||||
|
|
||||||
for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3) {
|
for (commas = 2 - num_len % 3; *p_src; commas = (commas + 1) % 3)
|
||||||
|
{
|
||||||
*p_dst++ = *p_src++;
|
*p_dst++ = *p_src++;
|
||||||
if (commas == 1) {
|
if (commas == 1) {
|
||||||
*p_dst++ = thousands_sep;
|
*p_dst++ = thousands_sep;
|
||||||
|
@ -739,7 +786,9 @@ static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
|
||||||
printf( "%s%*s %-*s %*s %*s%s\n",
|
printf( "%s%*s %-*s %*s %*s%s\n",
|
||||||
BCYAN, lenPid, "Pid", lenUid, "Uid", lenApp, "App", lenInstances, "Instances", RESET);
|
BCYAN, lenPid, "Pid", lenUid, "Uid", lenApp, "App", lenInstances, "Instances", RESET);
|
||||||
|
|
||||||
for (procinfo_t& procinfo : inotify_proclist) {
|
|
||||||
|
for ( procinfo_t &procinfo : inotify_proclist )
|
||||||
|
{
|
||||||
char watches_str[16];
|
char watches_str[16];
|
||||||
|
|
||||||
str_format_uint32(watches_str, procinfo.watches);
|
str_format_uint32(watches_str, procinfo.watches);
|
||||||
|
@ -758,18 +807,23 @@ static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
|
||||||
BYELLOW, lenApp, procinfo.appname.c_str(), RESET,
|
BYELLOW, lenApp, procinfo.appname.c_str(), RESET,
|
||||||
lenInstances, procinfo.instances );
|
lenInstances, procinfo.instances );
|
||||||
|
|
||||||
if (g_verbose > 1) {
|
if ( g_verbose > 1 )
|
||||||
for (std::string& fname : procinfo.fdset_filenames) {
|
{
|
||||||
|
for ( std::string &fname : procinfo.fdset_filenames )
|
||||||
|
{
|
||||||
printf( " %s%s%s\n", CYAN, fname.c_str(), RESET );
|
printf( " %s%s%s\n", CYAN, fname.c_str(), RESET );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (procinfo.in_cmd_line) {
|
if ( procinfo.in_cmd_line )
|
||||||
for (const auto& it1 : procinfo.dev_map) {
|
{
|
||||||
|
for ( const auto &it1 : procinfo.dev_map )
|
||||||
|
{
|
||||||
dev_t dev = it1.first;
|
dev_t dev = it1.first;
|
||||||
|
|
||||||
printf( "%s[%u.%u]:%s", BGRAY, major( dev ), minor( dev ), RESET );
|
printf( "%s[%u.%u]:%s", BGRAY, major( dev ), minor( dev ), RESET );
|
||||||
for (const auto& it2 : it1.second) {
|
for ( const auto &it2 : it1.second )
|
||||||
|
{
|
||||||
std::string inode_device_str = string_format( "%lu", it2 );
|
std::string inode_device_str = string_format( "%lu", it2 );
|
||||||
|
|
||||||
printf( " %s%s%s", BGRAY, inode_device_str.c_str(), RESET );
|
printf( " %s%s%s", BGRAY, inode_device_str.c_str(), RESET );
|
||||||
|
@ -782,20 +836,24 @@ static void print_inotify_proclist(std::vector<procinfo_t>& inotify_proclist)
|
||||||
|
|
||||||
bool thread_shared_data_t::init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist )
|
bool thread_shared_data_t::init( uint32_t numthreads, const std::vector< procinfo_t > &inotify_proclist )
|
||||||
{
|
{
|
||||||
for (const procinfo_t& procinfo : inotify_proclist) {
|
for ( const procinfo_t &procinfo : inotify_proclist )
|
||||||
|
{
|
||||||
if ( !procinfo.in_cmd_line )
|
if ( !procinfo.in_cmd_line )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (const auto& it1 : procinfo.dev_map) {
|
for ( const auto &it1 : procinfo.dev_map )
|
||||||
|
{
|
||||||
dev_t dev = it1.first;
|
dev_t dev = it1.first;
|
||||||
|
|
||||||
for (const auto& inode : it1.second) {
|
for ( const auto &inode : it1.second )
|
||||||
|
{
|
||||||
inode_set[ inode ].insert( dev );
|
inode_set[ inode ].insert( dev );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inode_set.empty()) {
|
if ( !inode_set.empty() )
|
||||||
|
{
|
||||||
dirqueues.resize( numthreads );
|
dirqueues.resize( numthreads );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,18 +875,22 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
|
||||||
// Initialize thread_info_t array
|
// Initialize thread_info_t array
|
||||||
std::vector< class thread_info_t > thread_array( g_numthreads, thread_info_t( tdata ) );
|
std::vector< class thread_info_t > thread_array( g_numthreads, thread_info_t( tdata ) );
|
||||||
|
|
||||||
for (uint32_t idx = 0; idx < thread_array.size(); idx++) {
|
for ( uint32_t idx = 0; idx < thread_array.size(); idx++ )
|
||||||
|
{
|
||||||
thread_info_t &thread_info = thread_array[ idx ];
|
thread_info_t &thread_info = thread_array[ idx ];
|
||||||
|
|
||||||
thread_info.idx = idx;
|
thread_info.idx = idx;
|
||||||
|
|
||||||
if (idx == 0) {
|
if ( idx == 0 )
|
||||||
|
{
|
||||||
// Add root dir in case someone is watching it
|
// Add root dir in case someone is watching it
|
||||||
thread_info.add_filename( stat_get_ino( "/" ), "/", "", false );
|
thread_info.add_filename( stat_get_ino( "/" ), "/", "", false );
|
||||||
// Add and parse root
|
// Add and parse root
|
||||||
thread_info.queue_directory( strdup( "/" ) );
|
thread_info.queue_directory( strdup( "/" ) );
|
||||||
thread_info.parse_dirqueue_entry();
|
thread_info.parse_dirqueue_entry();
|
||||||
} else if (pthread_create(&thread_info.pthread_id, NULL, &parse_dirqueue_threadproc, &thread_info)) {
|
}
|
||||||
|
else if ( pthread_create( &thread_info.pthread_id, NULL, &parse_dirqueue_threadproc, &thread_info ) )
|
||||||
|
{
|
||||||
printf( "Warning: pthread_create failed. errno: %d\n", errno );
|
printf( "Warning: pthread_create failed. errno: %d\n", errno );
|
||||||
thread_info.pthread_id = 0;
|
thread_info.pthread_id = 0;
|
||||||
}
|
}
|
||||||
|
@ -838,16 +900,20 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
|
||||||
parse_dirqueue_threadproc( &thread_array[ 0 ] );
|
parse_dirqueue_threadproc( &thread_array[ 0 ] );
|
||||||
|
|
||||||
uint32_t total_scanned_dirs = 0;
|
uint32_t total_scanned_dirs = 0;
|
||||||
for (const thread_info_t& thread_info : thread_array) {
|
for ( const thread_info_t &thread_info : thread_array )
|
||||||
if (thread_info.pthread_id) {
|
{
|
||||||
if (g_verbose > 1) {
|
if ( thread_info.pthread_id )
|
||||||
|
{
|
||||||
|
if ( g_verbose > 1 )
|
||||||
|
{
|
||||||
printf( "Waiting for thread #%zu\n", thread_info.pthread_id );
|
printf( "Waiting for thread #%zu\n", thread_info.pthread_id );
|
||||||
}
|
}
|
||||||
|
|
||||||
void *status = NULL;
|
void *status = NULL;
|
||||||
int rc = pthread_join( thread_info.pthread_id, &status );
|
int rc = pthread_join( thread_info.pthread_id, &status );
|
||||||
|
|
||||||
if (g_verbose > 1) {
|
if ( g_verbose > 1 )
|
||||||
|
{
|
||||||
printf( "Thread #%zu rc=%d status=%d\n", thread_info.pthread_id, rc, ( int )( intptr_t )status );
|
printf( "Thread #%zu rc=%d status=%d\n", thread_info.pthread_id, rc, ( int )( intptr_t )status );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -858,7 +924,8 @@ static uint32_t find_files_in_inode_set(const std::vector<procinfo_t>& inotify_p
|
||||||
all_found_files.insert( all_found_files.end(),
|
all_found_files.insert( all_found_files.end(),
|
||||||
thread_info.found_files.begin(), thread_info.found_files.end() );
|
thread_info.found_files.begin(), thread_info.found_files.end() );
|
||||||
|
|
||||||
if (g_verbose > 1) {
|
if ( g_verbose > 1 )
|
||||||
|
{
|
||||||
printf( "Thread #%zu: %u dirs, %zu files found\n",
|
printf( "Thread #%zu: %u dirs, %zu files found\n",
|
||||||
thread_info.pthread_id, thread_info.scanned_dirs, thread_info.found_files.size() );
|
thread_info.pthread_id, thread_info.scanned_dirs, thread_info.found_files.size() );
|
||||||
}
|
}
|
||||||
|
@ -886,8 +953,10 @@ static uint32_t get_inotify_procfs_value(const std::string& fname)
|
||||||
std::string filename = "/proc/sys/fs/inotify/" + fname;
|
std::string filename = "/proc/sys/fs/inotify/" + fname;
|
||||||
|
|
||||||
int fd = open( filename.c_str(), O_RDONLY );
|
int fd = open( filename.c_str(), O_RDONLY );
|
||||||
if (fd >= 0) {
|
if ( fd >= 0 )
|
||||||
if (read(fd, buf, sizeof(buf)) > 0) {
|
{
|
||||||
|
if ( read( fd, buf, sizeof( buf ) ) > 0 )
|
||||||
|
{
|
||||||
val = strtoul( buf, nullptr, 10 );
|
val = strtoul( buf, nullptr, 10 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,14 +968,16 @@ static uint32_t get_inotify_procfs_value(const std::string& fname)
|
||||||
|
|
||||||
static void print_inotify_limits()
|
static void print_inotify_limits()
|
||||||
{
|
{
|
||||||
const std::vector<std::string> filenames = {
|
const std::vector< std::string > filenames =
|
||||||
|
{
|
||||||
"max_queued_events",
|
"max_queued_events",
|
||||||
"max_user_instances",
|
"max_user_instances",
|
||||||
"max_user_watches"
|
"max_user_watches"
|
||||||
};
|
};
|
||||||
|
|
||||||
printf( "%sINotify Limits:%s\n", BCYAN, RESET );
|
printf( "%sINotify Limits:%s\n", BCYAN, RESET );
|
||||||
for (const std::string& fname : filenames) {
|
for ( const std::string &fname : filenames )
|
||||||
|
{
|
||||||
char str[16];
|
char str[16];
|
||||||
uint32_t val = get_inotify_procfs_value( fname );
|
uint32_t val = get_inotify_procfs_value( fname );
|
||||||
|
|
||||||
|
@ -921,30 +992,42 @@ static uint32_t parse_config_file(const char* config_file)
|
||||||
uint32_t dir_count = 0;
|
uint32_t dir_count = 0;
|
||||||
|
|
||||||
FILE *fp = fopen( config_file, "r" );
|
FILE *fp = fopen( config_file, "r" );
|
||||||
if (fp) {
|
if ( fp )
|
||||||
|
{
|
||||||
char line_buf[ 8192 ];
|
char line_buf[ 8192 ];
|
||||||
bool in_ignore_dirs_section = false;
|
bool in_ignore_dirs_section = false;
|
||||||
|
|
||||||
for (;;) {
|
for ( ;; )
|
||||||
|
{
|
||||||
if ( !fgets( line_buf, sizeof( line_buf ) - 1, fp ) )
|
if ( !fgets( line_buf, sizeof( line_buf ) - 1, fp ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (line_buf[0] == '#') {
|
if ( line_buf[0] == '#' )
|
||||||
|
{
|
||||||
// comment
|
// comment
|
||||||
} else if (!in_ignore_dirs_section) {
|
}
|
||||||
|
else if ( !in_ignore_dirs_section )
|
||||||
|
{
|
||||||
size_t len = strcspn( line_buf, "\r\n" );
|
size_t len = strcspn( line_buf, "\r\n" );
|
||||||
|
|
||||||
if ((len == 12) && !strncmp("[ignoredirs]", line_buf, 12)) {
|
if ( ( len == 12 ) && !strncmp( "[ignoredirs]", line_buf, 12 ) )
|
||||||
|
{
|
||||||
in_ignore_dirs_section = true;
|
in_ignore_dirs_section = true;
|
||||||
}
|
}
|
||||||
} else if (line_buf[0] == '[') {
|
}
|
||||||
|
else if ( line_buf[ 0 ] == '[' )
|
||||||
|
{
|
||||||
in_ignore_dirs_section = false;
|
in_ignore_dirs_section = false;
|
||||||
} else if (in_ignore_dirs_section && (line_buf[0] == '/')) {
|
}
|
||||||
|
else if ( in_ignore_dirs_section && ( line_buf[ 0 ] == '/' ) )
|
||||||
|
{
|
||||||
size_t len = strcspn( line_buf, "\r\n" );
|
size_t len = strcspn( line_buf, "\r\n" );
|
||||||
|
|
||||||
if (len > 1) {
|
if ( len > 1 )
|
||||||
|
{
|
||||||
line_buf[ len ] = 0;
|
line_buf[ len ] = 0;
|
||||||
if (line_buf[len - 1] != '/') {
|
if ( line_buf[ len - 1 ] != '/' )
|
||||||
|
{
|
||||||
line_buf[ len ] = '/';
|
line_buf[ len ] = '/';
|
||||||
line_buf[ len + 1 ] = '\0';
|
line_buf[ len + 1 ] = '\0';
|
||||||
}
|
}
|
||||||
|
@ -966,7 +1049,8 @@ static bool parse_ignore_dirs_file()
|
||||||
const std::string filename = "inotify-info.config";
|
const std::string filename = "inotify-info.config";
|
||||||
|
|
||||||
const char *xdg_config_dir = getenv( "XDG_CONFIG_HOME" );
|
const char *xdg_config_dir = getenv( "XDG_CONFIG_HOME" );
|
||||||
if (xdg_config_dir) {
|
if ( xdg_config_dir )
|
||||||
|
{
|
||||||
std::string config_file = std::string( xdg_config_dir ) + "/" + filename;
|
std::string config_file = std::string( xdg_config_dir ) + "/" + filename;
|
||||||
if ( parse_config_file( config_file.c_str() ) )
|
if ( parse_config_file( config_file.c_str() ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -977,7 +1061,8 @@ static bool parse_ignore_dirs_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *home_dir = getenv( "HOME" );
|
const char *home_dir = getenv( "HOME" );
|
||||||
if (home_dir) {
|
if ( home_dir )
|
||||||
|
{
|
||||||
std::string config_file = std::string( home_dir ) + "/" + filename;
|
std::string config_file = std::string( home_dir ) + "/" + filename;
|
||||||
if ( parse_config_file( config_file.c_str() ) )
|
if ( parse_config_file( config_file.c_str() ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -990,27 +1075,22 @@ static bool parse_ignore_dirs_file()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_version()
|
|
||||||
{
|
|
||||||
printf("%s\n", INOTIFYINFO_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage( const char *appname )
|
static void print_usage( const char *appname )
|
||||||
{
|
{
|
||||||
printf( "Usage: %s [--threads=##] [appname | pid...]\n", appname );
|
printf( "Usage: %s [--threads=##] [appname | pid...]\n", appname );
|
||||||
printf( " [-vv]\n" );
|
printf( " [-vv]\n" );
|
||||||
printf(" [--version]\n");
|
|
||||||
printf( " [-?|-h|--help]\n" );
|
printf( " [-?|-h|--help]\n" );
|
||||||
|
|
||||||
|
exit( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_cmdline( int argc, char **argv, std::vector< std::string > &cmdline_applist )
|
static void parse_cmdline( int argc, char **argv, std::vector< std::string > &cmdline_applist )
|
||||||
{
|
{
|
||||||
static struct option long_opts[] = {
|
static struct option long_opts[] =
|
||||||
|
{
|
||||||
{ "verbose", no_argument, 0, 0 },
|
{ "verbose", no_argument, 0, 0 },
|
||||||
{ "threads", required_argument, 0, 0 },
|
{ "threads", required_argument, 0, 0 },
|
||||||
{ "ignoredir", required_argument, 0, 0 },
|
{ "ignoredir", required_argument, 0, 0 },
|
||||||
{ "version", no_argument, 0, 0 },
|
|
||||||
{ "help", no_argument, 0, 0 },
|
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1019,24 +1099,20 @@ static void parse_cmdline(int argc, char** argv, std::vector<std::string>& cmdli
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
int opt_ind = 0;
|
int opt_ind = 0;
|
||||||
while ((c = getopt_long(argc, argv, "m:s:?hv", long_opts, &opt_ind)) != -1) {
|
while ( ( c = getopt_long( argc, argv, "m:s:?hv", long_opts, &opt_ind ) ) != -1 )
|
||||||
switch (c) {
|
{
|
||||||
|
switch ( c )
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (!strcasecmp("help", long_opts[opt_ind].name)) {
|
|
||||||
print_usage(argv[0]);
|
|
||||||
exit(0);
|
|
||||||
};
|
|
||||||
if (!strcasecmp("version", long_opts[opt_ind].name)) {
|
|
||||||
print_version();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
if ( !strcasecmp( "verbose", long_opts[ opt_ind ].name ) )
|
if ( !strcasecmp( "verbose", long_opts[ opt_ind ].name ) )
|
||||||
g_verbose++;
|
g_verbose++;
|
||||||
else if ( !strcasecmp( "threads", long_opts[ opt_ind ].name ) )
|
else if ( !strcasecmp( "threads", long_opts[ opt_ind ].name ) )
|
||||||
g_numthreads = atoi( optarg );
|
g_numthreads = atoi( optarg );
|
||||||
else if (!strcasecmp("ignoredir", long_opts[opt_ind].name)) {
|
else if ( !strcasecmp( "ignoredir", long_opts[ opt_ind ].name ) )
|
||||||
|
{
|
||||||
std::string dirname = optarg;
|
std::string dirname = optarg;
|
||||||
if (dirname.size() > 1) {
|
if ( dirname.size() > 1 )
|
||||||
|
{
|
||||||
if ( optarg[ dirname.size() - 1 ] != '/' )
|
if ( optarg[ dirname.size() - 1 ] != '/' )
|
||||||
dirname += "/";
|
dirname += "/";
|
||||||
ignore_dirs.push_back( dirname );
|
ignore_dirs.push_back( dirname );
|
||||||
|
@ -1048,25 +1124,25 @@ static void parse_cmdline(int argc, char** argv, std::vector<std::string>& cmdli
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
print_usage(argv[0]);
|
|
||||||
exit(0);
|
|
||||||
default:
|
default:
|
||||||
print_usage( argv[ 0 ] );
|
print_usage( argv[ 0 ] );
|
||||||
exit(-1);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; optind < argc; optind++) {
|
for ( ; optind < argc; optind++ )
|
||||||
|
{
|
||||||
cmdline_applist.push_back( argv[ optind ] );
|
cmdline_applist.push_back( argv[ optind ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_ignore_dirs_file();
|
parse_ignore_dirs_file();
|
||||||
|
|
||||||
if (g_verbose > 1) {
|
if ( g_verbose > 1 )
|
||||||
|
{
|
||||||
printf( "%lu ignore_dirs:\n", ignore_dirs.size() );
|
printf( "%lu ignore_dirs:\n", ignore_dirs.size() );
|
||||||
|
|
||||||
for (std::string& dname : ignore_dirs) {
|
for ( std::string &dname : ignore_dirs )
|
||||||
|
{
|
||||||
printf( " '%s'\n", dname.c_str() );
|
printf( " '%s'\n", dname.c_str() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1083,7 +1159,8 @@ int main(int argc, char* argv[])
|
||||||
std::vector< procinfo_t > inotify_proclist;
|
std::vector< procinfo_t > inotify_proclist;
|
||||||
|
|
||||||
struct lconv *env = localeconv();
|
struct lconv *env = localeconv();
|
||||||
if (env && env->thousands_sep && env->thousands_sep[0]) {
|
if (env && env->thousands_sep && env->thousands_sep[0])
|
||||||
|
{
|
||||||
thousands_sep = env->thousands_sep[0];
|
thousands_sep = env->thousands_sep[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1093,12 +1170,14 @@ int main(int argc, char* argv[])
|
||||||
print_inotify_limits();
|
print_inotify_limits();
|
||||||
print_separator();
|
print_separator();
|
||||||
|
|
||||||
if (init_inotify_proclist(inotify_proclist)) {
|
if ( init_inotify_proclist( inotify_proclist ) )
|
||||||
|
{
|
||||||
uint32_t total_watches = 0;
|
uint32_t total_watches = 0;
|
||||||
uint32_t total_instances = 0;
|
uint32_t total_instances = 0;
|
||||||
std::vector< filename_info_t > all_found_files;
|
std::vector< filename_info_t > all_found_files;
|
||||||
|
|
||||||
for (procinfo_t& procinfo : inotify_proclist) {
|
for ( procinfo_t &procinfo : inotify_proclist )
|
||||||
|
{
|
||||||
procinfo.in_cmd_line = is_proc_in_cmdline_applist( procinfo, cmdline_applist );
|
procinfo.in_cmd_line = is_proc_in_cmdline_applist( procinfo, cmdline_applist );
|
||||||
|
|
||||||
total_watches += procinfo.watches;
|
total_watches += procinfo.watches;
|
||||||
|
@ -1117,10 +1196,12 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
double search_time = gettime();
|
double search_time = gettime();
|
||||||
uint32_t total_scanned_dirs = find_files_in_inode_set( inotify_proclist, all_found_files );
|
uint32_t total_scanned_dirs = find_files_in_inode_set( inotify_proclist, all_found_files );
|
||||||
if (total_scanned_dirs) {
|
if ( total_scanned_dirs )
|
||||||
|
{
|
||||||
search_time = gettime() - search_time;
|
search_time = gettime() - search_time;
|
||||||
|
|
||||||
for (const filename_info_t& fname_info : all_found_files) {
|
for ( const filename_info_t &fname_info : all_found_files )
|
||||||
|
{
|
||||||
printf( "%s%9lu%s [%u:%u] %s\n", BGREEN, fname_info.inode, RESET,
|
printf( "%s%9lu%s [%u:%u] %s\n", BGREEN, fname_info.inode, RESET,
|
||||||
major( fname_info.dev ), minor( fname_info.dev ),
|
major( fname_info.dev ), minor( fname_info.dev ),
|
||||||
fname_info.filename.c_str() );
|
fname_info.filename.c_str() );
|
||||||
|
|
|
@ -57,3 +57,4 @@
|
||||||
|
|
||||||
std::string string_formatv(const char *fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
|
std::string string_formatv(const char *fmt, va_list ap) ATTRIBUTE_PRINTF(1, 0);
|
||||||
std::string string_format(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
|
std::string string_format(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,14 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
|
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
|
||||||
|
|
||||||
#include <sched.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <unistd.h> // for usleep
|
#include <unistd.h> // for usleep
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
#define __LFQ_VAL_COMPARE_AND_SWAP __sync_val_compare_and_swap
|
#define __LFQ_VAL_COMPARE_AND_SWAP __sync_val_compare_and_swap
|
||||||
#define __LFQ_BOOL_COMPARE_AND_SWAP __sync_bool_compare_and_swap
|
#define __LFQ_BOOL_COMPARE_AND_SWAP __sync_bool_compare_and_swap
|
||||||
|
@ -48,8 +48,7 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 comparand)
|
inline BOOL __SYNC_BOOL_CAS(LONG64 volatile *dest, LONG64 input, LONG64 comparand) {
|
||||||
{
|
|
||||||
return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
|
return InterlockedCompareExchangeNoFence64(dest, input, comparand) == comparand;
|
||||||
}
|
}
|
||||||
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
|
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
|
||||||
|
@ -64,8 +63,7 @@ inline BOOL __SYNC_BOOL_CAS(LONG64 volatile* dest, LONG64 input, LONG64 comparan
|
||||||
#ifndef asm
|
#ifndef asm
|
||||||
#define asm __asm
|
#define asm __asm
|
||||||
#endif
|
#endif
|
||||||
inline BOOL __SYNC_BOOL_CAS(LONG volatile* dest, LONG input, LONG comparand)
|
inline BOOL __SYNC_BOOL_CAS(LONG volatile *dest, LONG input, LONG comparand) {
|
||||||
{
|
|
||||||
return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
|
return InterlockedCompareExchangeNoFence(dest, input, comparand) == comparand;
|
||||||
}
|
}
|
||||||
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
|
#define __LFQ_VAL_COMPARE_AND_SWAP(dest, comparand, input) \
|
||||||
|
@ -109,18 +107,15 @@ static void __lfq_check_free(lfqueue_t*);
|
||||||
static void *_dequeue(lfqueue_t *);
|
static void *_dequeue(lfqueue_t *);
|
||||||
static void *_single_dequeue(lfqueue_t *);
|
static void *_single_dequeue(lfqueue_t *);
|
||||||
static int _enqueue(lfqueue_t *, void* );
|
static int _enqueue(lfqueue_t *, void* );
|
||||||
static inline void* _lfqueue_malloc(__attribute__((unused)) void* pl, size_t sz)
|
static inline void* _lfqueue_malloc(__attribute__ ((unused)) void* pl, size_t sz) {
|
||||||
{
|
|
||||||
return malloc(sz);
|
return malloc(sz);
|
||||||
}
|
}
|
||||||
static inline void _lfqueue_free(__attribute__((unused)) void* pl, void* ptr)
|
static inline void _lfqueue_free(__attribute__ ((unused)) void* pl, void* ptr) {
|
||||||
{
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
_dequeue(lfqueue_t* lfqueue)
|
_dequeue(lfqueue_t *lfqueue) {
|
||||||
{
|
|
||||||
lfqueue_cas_node_t *head, *next;
|
lfqueue_cas_node_t *head, *next;
|
||||||
void *val;
|
void *val;
|
||||||
|
|
||||||
|
@ -133,7 +128,8 @@ _dequeue(lfqueue_t* lfqueue)
|
||||||
val = NULL;
|
val = NULL;
|
||||||
goto _done;
|
goto _done;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (next) {
|
if (next) {
|
||||||
val = next->value;
|
val = next->value;
|
||||||
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
|
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
|
||||||
|
@ -156,8 +152,7 @@ _done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
_single_dequeue(lfqueue_t* lfqueue)
|
_single_dequeue(lfqueue_t *lfqueue) {
|
||||||
{
|
|
||||||
lfqueue_cas_node_t *head, *next;
|
lfqueue_cas_node_t *head, *next;
|
||||||
void *val;
|
void *val;
|
||||||
|
|
||||||
|
@ -169,7 +164,8 @@ _single_dequeue(lfqueue_t* lfqueue)
|
||||||
if (next == NULL) {
|
if (next == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (next) {
|
if (next) {
|
||||||
val = next->value;
|
val = next->value;
|
||||||
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
|
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->head, head, next)) {
|
||||||
|
@ -186,8 +182,7 @@ _single_dequeue(lfqueue_t* lfqueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_enqueue(lfqueue_t* lfqueue, void* value)
|
_enqueue(lfqueue_t *lfqueue, void* value) {
|
||||||
{
|
|
||||||
lfqueue_cas_node_t *tail, *node;
|
lfqueue_cas_node_t *tail, *node;
|
||||||
node = (lfqueue_cas_node_t*) lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t));
|
node = (lfqueue_cas_node_t*) lfqueue->_malloc(lfqueue->pl, sizeof(lfqueue_cas_node_t));
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
|
@ -213,8 +208,7 @@ _enqueue(lfqueue_t* lfqueue, void* value)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode)
|
__lfq_recycle_free(lfqueue_t *lfqueue, lfqueue_cas_node_t* freenode) {
|
||||||
{
|
|
||||||
lfqueue_cas_node_t *freed;
|
lfqueue_cas_node_t *freed;
|
||||||
do {
|
do {
|
||||||
freed = lfqueue->move_free;
|
freed = lfqueue->move_free;
|
||||||
|
@ -226,8 +220,7 @@ __lfq_recycle_free(lfqueue_t* lfqueue, lfqueue_cas_node_t* freenode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
__lfq_check_free(lfqueue_t* lfqueue)
|
__lfq_check_free(lfqueue_t *lfqueue) {
|
||||||
{
|
|
||||||
lfq_time_t curr_time;
|
lfq_time_t curr_time;
|
||||||
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) {
|
if (__LFQ_BOOL_COMPARE_AND_SWAP(&lfqueue->in_free_mode, 0, 1)) {
|
||||||
lfq_get_curr_time(&curr_time);
|
lfq_get_curr_time(&curr_time);
|
||||||
|
@ -248,13 +241,13 @@ __lfq_check_free(lfqueue_t* lfqueue)
|
||||||
__LFQ_SYNC_MEMORY();
|
__LFQ_SYNC_MEMORY();
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfqueue_init(lfqueue_t* lfqueue)
|
int
|
||||||
{
|
lfqueue_init(lfqueue_t *lfqueue) {
|
||||||
return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free);
|
return lfqueue_init_mf(lfqueue, NULL, _lfqueue_malloc, _lfqueue_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free)
|
int
|
||||||
{
|
lfqueue_init_mf(lfqueue_t *lfqueue, void* pl, lfqueue_malloc_fn lfqueue_malloc, lfqueue_free_fn lfqueue_free) {
|
||||||
lfqueue->_malloc = lfqueue_malloc;
|
lfqueue->_malloc = lfqueue_malloc;
|
||||||
lfqueue->_free = lfqueue_free;
|
lfqueue->_free = lfqueue_free;
|
||||||
lfqueue->pl = pl;
|
lfqueue->pl = pl;
|
||||||
|
@ -283,8 +276,8 @@ int lfqueue_init_mf(lfqueue_t* lfqueue, void* pl, lfqueue_malloc_fn lfqueue_mall
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lfqueue_destroy(lfqueue_t* lfqueue)
|
void
|
||||||
{
|
lfqueue_destroy(lfqueue_t *lfqueue) {
|
||||||
void* p;
|
void* p;
|
||||||
while ((p = lfqueue_deq(lfqueue))) {
|
while ((p = lfqueue_deq(lfqueue))) {
|
||||||
lfqueue->_free(lfqueue->pl, p);
|
lfqueue->_free(lfqueue->pl, p);
|
||||||
|
@ -305,8 +298,8 @@ void lfqueue_destroy(lfqueue_t* lfqueue)
|
||||||
lfqueue->size = 0;
|
lfqueue->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfqueue_enq(lfqueue_t* lfqueue, void* value)
|
int
|
||||||
{
|
lfqueue_enq(lfqueue_t *lfqueue, void *value) {
|
||||||
if (_enqueue(lfqueue, value)) {
|
if (_enqueue(lfqueue, value)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -314,11 +307,12 @@ int lfqueue_enq(lfqueue_t* lfqueue, void* value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* lfqueue_deq(lfqueue_t* lfqueue)
|
void*
|
||||||
{
|
lfqueue_deq(lfqueue_t *lfqueue) {
|
||||||
void *v;
|
void *v;
|
||||||
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
|
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
|
||||||
(v = _dequeue(lfqueue))) {
|
(v = _dequeue(lfqueue))
|
||||||
|
) {
|
||||||
|
|
||||||
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
|
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
|
||||||
return v;
|
return v;
|
||||||
|
@ -326,8 +320,8 @@ void* lfqueue_deq(lfqueue_t* lfqueue)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* lfqueue_deq_must(lfqueue_t* lfqueue)
|
void*
|
||||||
{
|
lfqueue_deq_must(lfqueue_t *lfqueue) {
|
||||||
void *v;
|
void *v;
|
||||||
while ( !(v = _dequeue(lfqueue)) ) {
|
while ( !(v = _dequeue(lfqueue)) ) {
|
||||||
// Rest the thread for other thread, to avoid keep looping force
|
// Rest the thread for other thread, to avoid keep looping force
|
||||||
|
@ -338,11 +332,12 @@ void* lfqueue_deq_must(lfqueue_t* lfqueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**This is only applicable when only single thread consume only**/
|
/**This is only applicable when only single thread consume only**/
|
||||||
void* lfqueue_single_deq(lfqueue_t* lfqueue)
|
void*
|
||||||
{
|
lfqueue_single_deq(lfqueue_t *lfqueue) {
|
||||||
void *v;
|
void *v;
|
||||||
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
|
if (//__LFQ_ADD_AND_FETCH(&lfqueue->size, 0) &&
|
||||||
(v = _single_dequeue(lfqueue))) {
|
(v = _single_dequeue(lfqueue))
|
||||||
|
) {
|
||||||
|
|
||||||
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
|
__LFQ_FETCH_AND_ADD(&lfqueue->size, -1);
|
||||||
return v;
|
return v;
|
||||||
|
@ -351,8 +346,8 @@ void* lfqueue_single_deq(lfqueue_t* lfqueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**This is only applicable when only single thread consume only**/
|
/**This is only applicable when only single thread consume only**/
|
||||||
void* lfqueue_single_deq_must(lfqueue_t* lfqueue)
|
void*
|
||||||
{
|
lfqueue_single_deq_must(lfqueue_t *lfqueue) {
|
||||||
void *v;
|
void *v;
|
||||||
while ( !(v = _single_dequeue(lfqueue)) ) {
|
while ( !(v = _single_dequeue(lfqueue)) ) {
|
||||||
// Rest the thread for other thread, to avoid keep looping force
|
// Rest the thread for other thread, to avoid keep looping force
|
||||||
|
@ -363,13 +358,12 @@ void* lfqueue_single_deq_must(lfqueue_t* lfqueue)
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
lfqueue_size(lfqueue_t* lfqueue)
|
lfqueue_size(lfqueue_t *lfqueue) {
|
||||||
{
|
|
||||||
return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
|
return __LFQ_ADD_AND_FETCH(&lfqueue->size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lfqueue_sleep(unsigned int milisec)
|
void
|
||||||
{
|
lfqueue_sleep(unsigned int milisec) {
|
||||||
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
|
#if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
#ifndef LFQUEUE_H
|
#ifndef LFQUEUE_H
|
||||||
#define LFQUEUE_H
|
#define LFQUEUE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -75,8 +75,10 @@ extern void lfqueue_destroy(lfqueue_t* lfqueue);
|
||||||
extern size_t lfqueue_size(lfqueue_t *lfqueue);
|
extern size_t lfqueue_size(lfqueue_t *lfqueue);
|
||||||
extern void lfqueue_sleep(unsigned int milisec);
|
extern void lfqueue_sleep(unsigned int milisec);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue