- Add comment explaining grep -v usage for filename extraction
- Document delete_empty_dirs state handling for both rsync methods
- Add trim() to progress line parsing to fix array indexing issue
caused by leading whitespace in rsync output
Use process substitution with stdbuf to capture rsync progress output
line-by-line in real-time. The '> >(stdbuf -o0 tr '\r' '\n' >status)'
pattern ensures unbuffered conversion of carriage returns to newlines,
allowing parse_rsync_progress() to read the latest updates via tac.
- Add stdbuf -o0 to enable real-time progress updates in status file
- Capture rsync PID using subshell: { echo $!; tr ... }
Testing if this resolves buffering and PID tracking issues.
- Add stdbuf -oL to rsync commands for immediate line-buffered output
Fixes choppy/delayed progress updates in status file during transfers
- Switch from grep -P to -E with [0-9]+ patterns for POSIX compatibility
Eliminates 'stray \ before d' warnings and improves portability
More explicit and readable than \d+ shortcuts
- Update comments about rsync progress format differences:
Running transfers show ETA, completed files show actual transfer time
1. Fixed status parsing bug where 'Completed: 118.88G, Speed: 2%, ETA: 58.91MB/s'
showed wrong value assignments due to tr -s '[:space:]' compressing newlines.
- Changed to tr -s ' \t' to preserve newlines
- Optimized with shell-based tac/grep approach for better performance
- Handles large rsync status files with thousands of progress lines efficiently
2. Added --no-inc-recursive flag to fix rsync creating directories with 0700 root:root
permissions during copy-delete operations, causing SMB access issues.
- Disables incremental recursion to avoid generator.c:1430 do_mkdir(...& 0700)
- Should preserve 1:1 source permissions and improve progress calculation
- NOTE: This is experimental and needs testing on dev server
Both fixes target the copy-delete operation (move files) that was most problematic.
Prevents moving a directory into its own subdirectory, which would cause
rsync --backup-dir to create nested structures and fail to delete source.
Example prevented: /mnt/disk1/parent → /mnt/disk1/parent/subfolder
The check uses trailing slashes to ensure exact directory boundary matching
and prevent false positives (e.g., /parent vs /parent2).
- Renamed $move variable to $delete_empty_dirs for clearer intent
- Variable now only set to true for rsync copy-delete (not for rsync-rename)
- rsync-rename doesn't need cleanup since source is atomically moved
- Added commented code to prevent moving directory into its own subdirectory
Initialize text array as indexed array to prevent associative array
when only progress line is parsed. Ensures text[0] is always set,
avoiding JSON output like {"1":"..."} in WebGUI.
Multiple improvements to file_manager reliability and status handling:
1. Fix rsync output parsing bug
- rsync returns filename and progress lines in unpredictable order
- Old JS parsing: text[1].split() assumed fixed line order
- New approach: Simplified shell parsing (tail + tr) in PHP
- parse_rsync_progress() helper function for consistent handling
2. Migrate status updates to JSON format
- Structure: {action: int, text: [file_text, progress_text?]}
- PHP: mb_strimhalf() for UTF-8-safe middle truncation
- PHP: htmlspecialchars() escaping, JS adds icons client-side
- Minimizes WebSocket overhead (no HTML in payload)
- Universal handler in BrowseButton.page (6 lines)
3. Fix stale status messages (Nchan caching issue)
- rc.nginx: nchan_message_timeout 30s for /pub/filemanager
- Status expires automatically after 30s
- Prevents displaying outdated progress status in footer
4. Remove obsolete move operation variants (case 5/10)
- file_manager: Remove case 5/10 comments (mv-based move)
- Browse.page: Remove action++ logic from doAction/doActions
- BrowseButton.page: Remove case 5/10 from dfm_makeDialog()
- All moves now use case 4/9 with automatic rsync-rename optimization
- Initialize outside the main loop to ensure correct state handling for move/cleanup phases
- If file_manager restarts and PID is loaded from file and move operation is still active, enable to cleanup empty directories afterwards
- Clarify comment for INI job parameters
Replace complex INI serialization with simple separate .pid file:
- Avoids escaping issues (semicolons, hashes, newlines, etc.)
- No risk of INI file corruption
- Consistent with existing pattern (.active, .status, .error, .pid)
- Simpler code with fewer error sources
- Atomic writes (single number to file)