2.2-stable
This commit is contained in:
parent
0933482f64
commit
95cbd11ba3
133
README.MD
133
README.MD
@ -69,8 +69,41 @@ Setting `NetworkEvents = false` in the server configuration disables the logging
|
|||||||
|
|
||||||
The `precaching` feature allows the server to pre-cache storage paths for faster access. This can improve performance by reducing the time needed to access frequently used storage paths.
|
The `precaching` feature allows the server to pre-cache storage paths for faster access. This can improve performance by reducing the time needed to access frequently used storage paths.
|
||||||
|
|
||||||
|
### Thumbnail Creation
|
||||||
|
|
||||||
|
Set `thumbnail` to true in the `[server]` section of `config.toml` to enable image thumbnail generation.
|
||||||
|
|
||||||
|
### Deduplication
|
||||||
|
|
||||||
|
Set `enabled` to true in the `[deduplication]` section of `config.toml` to enable file deduplication. Specify the `storagepath` where deduplicated files will be stored.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Deduplication
|
||||||
|
|
||||||
|
Set `enabled` to true in the `[deduplication]` section of `config.toml` to enable file deduplication. Specify the `directory` where deduplicated files will be stored.
|
||||||
|
|
||||||
|
### Example `config.toml`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[deduplication]
|
||||||
|
enabled = true
|
||||||
|
directory = "/mnt/hmac-storage/deduplication/"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Thumbnails
|
||||||
|
|
||||||
|
Set `enabled` to true in the `[thumbnails]` section of `config.toml` to enable thumbnail creation. Specify the `directory` where thumbnails will be stored and the `size` of the thumbnails.
|
||||||
|
|
||||||
|
### Example `config.toml`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[thumbnails]
|
||||||
|
enabled = true
|
||||||
|
directory = "/mnt/hmac-storage/thumbnails/"
|
||||||
|
size = "200x200"
|
||||||
|
```
|
||||||
|
|
||||||
## Example `config.toml`
|
## Example `config.toml`
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@ -89,6 +122,7 @@ AutoAdjustWorkers = true # Enable auto-adjustment for worker scaling
|
|||||||
NetworkEvents = false # Disable logging and tracking of network-related events
|
NetworkEvents = false # Disable logging and tracking of network-related events
|
||||||
PIDFilePath = "./hmac_file_server.pid" # Path to PID file
|
PIDFilePath = "./hmac_file_server.pid" # Path to PID file
|
||||||
Precaching = true # Enable pre-caching of storage paths
|
Precaching = true # Enable pre-caching of storage paths
|
||||||
|
ThumbnailEnabled = false # Whether to create thumbnails for uploaded images
|
||||||
|
|
||||||
[timeouts]
|
[timeouts]
|
||||||
ReadTimeout = "480s"
|
ReadTimeout = "480s"
|
||||||
@ -132,6 +166,105 @@ UploadQueueSize = 5000
|
|||||||
|
|
||||||
[file]
|
[file]
|
||||||
FileRevision = 1 # Revision number for file handling
|
FileRevision = 1 # Revision number for file handling
|
||||||
|
|
||||||
|
[deduplication]
|
||||||
|
enabled = true
|
||||||
|
storagepath = "/mnt/nfs_vol01/hmac-file-server/deduplication/"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## HMAC File Server - Version 2.2 Stable
|
||||||
|
|
||||||
|
Below is an example configuration file (config.toml) you can use as a reference (with sensitive data removed):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[server]
|
||||||
|
listenport = "8080"
|
||||||
|
unixsocket = false
|
||||||
|
storagepath = "/mnt/nfs_vol01/hmac-file-server/"
|
||||||
|
loglevel = "debug"
|
||||||
|
logfile = "/var/log/hmac-file-server.log"
|
||||||
|
metricsenabled = true
|
||||||
|
metricsport = "9090"
|
||||||
|
deduplicationenabled = true
|
||||||
|
minfreebytes = "5GB"
|
||||||
|
filettl = "2Y"
|
||||||
|
autoadjustworkers = true
|
||||||
|
networkevents = false
|
||||||
|
pidfilepath = "./hmac-file-server.pid"
|
||||||
|
precaching = true
|
||||||
|
|
||||||
|
[deduplication]
|
||||||
|
enabled = true
|
||||||
|
directory = "/mnt/nfs_vol01/hmac-storage/deduplication/"
|
||||||
|
|
||||||
|
[thumbnails]
|
||||||
|
enabled = true
|
||||||
|
directory = "/mnt/nfs_vol01/hmac-file-server/thumbnails/"
|
||||||
|
size = "200x200"
|
||||||
|
|
||||||
|
[iso]
|
||||||
|
enabled = false
|
||||||
|
size = "1TB"
|
||||||
|
mountpoint = "/mnt/nfs_vol01/hmac-file-server/iso/"
|
||||||
|
charset = "utf-8"
|
||||||
|
|
||||||
|
[timeouts]
|
||||||
|
readtimeout = "3600s"
|
||||||
|
writetimeout = "3600s"
|
||||||
|
idletimeout = "3600s"
|
||||||
|
|
||||||
|
[security]
|
||||||
|
secret = "stellar-wisdom-orbit-echo"
|
||||||
|
|
||||||
|
[versioning]
|
||||||
|
enableversioning = false
|
||||||
|
maxversions = 1
|
||||||
|
|
||||||
|
[uploads]
|
||||||
|
resumableuploadsenabled = false
|
||||||
|
chunkeduploadsenabled = true
|
||||||
|
chunksize = "32MB"
|
||||||
|
allowedextensions = [
|
||||||
|
".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif",
|
||||||
|
".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4",
|
||||||
|
".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm",
|
||||||
|
".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg"
|
||||||
|
]
|
||||||
|
|
||||||
|
[downloads]
|
||||||
|
chunkeddownloadsenabled = false
|
||||||
|
chunksize = "32MB"
|
||||||
|
allowedextensions = [
|
||||||
|
".txt", ".pdf", ".png", ".jpg", ".jpeg", ".gif",
|
||||||
|
".bmp", ".tiff", ".svg", ".webp", ".wav", ".mp4",
|
||||||
|
".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm",
|
||||||
|
".mpeg", ".mpg", ".m4v", ".3gp", ".3g2", ".mp3", ".ogg"
|
||||||
|
]
|
||||||
|
|
||||||
|
[clamav]
|
||||||
|
clamavenabled = true
|
||||||
|
clamavsocket = "/var/run/clamav/clamd.ctl"
|
||||||
|
numscanworkers = 4
|
||||||
|
scanfileextensions = [
|
||||||
|
".exe", ".dll", ".bin", ".com", ".bat",
|
||||||
|
".sh", ".php", ".js"
|
||||||
|
]
|
||||||
|
|
||||||
|
[redis]
|
||||||
|
redisenabled = true
|
||||||
|
redisdbindex = 0
|
||||||
|
redisaddr = "localhost:6379"
|
||||||
|
redispassword = ""
|
||||||
|
redishealthcheckinterval = "120s"
|
||||||
|
|
||||||
|
[workers]
|
||||||
|
numworkers = 4
|
||||||
|
uploadqueuesize = 5000
|
||||||
|
|
||||||
|
[file]
|
||||||
|
filerevision = 1
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# Release Notes - hmac-file-server v2.1-stable
|
# Release Notes - hmac-file-server v2.2-stable
|
||||||
|
|
||||||
**Release Date:** April 27, 2024
|
**Release Date:** December 24, 2024
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
We are excited to announce the release of **hmac-file-server v2.1-stable**. This version brings significant enhancements, new features, and important bug fixes to improve the performance, security, and usability of the HMAC File Server. Below are the detailed changes and updates included in this release.
|
We are excited to announce the release of **hmac-file-server v2.2-stable**. This version brings significant enhancements, new features, and important bug fixes to improve the performance, security, and usability of the HMAC File Server. Below are the detailed changes and updates included in this release.
|
||||||
|
|
||||||
## New Features
|
## New Features
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ We are excited to announce the release of **hmac-file-server v2.1-stable**. This
|
|||||||
2. **Update Application:**
|
2. **Update Application:**
|
||||||
- Pull the latest version from the repository:
|
- Pull the latest version from the repository:
|
||||||
```sh
|
```sh
|
||||||
git pull origin v2.1-stable
|
git pull origin v2.2-stable
|
||||||
```
|
```
|
||||||
- Alternatively, download the latest release from the [releases page](https://github.com/PlusOne/hmac-file-server/releases).
|
- Alternatively, download the latest release from the [releases page](https://github.com/PlusOne/hmac-file-server/releases).
|
||||||
|
|
||||||
@ -154,3 +154,70 @@ For any issues or questions regarding this release, please open an issue on our
|
|||||||
---
|
---
|
||||||
|
|
||||||
*Thank you for using hmac-file-server! We hope this release enhances your experience and meets your needs effectively.*
|
*Thank you for using hmac-file-server! We hope this release enhances your experience and meets your needs effectively.*
|
||||||
|
|
||||||
|
## Release Notes - Version 2.2 Stable
|
||||||
|
|
||||||
|
### What's New in Version 2.2:
|
||||||
|
|
||||||
|
- **Enhanced Deduplication Mechanism:**
|
||||||
|
- Fixed issues related to SHA256 checksum validation, ensuring accurate file deduplication.
|
||||||
|
- Improved error handling for deduplication processes, preventing failures when referencing existing files.
|
||||||
|
|
||||||
|
- **ClamAV and Redis Optimizations:**
|
||||||
|
- Streamlined ClamAV initialization for faster malware scanning.
|
||||||
|
- Optimized Redis connection handling for better caching performance and reliability.
|
||||||
|
|
||||||
|
- **Configuration Improvements:**
|
||||||
|
- Introduced new configuration parameters for finer control over deduplication directories and checksum algorithms.
|
||||||
|
- Enhanced `config.toml` validation to ensure all necessary fields are correctly set, reducing runtime errors.
|
||||||
|
|
||||||
|
- **Logging Enhancements:**
|
||||||
|
- Improved log formatting for easier troubleshooting and monitoring.
|
||||||
|
- Added detailed logs for deduplication steps, providing clearer visibility into the deduplication process.
|
||||||
|
|
||||||
|
- **Performance Upgrades:**
|
||||||
|
- Further optimized auto-adjusting worker pools to handle higher loads with minimal latency.
|
||||||
|
- Reduced memory footprint during peak operations, ensuring consistent performance.
|
||||||
|
|
||||||
|
### Key Fixes:
|
||||||
|
|
||||||
|
- **Deduplication Directory Validation:**
|
||||||
|
- Resolved issues where the deduplication directory was not correctly recognized, preventing file reference errors.
|
||||||
|
|
||||||
|
- **Error Handling Enhancements:**
|
||||||
|
- Improved error messages and fallback mechanisms for ClamAV and Redis initialization failures.
|
||||||
|
|
||||||
|
- **Configuration Cleanup:**
|
||||||
|
- Removed deprecated parameters and streamlined configuration settings for easier management and clarity.
|
||||||
|
|
||||||
|
### Upgrading to Version 2.2:
|
||||||
|
|
||||||
|
1. **Pull the Latest Release:**
|
||||||
|
```sh
|
||||||
|
git pull https://github.com/PlusOne/hmac-file-server.git
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Update Dependencies:**
|
||||||
|
```sh
|
||||||
|
go mod tidy
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Review and Update `config.toml`:**
|
||||||
|
- Ensure all new configuration parameters are set.
|
||||||
|
- Validate the `deduplication.directory` path and permissions.
|
||||||
|
- Example `deduplication` section:
|
||||||
|
```toml
|
||||||
|
[deduplication]
|
||||||
|
enabled = true
|
||||||
|
directory = "/mnt/hmac-storage/deduplication/"
|
||||||
|
checksum_algorithm = "sha256" # New parameter for checksum selection
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Restart the Application:**
|
||||||
|
```sh
|
||||||
|
./hmac-file-server
|
||||||
|
```
|
||||||
|
|
||||||
|
### Enjoy Enhanced Performance and Security!
|
||||||
|
|
||||||
|
With Version 2.2, experience more reliable file handling, robust security measures, and optimized performance. Upgrade now to take advantage of these powerful improvements!
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
listenport = "8080"
|
listenport = "8080"
|
||||||
unixsocket = false
|
unixsocket = false
|
||||||
storagepath = "./uploads"
|
storagepath = "./uploads"
|
||||||
loglevel = "debug"
|
loglevel = "debug"Q
|
||||||
logfile = "./hmac-file-server.log"
|
logfile = "./hmac-file-server.log"
|
||||||
metricsenabled = true
|
metricsenabled = true
|
||||||
metricsport = "8081"
|
metricsport = "8081"
|
||||||
@ -15,6 +15,7 @@ temppath = "/tmp/hmac"
|
|||||||
loggingjson = false
|
loggingjson = false
|
||||||
pidfilepath = "./hmac_file_server.pid"
|
pidfilepath = "./hmac_file_server.pid"
|
||||||
cleanuponexit = true
|
cleanuponexit = true
|
||||||
|
precaching = true
|
||||||
|
|
||||||
[iso]
|
[iso]
|
||||||
enabled = false
|
enabled = false
|
||||||
|
Binary file not shown.
119
cmd/server/hmac-file-server.log
Normal file
119
cmd/server/hmac-file-server.log
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="========================================"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg=" HMAC File Server - v2.0-dev "
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg=" Secure File Handling with HMAC Auth "
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="========================================"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Features: Prometheus Metrics, Chunked Uploads, ClamAV Scanning"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Build Date: 2024-10-28"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Operating System: linux"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Architecture: amd64"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Number of CPUs: 8"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Go Version: go1.22.0"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Total Memory: 15684 MB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Free Memory: 2378 MB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Used Memory: 5770 MB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="CPU Model: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz, Cores: 1, Mhz: 4900.000000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /, Total: 465 GB, Free: 58 GB, Used: 383 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/backupz/6, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/brave/458, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/brave/456, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/bare/5, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/canonical-livepatch/282, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/canonical-livepatch/286, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/cameractrls/35, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/cameractrls/34, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/cmake/1425, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/cmake/1429, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core/17200, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core18/2846, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core18/2829, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core20/2379, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core20/2434, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core24/490, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core22/1663, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core24/609, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/drawio/228, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/duplicity/513, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/drawio/230, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/duplicity/517, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/dynahack/32, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/firefox/5273, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/firefox/5361, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/firmware-updater/127, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/firmware-updater/147, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gaming-graphics-core22/166, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gaming-graphics-core22/184, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gnome-3-28-1804/198, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gnome-3-34-1804/93, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gnome-3-38-2004/143, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gnome-42-2204/176, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/godot/45, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gnome-46-2404/48, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/hello-world/29, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/gtk-common-themes/1535, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/kf5-5-110-qt-5-15-11-core22/3, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/kf5-5-113-qt-5-15-11-core22/1, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/marble/32, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/master-pdf-editor-5/20, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/master-pdf-editor-5/21, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/mesa-2404/143, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/mesa-core22/311, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/micropolis/168, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/mkcron/2, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/obs-studio/1302, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/qownnotes/11552, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/qownnotes/11560, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/qt513/24, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/remmina/6419, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/retroarch/2879, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snap-store/1244, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snapd/21759, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snapd/23258, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snapd-desktop-integration/247, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/steam/200, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snapd-desktop-integration/253, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/sublime-text/156, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/steam/206, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/sublime-text/177, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/suckit/49, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/teleguard-desktop/91, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/thunderbird/571, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/thunderbird/581, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/wine-platform-7-stable-core20/6, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /var/snap/firefox/common/host-hunspell, Total: 465 GB, Free: 58 GB, Used: 383 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/winbox/171, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/video-downloader/1212, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/winbox/170, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/wine-platform-runtime-core20/146, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/wine-platform-runtime-core20/147, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /boot, Total: 1 GB, Free: 1 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /boot/efi, Total: 1 GB, Free: 1 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /media/renz/external, Total: 116 GB, Free: 80 GB, Used: 29 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/video-downloader/1221, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/core22/1722, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/snap-store/1247, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Disk Mountpoint: /snap/teleguard-desktop/94, Total: 0 GB, Free: 0 GB, Used: 0 GB"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Hostname: xps7390"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Uptime: 35037 seconds"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Boot Time: 2024-12-04 07:38:06 +0100 CET"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Platform: ubuntu"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Platform Family: debian"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Platform Version: 24.04"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Kernel Version: 6.8.0-49-generic"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Prometheus metrics initialized."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload queue initialized with size: 1000"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload, scan, and network event channels initialized."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Initialized 4 upload workers"
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload worker 2 started."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload worker 1 started."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload worker 3 started."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Upload worker 0 started."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Starting HMAC file server v2.0-dev..."
|
||||||
|
time="2024-12-04T17:22:02+01:00" level=info msg="Metrics server started on port 9090"
|
||||||
|
time="2024-12-04T17:22:03+01:00" level=info msg="Received signal interrupt. Initiating shutdown..."
|
@ -38,6 +38,7 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
)
|
)
|
||||||
|
|
||||||
// parseSize converts a human-readable size string to bytes
|
// parseSize converts a human-readable size string to bytes
|
||||||
@ -111,6 +112,7 @@ type ServerConfig struct {
|
|||||||
NetworkEvents bool `mapstructure:"NetworkEvents"` // Added field
|
NetworkEvents bool `mapstructure:"NetworkEvents"` // Added field
|
||||||
PrecachingEnabled bool `mapstructure:"precaching"` // Added field
|
PrecachingEnabled bool `mapstructure:"precaching"` // Added field
|
||||||
PIDFilePath string `mapstructure:"pidfilepath"` // Added field
|
PIDFilePath string `mapstructure:"pidfilepath"` // Added field
|
||||||
|
ThumbnailEnabled bool `mapstructure:"thumbnail"` // Added field
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimeoutConfig struct {
|
type TimeoutConfig struct {
|
||||||
@ -176,6 +178,17 @@ type DownloadsConfig struct {
|
|||||||
ChunkSize string `mapstructure:"ChunkSize"`
|
ChunkSize string `mapstructure:"ChunkSize"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeduplicationConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Directory string `mapstructure:"directory"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThumbnailsConfig struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Directory string `mapstructure:"directory"`
|
||||||
|
Size string `mapstructure:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Server ServerConfig `mapstructure:"server"`
|
Server ServerConfig `mapstructure:"server"`
|
||||||
Timeouts TimeoutConfig `mapstructure:"timeouts"`
|
Timeouts TimeoutConfig `mapstructure:"timeouts"`
|
||||||
@ -189,6 +202,8 @@ type Config struct {
|
|||||||
File FileConfig `mapstructure:"file"`
|
File FileConfig `mapstructure:"file"`
|
||||||
ISO ISOConfig `mapstructure:"iso"`
|
ISO ISOConfig `mapstructure:"iso"`
|
||||||
Paste PasteConfig `mapstructure:"paste"`
|
Paste PasteConfig `mapstructure:"paste"`
|
||||||
|
Deduplication DeduplicationConfig `mapstructure:"deduplication"`
|
||||||
|
Thumbnails ThumbnailsConfig `mapstructure:"thumbnails"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UploadTask struct {
|
type UploadTask struct {
|
||||||
@ -209,7 +224,7 @@ type NetworkEvent struct {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
conf Config
|
conf Config
|
||||||
versionString string = "v2.1-stable"
|
versionString string = "v2.2-stable"
|
||||||
log = logrus.New()
|
log = logrus.New()
|
||||||
uploadQueue chan UploadTask
|
uploadQueue chan UploadTask
|
||||||
networkEvents chan NetworkEvent
|
networkEvents chan NetworkEvent
|
||||||
@ -549,6 +564,7 @@ func setDefaults() {
|
|||||||
viper.SetDefault("server.NetworkEvents", true) // Set default
|
viper.SetDefault("server.NetworkEvents", true) // Set default
|
||||||
viper.SetDefault("server.precaching", true) // Set default for precaching
|
viper.SetDefault("server.precaching", true) // Set default for precaching
|
||||||
viper.SetDefault("server.pidfilepath", "/var/run/hmacfileserver.pid") // Set default for PID file path
|
viper.SetDefault("server.pidfilepath", "/var/run/hmacfileserver.pid") // Set default for PID file path
|
||||||
|
viper.SetDefault("server.thumbnail", false) // Set default for thumbnail
|
||||||
_, err := parseTTL("1D")
|
_, err := parseTTL("1D")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("Failed to parse TTL: %v", err)
|
log.Warnf("Failed to parse TTL: %v", err)
|
||||||
@ -700,6 +716,48 @@ func validateConfig(conf *Config) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.Deduplication.Enabled {
|
||||||
|
if conf.Deduplication.Directory == "" {
|
||||||
|
return fmt.Errorf("deduplication.directory is required when deduplication is enabled")
|
||||||
|
}
|
||||||
|
// Optionally, check if deduplication directory exists
|
||||||
|
if _, err := os.Stat(conf.Deduplication.Directory); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("deduplication.directory does not exist: %s", conf.Deduplication.Directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if conf.Thumbnails.Enabled {
|
||||||
|
if conf.Thumbnails.Directory == "" {
|
||||||
|
return fmt.Errorf("thumbnails.directory is required when thumbnails are enabled")
|
||||||
|
}
|
||||||
|
// Optionally, check if thumbnails storage path exists
|
||||||
|
if _, err := os.Stat(conf.Thumbnails.Directory); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("thumbnails.directory does not exist: %s", conf.Thumbnails.Directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the primary storage path is accessible
|
||||||
|
if err := checkStoragePath(conf.Server.StoragePath); err != nil {
|
||||||
|
return fmt.Errorf("storage path check failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkStoragePath(path string) error {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Errorf("Storage path does not exist: %s", path)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Error accessing storage path: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !info.IsDir() {
|
||||||
|
return fmt.Errorf("not a directory: %s", path)
|
||||||
|
}
|
||||||
|
log.Infof("Verified storage path is accessible: %s", path)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +807,7 @@ func logSystemInfo() {
|
|||||||
cpuInfo, _ := cpu.Info()
|
cpuInfo, _ := cpu.Info()
|
||||||
uniqueCPUModels := make(map[string]bool)
|
uniqueCPUModels := make(map[string]bool)
|
||||||
for _, info := range cpuInfo {
|
for _, info := range cpuInfo {
|
||||||
if !uniqueCPUModels[info.ModelName] {
|
if (!uniqueCPUModels[info.ModelName]) {
|
||||||
log.Infof("CPU Model: %s, Cores: %d, Mhz: %f", info.ModelName, info.Cores, info.Mhz)
|
log.Infof("CPU Model: %s, Cores: %d, Mhz: %f", info.ModelName, info.Cores, info.Mhz)
|
||||||
uniqueCPUModels[info.ModelName] = true
|
uniqueCPUModels[info.ModelName] = true
|
||||||
}
|
}
|
||||||
@ -815,6 +873,7 @@ func updateSystemMetrics(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fileExists(filePath string) (bool, int64) {
|
func fileExists(filePath string) (bool, int64) {
|
||||||
|
log.Debugf("Checking file existence: %s", filePath)
|
||||||
if cachedInfo, found := fileInfoCache.Get(filePath); found {
|
if cachedInfo, found := fileInfoCache.Get(filePath); found {
|
||||||
if info, ok := cachedInfo.(os.FileInfo); ok {
|
if info, ok := cachedInfo.(os.FileInfo); ok {
|
||||||
return !info.IsDir(), info.Size()
|
return !info.IsDir(), info.Size()
|
||||||
@ -950,7 +1009,23 @@ func processUpload(task UploadTask) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := os.Rename(tempFilename, absFilename)
|
// Compute file hash first:
|
||||||
|
hashVal, err := computeSHA256(context.Background(), tempFilename)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Could not compute hash: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Computed hash for %s: %s", absFilename, hashVal)
|
||||||
|
|
||||||
|
// Check Redis for existing entry:
|
||||||
|
existingPath, redisErr := redisClient.Get(context.Background(), hashVal).Result()
|
||||||
|
if redisErr == nil && existingPath != "" {
|
||||||
|
log.Warnf("Duplicate upload detected. Using existing file at: %s", existingPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Renaming temp file %s -> %s", tempFilename, absFilename)
|
||||||
|
err = os.Rename(tempFilename, absFilename)
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Remove(tempFilename)
|
os.Remove(tempFilename)
|
||||||
@ -962,6 +1037,10 @@ func processUpload(task UploadTask) error {
|
|||||||
}
|
}
|
||||||
log.Infof("File moved to final destination: %s", absFilename)
|
log.Infof("File moved to final destination: %s", absFilename)
|
||||||
|
|
||||||
|
log.Debugf("Verifying existence immediately after rename: %s", absFilename)
|
||||||
|
exists, size := fileExists(absFilename)
|
||||||
|
log.Debugf("Exists? %v, Size: %d", exists, size)
|
||||||
|
|
||||||
// Gajim and Dino do not require a callback or acknowledgement beyond HTTP success.
|
// Gajim and Dino do not require a callback or acknowledgement beyond HTTP success.
|
||||||
callbackURL := r.Header.Get("Callback-URL")
|
callbackURL := r.Header.Get("Callback-URL")
|
||||||
if callbackURL != "" {
|
if callbackURL != "" {
|
||||||
@ -970,6 +1049,9 @@ func processUpload(task UploadTask) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if conf.Server.DeduplicationEnabled {
|
if conf.Server.DeduplicationEnabled {
|
||||||
|
log.Debugf("Performing deduplication check for %s", task.AbsFilename)
|
||||||
|
log.Debugf("Dedup check: Using hash %s to find existing path", hashVal)
|
||||||
|
log.Debugf("Existing path found in Redis: %s", existingPath)
|
||||||
err = handleDeduplication(context.Background(), absFilename)
|
err = handleDeduplication(context.Background(), absFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Deduplication failed")
|
log.WithError(err).Error("Deduplication failed")
|
||||||
@ -989,6 +1071,25 @@ func processUpload(task UploadTask) error {
|
|||||||
log.Infof("ISO container handled successfully for file: %s", absFilename)
|
log.Infof("ISO container handled successfully for file: %s", absFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conf.Thumbnails.Enabled {
|
||||||
|
err = generateThumbnail(absFilename, conf.Thumbnails.Directory, conf.Thumbnails.Size)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to generate thumbnail for %s: %v", absFilename, err)
|
||||||
|
uploadErrorsTotal.Inc()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Infof("Thumbnail generated for %s", absFilename)
|
||||||
|
}
|
||||||
|
|
||||||
|
if redisClient != nil {
|
||||||
|
errSet := redisClient.Set(context.Background(), hashVal, absFilename, 0).Err()
|
||||||
|
if errSet != nil {
|
||||||
|
log.Warnf("Failed storing hash reference: %v", errSet)
|
||||||
|
} else {
|
||||||
|
log.Infof("Hash reference stored: %s -> %s", hashVal, absFilename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.WithFields(logrus.Fields{"file": absFilename}).Info("File uploaded and processed successfully")
|
log.WithFields(logrus.Fields{"file": absFilename}).Info("File uploaded and processed successfully")
|
||||||
|
|
||||||
uploadDuration.Observe(time.Since(startTime).Seconds())
|
uploadDuration.Observe(time.Since(startTime).Seconds())
|
||||||
@ -1359,16 +1460,24 @@ func handleUpload(w http.ResponseWriter, r *http.Request, absFilename, fileStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDownload(w http.ResponseWriter, r *http.Request, absFilename, fileStorePath string) {
|
func handleDownload(w http.ResponseWriter, r *http.Request, absFilename, fileStorePath string) {
|
||||||
|
log.Debugf("Attempting to download file from path: %s", absFilename)
|
||||||
|
|
||||||
fileInfo, err := getFileInfo(absFilename)
|
fileInfo, err := getFileInfo(absFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("Failed to get file information")
|
log.Errorf("Failed to get file information for %s: %v", absFilename, err)
|
||||||
http.Error(w, "Not Found", http.StatusNotFound)
|
// If file doesn't exist, list directory contents for debug
|
||||||
downloadErrorsTotal.Inc()
|
if os.IsNotExist(err) {
|
||||||
return
|
dir := filepath.Dir(absFilename)
|
||||||
} else if fileInfo.IsDir() {
|
items, dirErr := os.ReadDir(dir)
|
||||||
log.Warn("Directory listing forbidden")
|
if dirErr == nil {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
for _, it := range items {
|
||||||
downloadErrorsTotal.Inc()
|
log.Debugf("Dir item: %s", it.Name())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Warnf("Could not read directory %s: %v", dir, dirErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1959,43 +2068,39 @@ func checkStorageSpace(storagePath string, minFreeBytes int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func handleDeduplication(ctx context.Context, absFilename string) error {
|
func handleDeduplication(ctx context.Context, absFilename string) error {
|
||||||
|
log.Debugf("Starting deduplication for: %s", absFilename)
|
||||||
checksum, err := computeSHA256(ctx, absFilename)
|
checksum, err := computeSHA256(ctx, absFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to compute SHA256 for %s: %v", absFilename, err)
|
log.Errorf("Failed to compute checksum for %s: %v", absFilename, err)
|
||||||
return fmt.Errorf("checksum computation failed: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
log.Debugf("Computed checksum for %s: %s", absFilename, checksum)
|
log.Debugf("Computed checksum for %s: %s", absFilename, checksum)
|
||||||
|
|
||||||
existingPath, err := redisClient.Get(ctx, checksum).Result()
|
existingPath, err := redisClient.Get(ctx, checksum).Result()
|
||||||
if err != nil {
|
|
||||||
if err == redis.Nil {
|
if err == redis.Nil {
|
||||||
|
log.Debugf("No existing file found for checksum %s", checksum)
|
||||||
err = redisClient.Set(ctx, checksum, absFilename, 0).Err()
|
err = redisClient.Set(ctx, checksum, absFilename, 0).Err()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Redis error setting checksum %s: %v", checksum, err)
|
log.Errorf("Failed to set checksum in Redis: %v", err)
|
||||||
return fmt.Errorf("redis error: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
log.Infof("Stored new checksum %s for file %s", checksum, absFilename)
|
log.Infof("Stored checksum %s with path %s in Redis", checksum, absFilename)
|
||||||
return nil
|
return nil
|
||||||
}
|
} else if err != nil {
|
||||||
log.Errorf("Redis error fetching checksum %s: %v", checksum, err)
|
log.Errorf("Redis lookup error: %v", err)
|
||||||
return fmt.Errorf("redis error: %w", err)
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
if existingPath != absFilename {
|
|
||||||
if _, err := os.Stat(existingPath); os.IsNotExist(err) {
|
|
||||||
log.Errorf("Existing file for checksum %s not found at %s", checksum, existingPath)
|
|
||||||
return fmt.Errorf("existing file not found: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("Found existing file for checksum %s at %s", checksum, existingPath)
|
||||||
err = os.Link(existingPath, absFilename)
|
err = os.Link(existingPath, absFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed linking %s to %s: %v", existingPath, absFilename, err)
|
log.Errorf("Failed to create hard link: %v", err)
|
||||||
return fmt.Errorf("failed link: %w", err)
|
return err
|
||||||
}
|
|
||||||
log.Infof("Created hard link for duplicate file %s -> %s", absFilename, existingPath)
|
|
||||||
} else {
|
|
||||||
log.Infof("File %s already exists with same checksum", absFilename)
|
|
||||||
}
|
}
|
||||||
|
log.Infof("Created hard link from %s to %s", absFilename, existingPath)
|
||||||
|
|
||||||
|
exists, size := fileExists(existingPath)
|
||||||
|
log.Debugf("Post-dedup check: Exists=%v, Size=%d at %s", exists, size, existingPath)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -2179,3 +2284,47 @@ func precacheStoragePath(dir string) error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateThumbnail(originalPath, thumbnailDir, size string) error {
|
||||||
|
// Implement thumbnail generation logic here
|
||||||
|
// For example, using an image processing library like "github.com/disintegration/imaging"
|
||||||
|
|
||||||
|
img, err := imaging.Open(originalPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse size (e.g., "200x200")
|
||||||
|
dimensions := strings.Split(size, "x")
|
||||||
|
if len(dimensions) != 2 {
|
||||||
|
return fmt.Errorf("invalid thumbnail size format: %s", size)
|
||||||
|
}
|
||||||
|
|
||||||
|
width, err := strconv.Atoi(dimensions[0])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid thumbnail width: %s", dimensions[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
height, err := strconv.Atoi(dimensions[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid thumbnail height: %s", dimensions[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
thumb := imaging.Thumbnail(img, width, height, imaging.Lanczos) // Example size
|
||||||
|
|
||||||
|
baseName := filepath.Base(originalPath)
|
||||||
|
thumbName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) + "_thumb" + filepath.Ext(baseName)
|
||||||
|
thumbPath := filepath.Join(thumbnailDir, thumbName)
|
||||||
|
|
||||||
|
err = os.MkdirAll(thumbnailDir, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imaging.Save(thumb, thumbPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
12
go.mod
12
go.mod
@ -10,7 +10,7 @@ require (
|
|||||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5
|
github.com/shirou/gopsutil/v3 v3.24.5
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.11.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -26,26 +26,24 @@ require (
|
|||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
|
||||||
golang.org/x/term v0.17.0 // indirect
|
golang.org/x/term v0.17.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
|
30
go.sum
30
go.sum
@ -3,11 +3,12 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
|
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e h1:rcHHSQqzCgvlwP0I/fQ8rQMn/MpHE5gWSLdtpxtP6KQ=
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e h1:rcHHSQqzCgvlwP0I/fQ8rQMn/MpHE5gWSLdtpxtP6KQ=
|
||||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e/go.mod h1:Byz7q8MSzSPkouskHJhX0er2mZY/m0Vj5bMeMCkkyY4=
|
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e/go.mod h1:Byz7q8MSzSPkouskHJhX0er2mZY/m0Vj5bMeMCkkyY4=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
@ -60,9 +61,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
|
|||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
@ -81,10 +81,6 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
|||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
|
||||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||||
@ -95,21 +91,21 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
|||||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
|
||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||||
|
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
github.com/spf13/viper v1.11.0 h1:7OX/1FS6n7jHD1zGrZTM7WtY13ZELRyosK4k93oPr44=
|
||||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
github.com/spf13/viper v1.11.0/go.mod h1:djo0X/bA5+tYVoCn+C7cAYJGcVn/qYLFTG8gdUsX7Zk=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
@ -126,14 +122,10 @@ github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS
|
|||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
|
||||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
Loading…
x
Reference in New Issue
Block a user