Configure specific File and Folder Permissions (#1108)

* Configure specific File and Folder Permissions, defaults for new items downloaded from OneDrive:
Directories: 700
Files: 600
This commit is contained in:
abraunegg 2020-10-30 08:00:26 +11:00 committed by GitHub
parent e81de988ee
commit cf4ee5017f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 122 additions and 5 deletions

2
config
View file

@ -40,3 +40,5 @@
# azure_ad_endpoint = ""
# azure_tenant_id = "common"
# sync_business_shared_folders = "false"
# sync_dir_permissions = "700"
# sync_file_permissions = "600"

View file

@ -300,6 +300,8 @@ The default configuration file is listed below:
# azure_ad_endpoint = ""
# azure_tenant_id = "common"
# sync_business_shared_folders = "false"
# sync_dir_permissions = "700"
# sync_file_permissions = "600"
```
@ -327,6 +329,26 @@ The issue here is around how the client stores the sync_dir path in the database
**Important Note:** If your `sync_dir` is pointing to a network mount point (a network share via NFS, Windows Network Share, Samba Network Share) these types of network mount points do not support 'inotify', thus tracking real-time changes via inotify of local files is not possible. Local filesystem changes will be replicated between the local filesystem and OneDrive based on the `monitor_interval` value. This is not something (inotify support for NFS, Samba) that this client can fix.
#### sync_dir directory and file permissions
The following are directory and file default permissions for any new directory or file that is created:
* Directories: 700 - This provides the following permissions: `drwx------`
* Files: 600 - This provides the following permissions: `-rw-------`
To change the default permissions, update the following 2 configuration options with the required permissions. Utilise [Unix Permissions Calculator](http://permissions-calculator.org/) to assist in determining the required permissions.
```text
# When changing a config option below, remove the '#' from the start of the line
# For explanations of all config options below see docs/USAGE.md or the man page.
#
...
# sync_business_shared_folders = "false"
sync_dir_permissions = "700"
sync_file_permissions = "600"
```
**Important:** Special permission bits (setuid, setgid, sticky bit) are not supported. Valid permission values are from `000` to `777` only.
#### skip_dir
Example:
```text

View file

@ -36,11 +36,17 @@ final class Config
private long[string] longValues;
// Compile time regex - this does not change
public auto configRegex = ctRegex!(`^(\w+)\s*=\s*"(.*)"\s*$`);
// Default directory permission mode
public long defaultDirectoryPermissionMode = 700;
public int configuredDirectoryPermissionMode;
// Default file permission mode
public long defaultFilePermissionMode = 600;
public int configuredFilePermissionMode;
this(string confdirOption)
{
// default configuration - entries in config file ~/.config/onedrive/config
// an entry here means it can be set via the config file if there is a coresponding read and set in update_from_args()
// an entry here means it can be set via the config file if there is a coresponding entry, read from config and set via update_from_args()
stringValues["sync_dir"] = defaultSyncDir;
stringValues["skip_file"] = defaultSkipFile;
stringValues["skip_dir"] = defaultSkipDir;
@ -106,6 +112,10 @@ final class Config
stringValues["azure_tenant_id"] = "common";
// Allow enable / disable of the syncing of OneDrive Business Shared Folders via configuration file
boolValues["sync_business_shared_folders"] = false;
// Configure the default folder permission attributes for newly created folders
longValues["sync_dir_permissions"] = defaultDirectoryPermissionMode;
// Configure the default file permission attributes for newly created file
longValues["sync_file_permissions"] = defaultFilePermissionMode;
// DEVELOPER OPTIONS
// display_memory = true | false
@ -181,7 +191,13 @@ final class Config
}
// Config directory options all determined
if (!exists(configDirName)) mkdirRecurse(configDirName);
if (!exists(configDirName)) {
// create the directory
mkdirRecurse(configDirName);
// Configure the applicable permissions for the folder
configDirName.setAttributes(returnRequiredDirectoryPermisions());
}
// configDirName has a trailing /
log.vlog("Using 'user' Config Dir: ", configDirName);
log.vlog("Using 'system' Config Dir: ", systemConfigDirName);
@ -611,6 +627,50 @@ final class Config
}
return true;
}
void configureRequiredDirectoryPermisions() {
// return the directory permission mode required
// - return octal!defaultDirectoryPermissionMode; ... cant be used .. which is odd
// Error: variable defaultDirectoryPermissionMode cannot be read at compile time
if (getValueLong("sync_dir_permissions") != defaultDirectoryPermissionMode) {
// return user configured permissions as octal integer
string valueToConvert = to!string(getValueLong("sync_dir_permissions"));
auto convertedValue = parse!long(valueToConvert, 8);
configuredDirectoryPermissionMode = to!int(convertedValue);
} else {
// return default as octal integer
string valueToConvert = to!string(defaultDirectoryPermissionMode);
auto convertedValue = parse!long(valueToConvert, 8);
configuredDirectoryPermissionMode = to!int(convertedValue);
}
}
void configureRequiredFilePermisions() {
// return the file permission mode required
// - return octal!defaultFilePermissionMode; ... cant be used .. which is odd
// Error: variable defaultFilePermissionMode cannot be read at compile time
if (getValueLong("sync_file_permissions") != defaultFilePermissionMode) {
// return user configured permissions as octal integer
string valueToConvert = to!string(getValueLong("sync_file_permissions"));
auto convertedValue = parse!long(valueToConvert, 8);
configuredFilePermissionMode = to!int(convertedValue);
} else {
// return default as octal integer
string valueToConvert = to!string(defaultFilePermissionMode);
auto convertedValue = parse!long(valueToConvert, 8);
configuredFilePermissionMode = to!int(convertedValue);
}
}
int returnRequiredDirectoryPermisions() {
// read the configuredDirectoryPermissionMode and return
return configuredDirectoryPermissionMode;
}
int returnRequiredFilePermisions() {
// read the configuredFilePermissionMode and return
return configuredFilePermissionMode;
}
}
void outputLongHelp(Option[] opt)

View file

@ -607,6 +607,23 @@ int main(string[] args)
itemDb = new ItemDatabase(cfg.databaseFilePathDryRun);
}
// What are the permission that have been set for the application?
// These are relevant for:
// - The ~/OneDrive parent folder or 'sync_dir' configured item
// - Any new folder created under ~/OneDrive or 'sync_dir'
// - Any new file created under ~/OneDrive or 'sync_dir'
// valid permissions are 000 -> 777 - anything else is invalid
if ((cfg.getValueLong("sync_dir_permissions") < 0) || (cfg.getValueLong("sync_file_permissions") < 0) || (cfg.getValueLong("sync_dir_permissions") > 777) || (cfg.getValueLong("sync_file_permissions") > 777)) {
log.error("ERROR: Invalid 'User|Group|Other' permissions set within config file. Please check.");
return EXIT_FAILURE;
} else {
// debug log output what permissions are being set to
log.vdebug("Configuring default new folder permissions as: ", cfg.getValueLong("sync_dir_permissions"));
cfg.configureRequiredDirectoryPermisions();
log.vdebug("Configuring default new file permissions as: ", cfg.getValueLong("sync_file_permissions"));
cfg.configureRequiredFilePermisions();
}
// configure the sync direcory based on syncDir config option
log.vlog("All operations will be performed in: ", syncDir);
if (!exists(syncDir)) {
@ -614,6 +631,8 @@ int main(string[] args)
try {
// Attempt to create the sync dir we have been configured with
mkdirRecurse(syncDir);
// Configure the applicable permissions for the folder
syncDir.setAttributes(cfg.returnRequiredDirectoryPermisions());
} catch (std.file.FileException e) {
// Creating the sync directory failed
log.error("ERROR: Unable to create local OneDrive syncDir - ", e.msg);
@ -621,6 +640,8 @@ int main(string[] args)
return EXIT_FAILURE;
}
}
// Change the working directory to the 'sync_dir' configured item
chdir(syncDir);
// Configure selective sync by parsing and getting a regex for skip_file config component
@ -858,8 +879,11 @@ int main(string[] args)
if (!exists(cfg.getValueString("single_directory"))) {
// The requested path to use with --single-directory does not exist locally within the configured 'sync_dir'
log.logAndNotify("WARNING: The requested path for --single-directory does not exist locally. Creating requested path within ", syncDir);
// Make the required path locally
mkdirRecurse(cfg.getValueString("single_directory"));
// Make the required --single-directory path locally
string singleDirectoryPath = cfg.getValueString("single_directory");
mkdirRecurse(singleDirectoryPath);
// Configure the applicable permissions for the folder
singleDirectoryPath.setAttributes(cfg.returnRequiredDirectoryPermisions());
}
}
// perform a --synchronize sync

View file

@ -495,7 +495,11 @@ final class OneDriveApi
scope(failure) {
if (exists(saveToPath)) remove(saveToPath);
}
mkdirRecurse(dirName(saveToPath));
// Create the directory
string newPath = dirName(saveToPath);
mkdirRecurse(newPath);
// Configure the applicable permissions for the folder
newPath.setAttributes(cfg.returnRequiredDirectoryPermisions());
const(char)[] url = driveByIdUrl ~ driveId ~ "/items/" ~ id ~ "/content?AVOverride=1";
download(url, saveToPath, fileSize);
}
@ -807,6 +811,8 @@ final class OneDriveApi
// close open file
file.close();
}
// Configure the applicable permissions for the file
filename.setAttributes(cfg.returnRequiredFilePermisions());
}
http.method = HTTP.Method.get;

View file

@ -2413,7 +2413,10 @@ final class SyncEngine
}
if (!dryRun) {
// Create the new directory
mkdirRecurse(path);
// Configure the applicable permissions for the folder
path.setAttributes(cfg.returnRequiredDirectoryPermisions());
} else {
// we dont create the directory, but we need to track that we 'faked it'
idsFaked ~= [item.driveId, item.id];