]> git.proxmox.com Git - ceph.git/blob - ceph/src/dokan/options.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / dokan / options.cc
1 /*
2 * Copyright (C) 2021 SUSE LINUX GmbH
3 *
4 * This is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License version 2.1, as published by the Free Software
7 * Foundation. See file COPYING.
8 *
9 */
10 #include <regex>
11
12 #include "include/compat.h"
13 #include "include/cephfs/libcephfs.h"
14
15 #include "ceph_dokan.h"
16 #include "utils.h"
17
18 #include "common/ceph_argparse.h"
19 #include "common/config.h"
20 #include "common/win32/wstring.h"
21
22 #include "global/global_init.h"
23
24 void print_usage() {
25 const char* usage_str = R"(
26 Usage: ceph-dokan.exe -l <mountpoint>
27 map -l <mountpoint> Map a CephFS filesystem
28 unmap -l <mountpoint> Unmap a CephFS filesystem
29
30 Map options:
31 -l [ --mountpoint ] arg mountpoint (path or drive letter) (e.g -l x)
32 -x [ --root-path ] arg mount a Ceph filesystem subdirectory
33
34 --operation-timeout arg Dokan operation timeout. Default: 120s.
35
36 --debug enable debug output
37 --dokan-stderr enable stderr Dokan logging
38
39 --read-only read-only mount
40 -o [ --win-mount-mgr] use the Windows mount manager
41 --current-session-only expose the mount only to the current user session
42 --removable use a removable drive
43 --win-vol-name arg The Windows volume name. Default: Ceph - <fs_name>.
44 --win-vol-serial arg The Windows volume serial number. Default: <fs_id>.
45 --max-path-len The value of the maximum path length. Default: 256.
46 --file-mode The access mode to be used when creating files.
47 --dir-mode The access mode to be used when creating directories.
48
49 Unmap options:
50 -l [ --mountpoint ] arg mountpoint (path or drive letter) (e.g -l x).
51 It has to be the exact same mountpoint that was
52 used when the mapping was created.
53
54 Common Options:
55 )";
56
57 std::cout << usage_str;
58 generic_client_usage();
59 }
60
61
62 int parse_args(
63 std::vector<const char*>& args,
64 std::ostream *err_msg,
65 Command *command, Config *cfg)
66 {
67 if (args.empty()) {
68 std::cout << "ceph-dokan: -h or --help for usage" << std::endl;
69 return -EINVAL;
70 }
71
72 std::string conf_file_list;
73 std::string cluster;
74 CephInitParameters iparams = ceph_argparse_early_args(
75 args, CEPH_ENTITY_TYPE_CLIENT, &cluster, &conf_file_list);
76
77 ConfigProxy config{false};
78 config->name = iparams.name;
79 config->cluster = cluster;
80 if (!conf_file_list.empty()) {
81 config.parse_config_files(conf_file_list.c_str(), nullptr, 0);
82 } else {
83 config.parse_config_files(nullptr, nullptr, 0);
84 }
85 config.parse_env(CEPH_ENTITY_TYPE_CLIENT);
86 config.parse_argv(args);
87
88 std::vector<const char*>::iterator i;
89 std::ostringstream err;
90 std::string mountpoint;
91 std::string win_vol_name;
92 std::string win_vol_serial;
93 std::string max_path_len;
94 std::string file_mode;
95 std::string dir_mode;
96
97 int thread_count;
98
99 for (i = args.begin(); i != args.end(); ) {
100 if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
101 *command = Command::Help;
102 return 0;
103 } else if (ceph_argparse_flag(args, i, "-v", "--version", (char*)NULL)) {
104 *command = Command::Version;
105 } else if (ceph_argparse_witharg(args, i, &mountpoint,
106 "--mountpoint", "-l", (char *)NULL)) {
107 cfg->mountpoint = to_wstring(mountpoint);
108 } else if (ceph_argparse_witharg(args, i, &cfg->root_path,
109 "--root-path", "-x", (char *)NULL)) {
110 } else if (ceph_argparse_flag(args, i, "--debug", (char *)NULL)) {
111 cfg->debug = true;
112 } else if (ceph_argparse_flag(args, i, "--dokan-stderr", (char *)NULL)) {
113 cfg->dokan_stderr = true;
114 } else if (ceph_argparse_flag(args, i, "--read-only", (char *)NULL)) {
115 cfg->readonly = true;
116 } else if (ceph_argparse_flag(args, i, "--removable", (char *)NULL)) {
117 cfg->removable = true;
118 } else if (ceph_argparse_flag(args, i, "--win-mount-mgr", "-o", (char *)NULL)) {
119 cfg->use_win_mount_mgr = true;
120 } else if (ceph_argparse_witharg(args, i, &win_vol_name,
121 "--win-vol-name", (char *)NULL)) {
122 cfg->win_vol_name = to_wstring(win_vol_name);
123 } else if (ceph_argparse_witharg(args, i, &win_vol_serial,
124 "--win-vol-serial", (char *)NULL)) {
125 cfg->win_vol_serial = std::stoul(win_vol_serial);
126 } else if (ceph_argparse_witharg(args, i, &max_path_len,
127 "--max-path-len", (char*)NULL)) {
128 unsigned long max_path_length = std::stoul(max_path_len);
129
130 if (max_path_length > 32767) {
131 *err_msg << "ceph-dokan: maximum path length should not "
132 << "exceed " << 32767;
133 return -EINVAL;
134 }
135
136 if (max_path_length < 256) {
137 *err_msg << "ceph-dokan: maximum path length should not "
138 << "have a value lower than 256";
139 return -EINVAL;
140 }
141
142 cfg->max_path_len = max_path_length;
143 } else if (ceph_argparse_witharg(args, i, &file_mode, "--file-mode", (char *)NULL)) {
144 mode_t mode = strtol(file_mode.c_str(), NULL, 8);
145 if (!std::regex_match(file_mode, std::regex("^[0-7]{3}$"))
146 || mode < 01 || mode > 0777) {
147 *err_msg << "ceph-dokan: invalid file access mode";
148 return -EINVAL;
149 }
150 cfg->file_mode = mode;
151 } else if (ceph_argparse_witharg(args, i, &dir_mode, "--dir-mode", (char *)NULL)) {
152 mode_t mode = strtol(dir_mode.c_str(), NULL, 8);
153 if (!std::regex_match(dir_mode, std::regex("^[0-7]{3}$"))
154 || mode < 01 || mode > 0777) {
155 *err_msg << "ceph-dokan: invalid directory access mode";
156 return -EINVAL;
157 }
158 cfg->dir_mode = mode;
159 } else if (ceph_argparse_flag(args, i, "--current-session-only", (char *)NULL)) {
160 cfg->current_session_only = true;
161 } else if (ceph_argparse_witharg(args, i, &thread_count,
162 err, "--thread-count", "-t", (char *)NULL)) {
163 std::cerr << "ceph-dokan: the thread count parameter is not supported by Dokany v2 "
164 << "and has been deprecated." << std::endl;
165 } else if (ceph_argparse_witharg(args, i, (int*)&cfg->operation_timeout,
166 err, "--operation-timeout", (char *)NULL)) {
167 if (!err.str().empty()) {
168 *err_msg << "ceph-dokan: " << err.str();
169 return -EINVAL;
170 }
171 if (cfg->operation_timeout < 0) {
172 *err_msg << "ceph-dokan: Invalid argument for operation-timeout";
173 return -EINVAL;
174 }
175 } else {
176 ++i;
177 }
178 }
179
180 if (cfg->use_win_mount_mgr && cfg->current_session_only) {
181 *err_msg << "ceph-dokan: The mount manager always mounts the drive "
182 << "for all user sessions.";
183 return -EINVAL;
184 }
185
186 Command cmd = Command::None;
187 if (args.begin() != args.end()) {
188 if (strcmp(*args.begin(), "help") == 0) {
189 cmd = Command::Help;
190 } else if (strcmp(*args.begin(), "version") == 0) {
191 cmd = Command::Version;
192 } else if (strcmp(*args.begin(), "map") == 0) {
193 cmd = Command::Map;
194 } else if (strcmp(*args.begin(), "unmap") == 0) {
195 cmd = Command::Unmap;
196 } else {
197 *err_msg << "ceph-dokan: unknown command: " << *args.begin();
198 return -EINVAL;
199 }
200 args.erase(args.begin());
201 }
202 if (cmd == Command::None) {
203 // The default command.
204 cmd = Command::Map;
205 }
206
207 switch (cmd) {
208 case Command::Map:
209 case Command::Unmap:
210 if (cfg->mountpoint.empty()) {
211 *err_msg << "ceph-dokan: missing mountpoint.";
212 return -EINVAL;
213 }
214 break;
215 default:
216 break;
217 }
218
219 if (args.begin() != args.end()) {
220 *err_msg << "ceph-dokan: unknown args: " << *args.begin();
221 return -EINVAL;
222 }
223
224 *command = cmd;
225 return 0;
226 }
227
228 int set_dokan_options(Config *cfg, PDOKAN_OPTIONS dokan_options) {
229 ZeroMemory(dokan_options, sizeof(DOKAN_OPTIONS));
230 dokan_options->Version = DOKAN_VERSION;
231 dokan_options->MountPoint = cfg->mountpoint.c_str();
232 dokan_options->Timeout = cfg->operation_timeout * 1000;
233
234 if (cfg->removable)
235 dokan_options->Options |= DOKAN_OPTION_REMOVABLE;
236 if (cfg->use_win_mount_mgr)
237 dokan_options->Options |= DOKAN_OPTION_MOUNT_MANAGER;
238 if (cfg->current_session_only)
239 dokan_options->Options |= DOKAN_OPTION_CURRENT_SESSION;
240 if (cfg->readonly)
241 dokan_options->Options |= DOKAN_OPTION_WRITE_PROTECT;
242 if (cfg->debug)
243 dokan_options->Options |= DOKAN_OPTION_DEBUG;
244 if (cfg->dokan_stderr)
245 dokan_options->Options |= DOKAN_OPTION_STDERR;
246
247 return 0;
248 }