mirror of
https://github.com/simon987/sist2.git
synced 2025-12-17 17:29:07 +00:00
Compare commits
12 Commits
2.11.5
...
a96e65d039
| Author | SHA1 | Date | |
|---|---|---|---|
| a96e65d039 | |||
| 87936eecd4 | |||
|
|
d817a0e9dd | ||
| d40f5052f9 | |||
| ee9a8fa514 | |||
| 81008d8936 | |||
| 52466d5d8a | |||
| 5f73fc024b | |||
| f2fd7ccf41 | |||
| d87fee8e00 | |||
|
|
672d1344d7 | ||
| 27e32db1ed |
30
.drone.yml
30
.drone.yml
@@ -11,21 +11,6 @@ steps:
|
|||||||
image: simon987/sist2-build
|
image: simon987/sist2-build
|
||||||
commands:
|
commands:
|
||||||
- ./scripts/build.sh
|
- ./scripts/build.sh
|
||||||
- name: docker
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: DOCKER_USER
|
|
||||||
password:
|
|
||||||
from_secret: DOCKER_PASSWORD
|
|
||||||
repo: simon987/sist2
|
|
||||||
context: ./
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: x64-linux
|
|
||||||
when:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
- name: scp files
|
- name: scp files
|
||||||
image: appleboy/drone-scp
|
image: appleboy/drone-scp
|
||||||
settings:
|
settings:
|
||||||
@@ -42,6 +27,21 @@ steps:
|
|||||||
- ./VERSION
|
- ./VERSION
|
||||||
- ./sist2-x64-linux
|
- ./sist2-x64-linux
|
||||||
- ./sist2-x64-linux-debug
|
- ./sist2-x64-linux-debug
|
||||||
|
- name: docker
|
||||||
|
image: plugins/docker
|
||||||
|
settings:
|
||||||
|
username:
|
||||||
|
from_secret: DOCKER_USER
|
||||||
|
password:
|
||||||
|
from_secret: DOCKER_PASSWORD
|
||||||
|
repo: simon987/sist2
|
||||||
|
context: ./
|
||||||
|
dockerfile: ./Dockerfile
|
||||||
|
auto_tag: true
|
||||||
|
auto_tag_suffix: x64-linux
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
- tag
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
|||||||
[submodule "third-party/libscan"]
|
|
||||||
path = third-party/libscan
|
|
||||||
url = https://github.com/simon987/libscan
|
|
||||||
[submodule "third-party/argparse"]
|
[submodule "third-party/argparse"]
|
||||||
path = third-party/argparse
|
path = third-party/argparse
|
||||||
url = https://github.com/simon987/argparse
|
url = https://github.com/simon987/argparse
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ add_subdirectory(third-party/argparse)
|
|||||||
|
|
||||||
add_executable(sist2
|
add_executable(sist2
|
||||||
|
|
||||||
# argparse
|
|
||||||
third-party/argparse/argparse.h third-party/argparse/argparse.c
|
|
||||||
|
|
||||||
src/main.c
|
src/main.c
|
||||||
src/sist.h
|
src/sist.h
|
||||||
src/io/walk.h src/io/walk.c
|
src/io/walk.h src/io/walk.c
|
||||||
@@ -41,7 +38,11 @@ add_executable(sist2
|
|||||||
src/log.c src/log.h
|
src/log.c src/log.h
|
||||||
src/cli.c src/cli.h
|
src/cli.c src/cli.h
|
||||||
src/stats.c src/stats.h src/ctx.c
|
src/stats.c src/stats.h src/ctx.c
|
||||||
src/parsing/sidecar.c src/parsing/sidecar.h)
|
src/parsing/sidecar.c src/parsing/sidecar.h
|
||||||
|
|
||||||
|
# argparse
|
||||||
|
third-party/argparse/argparse.h third-party/argparse/argparse.c
|
||||||
|
)
|
||||||
|
|
||||||
target_link_directories(sist2 PRIVATE BEFORE ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/)
|
target_link_directories(sist2 PRIVATE BEFORE ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib)
|
set(CMAKE_FIND_LIBRARY_SUFFIXES .a .lib)
|
||||||
@@ -86,6 +87,7 @@ if (SIST_DEBUG)
|
|||||||
sist2
|
sist2
|
||||||
PRIVATE
|
PRIVATE
|
||||||
-fsanitize=address
|
-fsanitize=address
|
||||||
|
-static-libasan
|
||||||
)
|
)
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
sist2
|
sist2
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ sist2 (Simple incremental search tool)
|
|||||||
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases) *
|
1. Download the [latest sist2 release](https://github.com/simon987/sist2/releases) *
|
||||||
1. *(or)* Download a [development snapshot](https://files.simon987.net/.gate/sist2/simon987_sist2/) *(Not
|
1. *(or)* Download a [development snapshot](https://files.simon987.net/.gate/sist2/simon987_sist2/) *(Not
|
||||||
recommended!)*
|
recommended!)*
|
||||||
1. *(or)* `docker pull simon987/sist2:2.11.4-x64-linux`
|
1. *(or)* `docker pull simon987/sist2:2.11.6-x64-linux`
|
||||||
|
|
||||||
1. See [Usage guide](docs/USAGE.md)
|
1. See [Usage guide](docs/USAGE.md)
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ docker run --rm my-sist2-image cat /root/sist2 > sist2-x64-linux
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
vcpkg install curl[core,openssl]
|
vcpkg install curl[core,openssl]
|
||||||
vcpkg install lmdb cjson glib brotli libarchive[core,bzip2,libxml2,lz4,lzma,lzo] pthread tesseract libxml2 libmupdf gtest mongoose libuuid libmagic libraw jasper lcms gumbo
|
vcpkg install lmdb cjson glib brotli libarchive[core,bzip2,libxml2,lz4,lzma,lzo] pthread tesseract libxml2 libmupdf gtest mongoose libmagic libraw jasper lcms gumbo
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Build
|
1. Build
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ Exec-script options
|
|||||||
### Scan options
|
### Scan options
|
||||||
|
|
||||||
* `-t, --threads`
|
* `-t, --threads`
|
||||||
Number of threads for file parsing. **Do not set a number higher than `$(nproc)` or `$(Get-WmiObject Win32_ComputerSystem).NumberOfLogicalProcessors` in Windows!**
|
Number of threads for file parsing. **Do not set a number higher than `$(nproc)` or `$(Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors` in Windows!**
|
||||||
* `-q, --quality`
|
* `-q, --quality`
|
||||||
Thumbnail quality, on a scale of 1.0 to 31.0, 1.0 being the best.
|
Thumbnail quality, on a scale of 1.0 to 31.0, 1.0 being the best.
|
||||||
* `--size`
|
* `--size`
|
||||||
|
|||||||
2
sist2-vue/dist/css/index.css
vendored
2
sist2-vue/dist/css/index.css
vendored
File diff suppressed because one or more lines are too long
2
sist2-vue/dist/js/index.js
vendored
2
sist2-vue/dist/js/index.js
vendored
File diff suppressed because one or more lines are too long
@@ -133,6 +133,11 @@ export default Vue.extend({
|
|||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-black .version-badge {
|
||||||
|
color: #eee !important;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
.version-badge {
|
.version-badge {
|
||||||
color: #222 !important;
|
color: #222 !important;
|
||||||
background: none;
|
background: none;
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ export default {
|
|||||||
},
|
},
|
||||||
lang: {
|
lang: {
|
||||||
en: "English",
|
en: "English",
|
||||||
fr: "Français"
|
fr: "Français",
|
||||||
|
"zh-CN": "简体中文",
|
||||||
},
|
},
|
||||||
displayMode: {
|
displayMode: {
|
||||||
grid: "Grid",
|
grid: "Grid",
|
||||||
@@ -228,7 +229,8 @@ export default {
|
|||||||
},
|
},
|
||||||
lang: {
|
lang: {
|
||||||
en: "English",
|
en: "English",
|
||||||
fr: "Français"
|
fr: "Français",
|
||||||
|
"zh-CN": "简体中文",
|
||||||
},
|
},
|
||||||
displayMode: {
|
displayMode: {
|
||||||
grid: "Grille",
|
grid: "Grille",
|
||||||
@@ -311,5 +313,161 @@ export default {
|
|||||||
selectedIndex: "indice sélectionné",
|
selectedIndex: "indice sélectionné",
|
||||||
selectedIndices: "indices sélectionnés",
|
selectedIndices: "indices sélectionnés",
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
"zh-CN": {
|
||||||
|
searchBar: {
|
||||||
|
simple: "搜索",
|
||||||
|
advanced: "高级搜索",
|
||||||
|
fuzzy: "模糊搜索"
|
||||||
|
},
|
||||||
|
download: "下载",
|
||||||
|
and: "与",
|
||||||
|
page: "页",
|
||||||
|
pages: "页",
|
||||||
|
mimeTypes: "文件类型",
|
||||||
|
tags: "标签",
|
||||||
|
help: {
|
||||||
|
simpleSearch: "简易搜索",
|
||||||
|
advancedSearch: "高级搜索",
|
||||||
|
help: "帮助",
|
||||||
|
term: "<关键词>",
|
||||||
|
and: "与操作",
|
||||||
|
or: "或操作",
|
||||||
|
not: "反选单个关键词",
|
||||||
|
quotes: "括起来的部分视为一个关键词,保序",
|
||||||
|
prefix: "在词尾使用时,匹配前缀",
|
||||||
|
parens: "表达式编组",
|
||||||
|
tildeTerm: "匹配编辑距离以内的关键词",
|
||||||
|
tildePhrase: "匹配短语,容忍一些非匹配词",
|
||||||
|
example1:
|
||||||
|
"例如: <code>\"番茄\" +(炒蛋 | 牛腩) -饭</code> 将匹配" +
|
||||||
|
"短语 <i>番茄炒蛋</i>、<i>炒蛋</i> 或者 <i>牛腩</i>,而忽略任何带有" +
|
||||||
|
"<i>饭</i>的关键词.",
|
||||||
|
defaultOperator:
|
||||||
|
"表达式中无<code>+</code>或者<code>|</code>时,默认使用" +
|
||||||
|
"<code>+</code>(与操作)。",
|
||||||
|
fuzzy:
|
||||||
|
"选中<b>模糊搜索</b>选项时,返回部分匹配的结果(3-grams)。",
|
||||||
|
moreInfoSimple: "详细信息:<a target=\"_blank\" " +
|
||||||
|
"rel=\"noreferrer\" href=\"//www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html\">Elasticsearch文档</a>",
|
||||||
|
moreInfoAdvanced: "高级搜索模式文档:<a target=\"_blank\" rel=\"noreferrer\" href=\"//www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#query-string-syntax\">Elasticsearch文档</a>"
|
||||||
|
},
|
||||||
|
config: "配置",
|
||||||
|
configDescription: "配置在此浏览器中实时保存。",
|
||||||
|
configReset: "重置所有设置",
|
||||||
|
searchOptions: "搜索选项",
|
||||||
|
treemapOptions: "树状图选项",
|
||||||
|
displayOptions: "显示选项",
|
||||||
|
opt: {
|
||||||
|
lang: "语言",
|
||||||
|
highlight: "启用高亮",
|
||||||
|
fuzzy: "默认使用模糊搜索",
|
||||||
|
searchInPath: "匹配文档路径",
|
||||||
|
suggestPath: "搜索框启用自动补全",
|
||||||
|
fragmentSize: "高亮上下文大小",
|
||||||
|
queryMode: "搜索模式",
|
||||||
|
displayMode: "显示",
|
||||||
|
columns: "列数",
|
||||||
|
treemapType: "树状图类属性",
|
||||||
|
treemapTiling: "树状图平铺",
|
||||||
|
treemapColorGroupingDepth: "树状图颜色编组深度(展开)",
|
||||||
|
treemapColor: "树状图颜色(折叠)",
|
||||||
|
treemapSize: "树状图大小",
|
||||||
|
theme: "主题",
|
||||||
|
lightboxLoadOnlyCurrent: "在图片查看器中,不要预读相邻的全图",
|
||||||
|
slideDuration: "幻灯片时长",
|
||||||
|
resultSize: "每页结果数",
|
||||||
|
tagOrOperator: "使用或操作(OR)匹配多个标签。",
|
||||||
|
hideDuplicates: "使用校验码隐藏重复结果",
|
||||||
|
hideLegacy: "隐藏'legacyES' Elasticsearch 通知"
|
||||||
|
},
|
||||||
|
queryMode: {
|
||||||
|
simple: "简单",
|
||||||
|
advanced: "高级",
|
||||||
|
},
|
||||||
|
lang: {
|
||||||
|
en: "English",
|
||||||
|
fr: "Français",
|
||||||
|
"zh-CN": "简体中文",
|
||||||
|
},
|
||||||
|
displayMode: {
|
||||||
|
grid: "网格",
|
||||||
|
list: "列表",
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
auto: "自动"
|
||||||
|
},
|
||||||
|
treemapType: {
|
||||||
|
cascaded: "折叠",
|
||||||
|
flat: "平铺(紧凑)"
|
||||||
|
},
|
||||||
|
treemapSize: {
|
||||||
|
small: "小",
|
||||||
|
medium: "中",
|
||||||
|
large: "大",
|
||||||
|
xLarge: "加大",
|
||||||
|
xxLarge: "加加大",
|
||||||
|
custom: "自订",
|
||||||
|
},
|
||||||
|
treemapTiling: {
|
||||||
|
binary: "Binary",
|
||||||
|
squarify: "Squarify",
|
||||||
|
slice: "Slice",
|
||||||
|
dice: "Dice",
|
||||||
|
sliceDice: "Slice & Dice",
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
light: "亮",
|
||||||
|
black: "暗"
|
||||||
|
},
|
||||||
|
hit: "命中",
|
||||||
|
hits: "命中",
|
||||||
|
details: "详细信息",
|
||||||
|
stats: "统计信息",
|
||||||
|
queryTime: "查询时间",
|
||||||
|
totalSize: "总大小",
|
||||||
|
pathBar: {
|
||||||
|
placeholder: "过滤路径",
|
||||||
|
modalTitle: "选择路径"
|
||||||
|
},
|
||||||
|
debug: "调试信息",
|
||||||
|
debugDescription: "对调试除错有用的信息。 若您遇到bug或者想建议新功能,请提交新Issue到" +
|
||||||
|
"<a href='https://github.com/simon987/sist2/issues/new/choose'>这里</a>.",
|
||||||
|
tagline: "标签栏",
|
||||||
|
toast: {
|
||||||
|
esConnErrTitle: "Elasticsearch连接错误",
|
||||||
|
esConnErr: "sist2 web 模块连接Elasticsearch出错。" +
|
||||||
|
"查看服务日志以获取更多信息。",
|
||||||
|
esQueryErrTitle: "查询错误",
|
||||||
|
esQueryErr: "无法识别或执行查询,请查阅高级搜索文档。" +
|
||||||
|
"查看服务日志以获取更多信息。",
|
||||||
|
dupeTagTitle: "重复标签",
|
||||||
|
dupeTag: "该标签已存在于此文档。"
|
||||||
|
},
|
||||||
|
saveTagModalTitle: "增加标签",
|
||||||
|
saveTagPlaceholder: "标签名",
|
||||||
|
confirm: "确认",
|
||||||
|
sort: {
|
||||||
|
relevance: "相关度",
|
||||||
|
dateAsc: "日期(由旧到新)",
|
||||||
|
dateDesc: "日期(由新到旧)",
|
||||||
|
sizeAsc: "大小(从小到大)",
|
||||||
|
sizeDesc: "大小(从大到小)",
|
||||||
|
nameAsc: "名字(A-z)",
|
||||||
|
nameDesc: "名字 (Z-a)",
|
||||||
|
random: "随机",
|
||||||
|
},
|
||||||
|
d3: {
|
||||||
|
mimeCount: "各类文件数量分布",
|
||||||
|
mimeSize: "各类文件大小分布",
|
||||||
|
dateHistogram: "文件修改时间分布",
|
||||||
|
sizeHistogram: "文件大小分布",
|
||||||
|
},
|
||||||
|
indexPicker: {
|
||||||
|
selectNone: "清空",
|
||||||
|
selectAll: "全选",
|
||||||
|
selectedIndex: "选中索引",
|
||||||
|
selectedIndices: "选中索引",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -133,6 +133,7 @@ export default {
|
|||||||
langOptions: [
|
langOptions: [
|
||||||
{value: "en", text: this.$t("lang.en")},
|
{value: "en", text: this.$t("lang.en")},
|
||||||
{value: "fr", text: this.$t("lang.fr")},
|
{value: "fr", text: this.$t("lang.fr")},
|
||||||
|
{value: "zh-CN", text: this.$t("lang.zh-CN")},
|
||||||
],
|
],
|
||||||
queryModeOptions: [
|
queryModeOptions: [
|
||||||
{value: "simple", text: this.$t("queryMode.simple")},
|
{value: "simple", text: this.$t("queryMode.simple")},
|
||||||
|
|||||||
15
src/cli.c
15
src/cli.c
@@ -22,6 +22,7 @@
|
|||||||
const char *TESS_DATAPATHS[] = {
|
const char *TESS_DATAPATHS[] = {
|
||||||
"/usr/share/tessdata/",
|
"/usr/share/tessdata/",
|
||||||
"/usr/share/tesseract-ocr/tessdata/",
|
"/usr/share/tesseract-ocr/tessdata/",
|
||||||
|
"/usr/share/tesseract-ocr/4.00/tessdata/",
|
||||||
"./",
|
"./",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
@@ -218,6 +219,19 @@ int scan_args_validate(scan_args_t *args, int argc, const char **argv) {
|
|||||||
args->max_memory_buffer = DEFAULT_MAX_MEM_BUFFER;
|
args->max_memory_buffer = DEFAULT_MAX_MEM_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args->list_path != NULL) {
|
||||||
|
if(strcmp(args->list_path, "-") == 0) {
|
||||||
|
args->list_file = stdin;
|
||||||
|
LOG_DEBUG("cli.c", "Using stdin as list file")
|
||||||
|
} else {
|
||||||
|
args->list_file = fopen(args->list_path, "r");
|
||||||
|
|
||||||
|
if (args->list_file == NULL) {
|
||||||
|
LOG_FATALF("main.c", "List file could not be opened: %s (%s)", args->list_path, errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUGF("cli.c", "arg quality=%f", args->quality)
|
LOG_DEBUGF("cli.c", "arg quality=%f", args->quality)
|
||||||
LOG_DEBUGF("cli.c", "arg size=%d", args->size)
|
LOG_DEBUGF("cli.c", "arg size=%d", args->size)
|
||||||
LOG_DEBUGF("cli.c", "arg content_size=%d", args->content_size)
|
LOG_DEBUGF("cli.c", "arg content_size=%d", args->content_size)
|
||||||
@@ -237,6 +251,7 @@ int scan_args_validate(scan_args_t *args, int argc, const char **argv) {
|
|||||||
LOG_DEBUGF("cli.c", "arg fast_epub=%d", args->fast_epub)
|
LOG_DEBUGF("cli.c", "arg fast_epub=%d", args->fast_epub)
|
||||||
LOG_DEBUGF("cli.c", "arg treemap_threshold=%f", args->treemap_threshold)
|
LOG_DEBUGF("cli.c", "arg treemap_threshold=%f", args->treemap_threshold)
|
||||||
LOG_DEBUGF("cli.c", "arg max_memory_buffer=%d", args->max_memory_buffer)
|
LOG_DEBUGF("cli.c", "arg max_memory_buffer=%d", args->max_memory_buffer)
|
||||||
|
LOG_DEBUGF("cli.c", "arg list_path=%s", args->list_path)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ typedef struct scan_args {
|
|||||||
int read_subtitles;
|
int read_subtitles;
|
||||||
int fast_epub;
|
int fast_epub;
|
||||||
int calculate_checksums;
|
int calculate_checksums;
|
||||||
|
char *list_path;
|
||||||
|
FILE *list_file;
|
||||||
} scan_args_t;
|
} scan_args_t;
|
||||||
|
|
||||||
scan_args_t *scan_args_create();
|
scan_args_t *scan_args_create();
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ typedef struct {
|
|||||||
|
|
||||||
GHashTable *original_table;
|
GHashTable *original_table;
|
||||||
GHashTable *copy_table;
|
GHashTable *copy_table;
|
||||||
|
pthread_mutex_t copy_table_mu;
|
||||||
|
|
||||||
pcre *exclude;
|
pcre *exclude;
|
||||||
pcre_extra *exclude_extra;
|
pcre_extra *exclude_extra;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <ftw.h>
|
#include <ftw.h>
|
||||||
|
|
||||||
|
#define STR_STARTS_WITH(x, y) (strncmp(y, x, strlen(y) - 1) == 0)
|
||||||
|
|
||||||
__always_inline
|
__always_inline
|
||||||
parse_job_t *create_fs_parse_job(const char *filepath, const struct stat *info, int base) {
|
parse_job_t *create_fs_parse_job(const char *filepath, const struct stat *info, int base) {
|
||||||
int len = (int) strlen(filepath);
|
int len = (int) strlen(filepath);
|
||||||
@@ -57,10 +59,11 @@ int handle_entry(const char *filepath, const struct stat *info, int typeflag, st
|
|||||||
pthread_mutex_lock(&ScanCtx.dbg_file_counts_mu);
|
pthread_mutex_lock(&ScanCtx.dbg_file_counts_mu);
|
||||||
ScanCtx.dbg_excluded_files_count += 1;
|
ScanCtx.dbg_excluded_files_count += 1;
|
||||||
pthread_mutex_unlock(&ScanCtx.dbg_file_counts_mu);
|
pthread_mutex_unlock(&ScanCtx.dbg_file_counts_mu);
|
||||||
return 0;
|
|
||||||
} else if (typeflag == FTW_D) {
|
} else if (typeflag == FTW_D) {
|
||||||
return FTW_SKIP_SUBTREE;
|
return FTW_SKIP_SUBTREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FTW_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeflag == FTW_F && S_ISREG(info->st_mode)) {
|
if (typeflag == FTW_F && S_ISREG(info->st_mode)) {
|
||||||
@@ -76,3 +79,57 @@ int handle_entry(const char *filepath, const struct stat *info, int typeflag, st
|
|||||||
int walk_directory_tree(const char *dirpath) {
|
int walk_directory_tree(const char *dirpath) {
|
||||||
return nftw(dirpath, handle_entry, MAX_FILE_DESCRIPTORS, FTW_PHYS | FTW_ACTIONRETVAL);
|
return nftw(dirpath, handle_entry, MAX_FILE_DESCRIPTORS, FTW_PHYS | FTW_ACTIONRETVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iterate_file_list(void *input_file) {
|
||||||
|
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), input_file) != NULL) {
|
||||||
|
|
||||||
|
// Remove trailing newline
|
||||||
|
*(buf + strlen(buf) - 1) = '\0';
|
||||||
|
|
||||||
|
int stat_ret = stat(buf, &info);
|
||||||
|
|
||||||
|
if (stat_ret != 0) {
|
||||||
|
LOG_ERRORF("walk.c", "Could not stat file %s (%s)", buf, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG(info.st_mode)) {
|
||||||
|
LOG_ERRORF("walk.c", "Is not a regular file: %s", buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *absolute_path = canonicalize_file_name(buf);
|
||||||
|
|
||||||
|
if (absolute_path == NULL) {
|
||||||
|
LOG_FATALF("walk.c", "FIXME: Could not get absolute path of %s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ScanCtx.exclude != NULL && EXCLUDED(absolute_path)) {
|
||||||
|
LOG_DEBUGF("walk.c", "Excluded: %s", absolute_path)
|
||||||
|
|
||||||
|
if (S_ISREG(info.st_mode)) {
|
||||||
|
pthread_mutex_lock(&ScanCtx.dbg_file_counts_mu);
|
||||||
|
ScanCtx.dbg_excluded_files_count += 1;
|
||||||
|
pthread_mutex_unlock(&ScanCtx.dbg_file_counts_mu);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!STR_STARTS_WITH(absolute_path, ScanCtx.index.desc.root)) {
|
||||||
|
LOG_FATALF("walk.c", "File is not a children of root folder (%s): %s", ScanCtx.index.desc.root, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int base = (int) (strrchr(buf, '/') - buf) + 1;
|
||||||
|
|
||||||
|
parse_job_t *job = create_fs_parse_job(absolute_path, &info, base);
|
||||||
|
free(absolute_path);
|
||||||
|
tpool_add_work(ScanCtx.pool, parse, job);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -5,4 +5,6 @@
|
|||||||
|
|
||||||
int walk_directory_tree(const char *);
|
int walk_directory_tree(const char *);
|
||||||
|
|
||||||
|
int iterate_file_list(void* input_file);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
19
src/main.c
19
src/main.c
@@ -14,6 +14,9 @@
|
|||||||
#include "parsing/mime.h"
|
#include "parsing/mime.h"
|
||||||
#include "parsing/parse.h"
|
#include "parsing/parse.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
|
||||||
#define DESCRIPTION "Lightning-fast file system indexer and search tool."
|
#define DESCRIPTION "Lightning-fast file system indexer and search tool."
|
||||||
@@ -29,8 +32,6 @@ static const char *const usage[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
#include<signal.h>
|
|
||||||
#include<unistd.h>
|
|
||||||
|
|
||||||
static __sighandler_t sigsegv_handler = NULL;
|
static __sighandler_t sigsegv_handler = NULL;
|
||||||
static __sighandler_t sigabrt_handler = NULL;
|
static __sighandler_t sigabrt_handler = NULL;
|
||||||
@@ -169,6 +170,7 @@ void initialize_scan_context(scan_args_t *args) {
|
|||||||
ScanCtx.dbg_current_files = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL);
|
ScanCtx.dbg_current_files = g_hash_table_new_full(g_int64_hash, g_int64_equal, NULL, NULL);
|
||||||
pthread_mutex_init(&ScanCtx.dbg_current_files_mu, NULL);
|
pthread_mutex_init(&ScanCtx.dbg_current_files_mu, NULL);
|
||||||
pthread_mutex_init(&ScanCtx.dbg_file_counts_mu, NULL);
|
pthread_mutex_init(&ScanCtx.dbg_file_counts_mu, NULL);
|
||||||
|
pthread_mutex_init(&ScanCtx.copy_table_mu, NULL);
|
||||||
|
|
||||||
ScanCtx.calculate_checksums = args->calculate_checksums;
|
ScanCtx.calculate_checksums = args->calculate_checksums;
|
||||||
|
|
||||||
@@ -334,10 +336,20 @@ void sist2_scan(scan_args_t *args) {
|
|||||||
ScanCtx.writer_pool = tpool_create(1, writer_cleanup, TRUE, FALSE);
|
ScanCtx.writer_pool = tpool_create(1, writer_cleanup, TRUE, FALSE);
|
||||||
tpool_start(ScanCtx.writer_pool);
|
tpool_start(ScanCtx.writer_pool);
|
||||||
|
|
||||||
|
if (args->list_path) {
|
||||||
|
// Scan using file list
|
||||||
|
int list_ret = iterate_file_list(args->list_file);
|
||||||
|
if (list_ret != 0) {
|
||||||
|
LOG_FATALF("main.c", "iterate_file_list() failed! (%d)", list_ret)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Scan directory recursively
|
||||||
int walk_ret = walk_directory_tree(ScanCtx.index.desc.root);
|
int walk_ret = walk_directory_tree(ScanCtx.index.desc.root);
|
||||||
if (walk_ret == -1) {
|
if (walk_ret == -1) {
|
||||||
LOG_FATALF("main.c", "walk_directory_tree() failed! %s (%d)", strerror(errno), errno)
|
LOG_FATALF("main.c", "walk_directory_tree() failed! %s (%d)", strerror(errno), errno)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tpool_wait(ScanCtx.pool);
|
tpool_wait(ScanCtx.pool);
|
||||||
tpool_destroy(ScanCtx.pool);
|
tpool_destroy(ScanCtx.pool);
|
||||||
|
|
||||||
@@ -577,6 +589,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
OPT_BOOLEAN(0, "fast-epub", &scan_args->fast_epub,
|
OPT_BOOLEAN(0, "fast-epub", &scan_args->fast_epub,
|
||||||
"Faster but less accurate EPUB parsing (no thumbnails, metadata)"),
|
"Faster but less accurate EPUB parsing (no thumbnails, metadata)"),
|
||||||
OPT_BOOLEAN(0, "checksums", &scan_args->calculate_checksums, "Calculate file checksums when scanning."),
|
OPT_BOOLEAN(0, "checksums", &scan_args->calculate_checksums, "Calculate file checksums when scanning."),
|
||||||
|
OPT_STRING(0, "list-file", &scan_args->list_path, "Specify a list of newline-delimited paths to be scanned"
|
||||||
|
" instead of normal directory traversal. Use '-' to read"
|
||||||
|
" from stdin."),
|
||||||
|
|
||||||
OPT_GROUP("Index options"),
|
OPT_GROUP("Index options"),
|
||||||
OPT_INTEGER('t', "threads", &common_threads, "Number of threads. DEFAULT=1"),
|
OPT_INTEGER('t', "threads", &common_threads, "Number of threads. DEFAULT=1"),
|
||||||
|
|||||||
@@ -79,7 +79,9 @@ void parse(void *arg) {
|
|||||||
|
|
||||||
int inc_ts = incremental_get(ScanCtx.original_table, doc->path_md5);
|
int inc_ts = incremental_get(ScanCtx.original_table, doc->path_md5);
|
||||||
if (inc_ts != 0 && inc_ts == job->vfile.info.st_mtim.tv_sec) {
|
if (inc_ts != 0 && inc_ts == job->vfile.info.st_mtim.tv_sec) {
|
||||||
|
pthread_mutex_lock(&ScanCtx.copy_table_mu);
|
||||||
incremental_mark_file_for_copy(ScanCtx.copy_table, doc->path_md5);
|
incremental_mark_file_for_copy(ScanCtx.copy_table, doc->path_md5);
|
||||||
|
pthread_mutex_unlock(&ScanCtx.copy_table_mu);
|
||||||
|
|
||||||
pthread_mutex_lock(&ScanCtx.dbg_file_counts_mu);
|
pthread_mutex_lock(&ScanCtx.dbg_file_counts_mu);
|
||||||
ScanCtx.dbg_skipped_files_count += 1;
|
ScanCtx.dbg_skipped_files_count += 1;
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "git_hash.h"
|
#include "git_hash.h"
|
||||||
|
|
||||||
#define VERSION "2.11.5"
|
#define VERSION "2.11.6"
|
||||||
static const char *const Version = VERSION;
|
static const char *const Version = VERSION;
|
||||||
|
|
||||||
#ifndef SIST_PLATFORM
|
#ifndef SIST_PLATFORM
|
||||||
|
|||||||
@@ -133,6 +133,9 @@ static int incremental_get_str(GHashTable *table, const char *path_md5) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not thread safe!
|
||||||
|
*/
|
||||||
__always_inline
|
__always_inline
|
||||||
static int incremental_mark_file_for_copy(GHashTable *table, const unsigned char path_md5[MD5_DIGEST_LENGTH]) {
|
static int incremental_mark_file_for_copy(GHashTable *table, const unsigned char path_md5[MD5_DIGEST_LENGTH]) {
|
||||||
char *ptr = malloc(MD5_STR_LENGTH);
|
char *ptr = malloc(MD5_STR_LENGTH);
|
||||||
|
|||||||
4
src/web/static_generated.c
vendored
4
src/web/static_generated.c
vendored
File diff suppressed because one or more lines are too long
20
third-party/libscan/libscan/ooxml/ooxml.c
vendored
20
third-party/libscan/libscan/ooxml/ooxml.c
vendored
@@ -15,18 +15,18 @@ static int should_read_part(const char *part) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( // Word
|
if ( // Word
|
||||||
STR_STARTS_WITH(part, "word/document.xml")
|
STR_STARTS_WITH_CONSTANT(part, "word/document.xml")
|
||||||
|| STR_STARTS_WITH(part, "word/footnotes.xml")
|
|| STR_STARTS_WITH_CONSTANT(part, "word/footnotes.xml")
|
||||||
|| STR_STARTS_WITH(part, "word/endnotes.xml")
|
|| STR_STARTS_WITH_CONSTANT(part, "word/endnotes.xml")
|
||||||
|| STR_STARTS_WITH(part, "word/footer")
|
|| STR_STARTS_WITH_CONSTANT(part, "word/footer")
|
||||||
|| STR_STARTS_WITH(part, "word/header")
|
|| STR_STARTS_WITH_CONSTANT(part, "word/header")
|
||||||
// PowerPoint
|
// PowerPoint
|
||||||
|| STR_STARTS_WITH(part, "ppt/slides/slide")
|
|| STR_STARTS_WITH_CONSTANT(part, "ppt/slides/slide")
|
||||||
|| STR_STARTS_WITH(part, "ppt/notesSlides/slide")
|
|| STR_STARTS_WITH_CONSTANT(part, "ppt/notesSlides/slide")
|
||||||
// Excel
|
// Excel
|
||||||
|| STR_STARTS_WITH(part, "xl/worksheets/sheet")
|
|| STR_STARTS_WITH_CONSTANT(part, "xl/worksheets/sheet")
|
||||||
|| STR_STARTS_WITH(part, "xl/sharedStrings.xml")
|
|| STR_STARTS_WITH_CONSTANT(part, "xl/sharedStrings.xml")
|
||||||
|| STR_STARTS_WITH(part, "xl/workbook.xml")
|
|| STR_STARTS_WITH_CONSTANT(part, "xl/workbook.xml")
|
||||||
) {
|
) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|||||||
10
third-party/libscan/libscan/raw/raw.c
vendored
10
third-party/libscan/libscan/raw/raw.c
vendored
@@ -143,7 +143,7 @@ void parse_raw(scan_raw_ctx_t *ctx, vfile_t *f, document_t *doc) {
|
|||||||
|
|
||||||
libraw_gps_info_t gps = libraw_lib->other.parsed_gps;
|
libraw_gps_info_t gps = libraw_lib->other.parsed_gps;
|
||||||
double gps_longitude_dec =
|
double gps_longitude_dec =
|
||||||
(gps.longtitude[0] + gps.longtitude[1] / 60 + gps.longtitude[2] / 3600) * DMS_REF(gps.longref);
|
(gps.longitude[0] + gps.longitude[1] / 60 + gps.longitude[2] / 3600) * DMS_REF(gps.longref);
|
||||||
snprintf(tmp, sizeof(tmp), "%.15f", gps_longitude_dec);
|
snprintf(tmp, sizeof(tmp), "%.15f", gps_longitude_dec);
|
||||||
if (gps_longitude_dec != 0.0) {
|
if (gps_longitude_dec != 0.0) {
|
||||||
APPEND_STR_META(doc, MetaExifGpsLongitudeDec, tmp)
|
APPEND_STR_META(doc, MetaExifGpsLongitudeDec, tmp)
|
||||||
@@ -163,7 +163,13 @@ void parse_raw(scan_raw_ctx_t *ctx, vfile_t *f, document_t *doc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
libraw_unpack_thumb(libraw_lib);
|
int unpack_ret = libraw_unpack_thumb(libraw_lib);
|
||||||
|
if (unpack_ret != 0) {
|
||||||
|
CTX_LOG_ERRORF(f->filepath, "libraw_unpack_thumb returned error code %d", unpack_ret)
|
||||||
|
free(buf);
|
||||||
|
libraw_close(libraw_lib);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int errc = 0;
|
int errc = 0;
|
||||||
libraw_processed_image_t *thumb = libraw_dcraw_make_mem_thumb(libraw_lib, &errc);
|
libraw_processed_image_t *thumb = libraw_dcraw_make_mem_thumb(libraw_lib, &errc);
|
||||||
|
|||||||
2
third-party/libscan/libscan/util.h
vendored
2
third-party/libscan/libscan/util.h
vendored
@@ -7,7 +7,7 @@
|
|||||||
#include "../third-party/utf8.h/utf8.h"
|
#include "../third-party/utf8.h/utf8.h"
|
||||||
#include "macros.h"
|
#include "macros.h"
|
||||||
|
|
||||||
#define STR_STARTS_WITH(x, y) (strncmp(y, x, sizeof(y) - 1) == 0)
|
#define STR_STARTS_WITH_CONSTANT(x, y) (strncmp(y, x, sizeof(y) - 1) == 0)
|
||||||
|
|
||||||
#define TEXT_BUF_FULL (-1)
|
#define TEXT_BUF_FULL (-1)
|
||||||
#define INITIAL_BUF_SIZE (1024 * 16)
|
#define INITIAL_BUF_SIZE (1024 * 16)
|
||||||
|
|||||||
17
third-party/libscan/test/main.cpp
vendored
17
third-party/libscan/test/main.cpp
vendored
@@ -227,7 +227,7 @@ TEST(Ebook, Utf8Pdf) {
|
|||||||
|
|
||||||
parse_ebook(&ebook_500_ctx, &f, "application/pdf", &doc);
|
parse_ebook(&ebook_500_ctx, &f, "application/pdf", &doc);
|
||||||
|
|
||||||
ASSERT_TRUE(STR_STARTS_WITH(get_meta(&doc, MetaContent)->str_val, "最後測試 "));
|
ASSERT_TRUE(STR_STARTS_WITH_CONSTANT(get_meta(&doc, MetaContent)->str_val, "最後測試 "));
|
||||||
cleanup(&doc, &f);
|
cleanup(&doc, &f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ TEST(Ebook, Utf8PdfInvalidChars) {
|
|||||||
// It should say "HART is a group of highly qualified ..." but the PDF
|
// It should say "HART is a group of highly qualified ..." but the PDF
|
||||||
// text is been intentionally fucked with by the authors
|
// text is been intentionally fucked with by the authors
|
||||||
// We can at least filter out the non-printable/invalid characters like '<27>' etc
|
// We can at least filter out the non-printable/invalid characters like '<27>' etc
|
||||||
ASSERT_TRUE(STR_STARTS_WITH(get_meta(&doc, MetaContent)->str_val, "HART i a g f highl alified "));
|
ASSERT_TRUE(STR_STARTS_WITH_CONSTANT(get_meta(&doc, MetaContent)->str_val, "HART i a g f highl alified "));
|
||||||
cleanup(&doc, &f);
|
cleanup(&doc, &f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,6 +780,19 @@ TEST(Arc, EncryptedZip) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* RAW */
|
/* RAW */
|
||||||
|
TEST(RAW, Segfault1) {
|
||||||
|
vfile_t f;
|
||||||
|
document_t doc;
|
||||||
|
load_doc_file("libscan-test-files/test_files/raw/segfault1.dng", &f, &doc);
|
||||||
|
|
||||||
|
parse_raw(&raw_ctx, &f, &doc);
|
||||||
|
|
||||||
|
ASSERT_EQ(get_meta(&doc, MetaWidth)->long_val, 3840);
|
||||||
|
ASSERT_EQ(get_meta(&doc, MetaHeight)->long_val, 7680);
|
||||||
|
|
||||||
|
cleanup(&doc, &f);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RAW, Panasonic) {
|
TEST(RAW, Panasonic) {
|
||||||
vfile_t f;
|
vfile_t f;
|
||||||
document_t doc;
|
document_t doc;
|
||||||
|
|||||||
Reference in New Issue
Block a user