Skip to content

Commit

Permalink
Add possibility to specify UNIX file permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
biggio authored and Ploppz committed May 13, 2022
1 parent cf713f7 commit 8df55c6
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 11 deletions.
2 changes: 2 additions & 0 deletions examples/rotate_by_date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ fn main() {
AppendTimestamp::with_format("%Y-%m-%d", FileLimit::MaxFiles(7), DateFrom::DateYesterday),
ContentLimit::Time(TimeFrequency::Daily),
Compression::None,
#[cfg(unix)]
None,
);

// Write a bunch of lines
Expand Down
52 changes: 41 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
//! log_path.clone(),
//! AppendCount::new(2),
//! ContentLimit::Lines(3),
//! Compression::None
//! Compression::None,
//! #[cfg(unix)]
//! None,
//! );
//!
//! // Write a bunch of lines
Expand Down Expand Up @@ -59,7 +61,9 @@
//! "target/my-log-directory-bytes/my-log-file",
//! AppendCount::new(2),
//! ContentLimit::Bytes(5),
//! Compression::None
//! Compression::None,
//! #[cfg(unix)]
//! None,
//! );
//!
//! writeln!(log, "Test file");
Expand Down Expand Up @@ -94,7 +98,9 @@
//! log_path.clone(),
//! AppendCount::new(3),
//! ContentLimit::Bytes(1),
//! Compression::None
//! Compression::None,
//! #[cfg(unix)]
//! None,
//! );
//!
//! write!(log, "A");
Expand Down Expand Up @@ -151,7 +157,9 @@
//! log_path.clone(),
//! AppendTimestamp::default(FileLimit::MaxFiles(2)),
//! ContentLimit::Bytes(1),
//! Compression::None
//! Compression::None,
//! #[cfg(unix)]
//! None,
//! );
//!
//! write!(log, "A");
Expand Down Expand Up @@ -196,6 +204,8 @@
//! AppendTimestamp::default(FileLimit::MaxFiles(4)),
//! ContentLimit::Bytes(1),
//! Compression::OnRotate(2),
//! #[cfg(unix)]
//! None,
//! );
//!
//! for i in 0..6 {
Expand Down Expand Up @@ -293,6 +303,9 @@ use std::{
};
use suffix::*;

#[cfg(unix)]
use std::os::unix::fs::OpenOptionsExt;

pub mod compression;
pub mod suffix;
#[cfg(test)]
Expand Down Expand Up @@ -377,6 +390,8 @@ pub struct FileRotate<S: SuffixScheme> {
suffix_scheme: S,
/// The bool is whether or not there's a .gz suffix to the filename
suffixes: BTreeSet<SuffixInfo<S::Repr>>,
#[cfg(unix)]
mode: Option<u32>,
}

impl<S: SuffixScheme> FileRotate<S> {
Expand All @@ -395,6 +410,7 @@ impl<S: SuffixScheme> FileRotate<S> {
suffix_scheme: S,
content_limit: ContentLimit,
compression: Compression,
#[cfg(unix)] mode: Option<u32>,
) -> Self {
match content_limit {
ContentLimit::Bytes(bytes) => {
Expand All @@ -421,9 +437,12 @@ impl<S: SuffixScheme> FileRotate<S> {
compression,
suffixes: BTreeSet::new(),
suffix_scheme,
#[cfg(unix)]
mode,
};
s.ensure_log_directory_exists();
s.scan_suffixes();

s
}
fn ensure_log_directory_exists(&mut self) {
Expand All @@ -434,12 +453,8 @@ impl<S: SuffixScheme> FileRotate<S> {
}
if !self.basepath.exists() || self.file.is_none() {
// Open or create the file
self.file = OpenOptions::new()
.read(true)
.create(true)
.append(true)
.open(&self.basepath)
.ok();
self.open_file();

match self.file {
None => self.count = 0,
Some(ref mut file) => {
Expand All @@ -463,6 +478,20 @@ impl<S: SuffixScheme> FileRotate<S> {
}
}
}

fn open_file(&mut self) {
let mut open_options = OpenOptions::new();

open_options.read(true).create(true).append(true);

if let Some(mode) = self.mode {
#[cfg(unix)]
open_options.mode(mode);
}

self.file = open_options.open(&self.basepath).ok();
}

fn scan_suffixes(&mut self) {
self.suffixes = self.suffix_scheme.scan_suffixes(&self.basepath);
}
Expand Down Expand Up @@ -544,7 +573,8 @@ impl<S: SuffixScheme> FileRotate<S> {
let new_suffix_info = self.move_file_with_suffix(None)?;
self.suffixes.insert(new_suffix_info);

self.file = Some(File::create(&self.basepath)?);
self.open_file();

self.count = 0;

self.handle_old_files()?;
Expand Down
61 changes: 61 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use super::{suffix::*, *};
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use tempdir::TempDir;

// Just useful to debug why test doesn't succeed
Expand Down Expand Up @@ -26,6 +28,8 @@ fn timestamp_max_files_rotation() {
AppendTimestamp::default(FileLimit::MaxFiles(4)),
ContentLimit::Lines(2),
Compression::None,
#[cfg(unix)]
None,
);

// Write 9 lines
Expand Down Expand Up @@ -83,6 +87,8 @@ fn timestamp_max_age_deletion() {
AppendTimestamp::default(FileLimit::Age(chrono::Duration::weeks(1))),
ContentLimit::Lines(1),
Compression::None,
#[cfg(unix)]
None,
);
writeln!(log, "trigger\nat\nleast\none\nrotation").unwrap();

Expand All @@ -108,6 +114,8 @@ fn count_max_files_rotation() {
AppendCount::new(4),
ContentLimit::Lines(2),
Compression::None,
#[cfg(unix)]
None,
);

// Write 9 lines
Expand Down Expand Up @@ -148,6 +156,8 @@ fn rotate_to_deleted_directory() {
AppendCount::new(4),
ContentLimit::Lines(1),
Compression::None,
#[cfg(unix)]
None,
);

write!(log, "a\nb\n").unwrap();
Expand Down Expand Up @@ -177,6 +187,8 @@ fn write_complete_record_until_bytes_surpassed() {
AppendTimestamp::default(FileLimit::MaxFiles(100)),
ContentLimit::BytesSurpassed(1),
Compression::None,
#[cfg(unix)]
None,
);

write!(log, "0123456789").unwrap();
Expand All @@ -201,6 +213,8 @@ fn compression_on_rotation() {
AppendCount::new(3),
ContentLimit::Lines(1),
Compression::OnRotate(1), // Keep one file uncompressed
#[cfg(unix)]
None,
);

writeln!(log, "A").unwrap();
Expand Down Expand Up @@ -244,6 +258,8 @@ fn no_truncate() {
AppendCount::new(3),
ContentLimit::Lines(10000),
Compression::None,
#[cfg(unix)]
None,
)
};
writeln!(file_rotate(), "A").unwrap();
Expand All @@ -269,6 +285,8 @@ fn byte_count_recalculation() {
AppendCount::new(3),
ContentLimit::Bytes(2),
Compression::None,
#[cfg(unix)]
None,
);

write!(file_rotate, "bc").unwrap();
Expand Down Expand Up @@ -296,6 +314,8 @@ fn line_count_recalculation() {
AppendCount::new(3),
ContentLimit::Lines(2),
Compression::None,
#[cfg(unix)]
None,
);

// A single line existed before the new logger ('a')
Expand All @@ -316,6 +336,41 @@ fn line_count_recalculation() {
assert_eq!(lines.next().unwrap().unwrap(), "c".to_string());
}

#[cfg(unix)]
#[test]
fn unix_file_permissions() {
let permissions = &[0o600, 0o644];

for permission in permissions {
let tmp_dir = TempDir::new("file-rotate-test").unwrap();
let parent = tmp_dir.path();
let log_path = parent.join("log");

let mut file_rotate = FileRotate::new(
&*log_path.to_string_lossy(),
AppendCount::new(3),
ContentLimit::Lines(2),
Compression::None,
Some(*permission),
);

// Trigger a rotation by writing three lines
writeln!(file_rotate, "a").unwrap();
writeln!(file_rotate, "b").unwrap();
writeln!(file_rotate, "c").unwrap();

assert_eq!(file_rotate.log_paths().len(), 1);

// The file created at initialization time should have the right permissions ...
let metadata = fs::metadata(&log_path).unwrap();
assert_eq!(metadata.permissions().mode() & 0o777, *permission);

// ... and also the one generated through a rotation
let metadata = fs::metadata(&file_rotate.log_paths()[0]).unwrap();
assert_eq!(metadata.permissions().mode() & 0o777, *permission);
}
}

#[quickcheck_macros::quickcheck]
fn arbitrary_lines(count: usize) {
let tmp_dir = TempDir::new("file-rotate-test").unwrap();
Expand All @@ -328,6 +383,8 @@ fn arbitrary_lines(count: usize) {
AppendTimestamp::default(FileLimit::MaxFiles(100)),
ContentLimit::Lines(count),
Compression::None,
#[cfg(unix)]
None,
);

for _ in 0..count - 1 {
Expand All @@ -352,6 +409,8 @@ fn arbitrary_bytes(count: usize) {
AppendTimestamp::default(FileLimit::MaxFiles(100)),
ContentLimit::Bytes(count),
Compression::None,
#[cfg(unix)]
None,
);

for _ in 0..count {
Expand Down Expand Up @@ -445,6 +504,8 @@ fn test_time_frequency(
AppendTimestamp::with_format("%Y-%m-%d_%H-%M-%S", FileLimit::MaxFiles(7), date_from),
ContentLimit::Time(frequency),
Compression::None,
#[cfg(unix)]
None,
);

writeln!(log, "a").unwrap();
Expand Down

0 comments on commit 8df55c6

Please sign in to comment.