1 /*
2    Copyright 2017 Skytechnology sp. z o.o..
3 
4    This file is part of LizardFS.
5 
6    LizardFS is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, version 3.
9 
10    LizardFS is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with LizardFS  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "common/platform.h"
20 
21 #include <cassert>
22 #include <system_error>
23 
24 #include "lizardfs_c_api.h"
25 #include "common/lizardfs_error_codes.h"
26 #include "common/md5.h"
27 #include "common/small_vector.h"
28 #include "mount/client/iovec_traits.h"
29 
30 #include "client.h"
31 
32 using namespace lizardfs;
33 
liz_set_default_init_params(struct liz_init_params * params,const char * host,const char * port,const char * mountpoint)34 void liz_set_default_init_params(struct liz_init_params *params,
35 		const char *host, const char *port, const char *mountpoint) {
36 	assert(params != nullptr);
37 	params->bind_host = nullptr;
38 	params->host = host;
39 	params->port = port;
40 	params->meta = false;
41 	params->mountpoint = mountpoint;
42 	params->subfolder = LizardClient::FsInitParams::kDefaultSubfolder;
43 	params->password = nullptr;
44 	params->md5_pass = nullptr;
45 	params->do_not_remember_password = LizardClient::FsInitParams::kDefaultDoNotRememberPassword;
46 	params->delayed_init = LizardClient::FsInitParams::kDefaultDelayedInit;
47 	params->report_reserved_period = LizardClient::FsInitParams::kDefaultReportReservedPeriod;
48 
49 	params->io_retries = LizardClient::FsInitParams::kDefaultIoRetries;
50 	params->chunkserver_round_time_ms = LizardClient::FsInitParams::kDefaultRoundTime;
51 	params->chunkserver_connect_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverConnectTo;
52 	params->chunkserver_wave_read_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverWaveReadTo;
53 	params->total_read_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverTotalReadTo;
54 	params->cache_expiration_time_ms = LizardClient::FsInitParams::kDefaultCacheExpirationTime;
55 	params->readahead_max_window_size_kB = LizardClient::FsInitParams::kDefaultReadaheadMaxWindowSize;
56 	params->prefetch_xor_stripes = LizardClient::FsInitParams::kDefaultPrefetchXorStripes;
57 	params->bandwidth_overuse = LizardClient::FsInitParams::kDefaultBandwidthOveruse;
58 
59 	params->write_cache_size = LizardClient::FsInitParams::kDefaultWriteCacheSize;
60 	params->write_workers = LizardClient::FsInitParams::kDefaultWriteWorkers;
61 	params->write_window_size = LizardClient::FsInitParams::kDefaultWriteWindowSize;
62 	params->chunkserver_write_timeout_ms = LizardClient::FsInitParams::kDefaultChunkserverWriteTo;
63 	params->cache_per_inode_percentage = LizardClient::FsInitParams::kDefaultCachePerInodePercentage;
64 	params->symlink_cache_timeout_s = LizardClient::FsInitParams::kDefaultSymlinkCacheTimeout;
65 
66 	params->debug_mode = LizardClient::FsInitParams::kDefaultDebugMode;
67 	params->keep_cache = LizardClient::FsInitParams::kDefaultKeepCache;
68 	params->direntry_cache_timeout = LizardClient::FsInitParams::kDefaultDirentryCacheTimeout;
69 	params->direntry_cache_size = LizardClient::FsInitParams::kDefaultDirentryCacheSize;
70 	params->entry_cache_timeout = LizardClient::FsInitParams::kDefaultEntryCacheTimeout;
71 	params->attr_cache_timeout = LizardClient::FsInitParams::kDefaultAttrCacheTimeout;
72 	params->mkdir_copy_sgid = LizardClient::FsInitParams::kDefaultMkdirCopySgid;
73 	params->sugid_clear_mode = (liz_sugid_clear_mode)LizardClient::FsInitParams::kDefaultSugidClearMode;
74 	params->use_rw_lock = LizardClient::FsInitParams::kDefaultUseRwLock;
75 	params->acl_cache_timeout = LizardClient::FsInitParams::kDefaultAclCacheTimeout;
76 	params->acl_cache_size = LizardClient::FsInitParams::kDefaultAclCacheSize;
77 
78 	params->verbose = LizardClient::FsInitParams::kDefaultVerbose;
79 
80 	params->io_limits_config_file = nullptr;
81 
82 	// statically assert that all SugidClearMode value are covered and consistent
83 	static_assert(sizeof(liz_sugid_clear_mode) >= sizeof(SugidClearMode), "");
84 	for (int dummy = LIZARDFS_SUGID_CLEAR_MODE_NEVER; dummy < LIZARDFS_SUGID_CLEAR_MODE_END_; ++dummy) {
85 		switch (SugidClearMode(dummy)) { // exhaustive match check thanks to 'enum class'
86 			#define STATIC_ASSERT_SUGID_CLEAR_MODE(KNAME,CENUM) \
87 					case SugidClearMode::KNAME: \
88 						static_assert((liz_sugid_clear_mode)SugidClearMode::KNAME  == CENUM, \
89 							"liz_sugid_clear_mode incompatible with SugidClearMode");
90 				STATIC_ASSERT_SUGID_CLEAR_MODE(kNever, LIZARDFS_SUGID_CLEAR_MODE_NEVER);
91 				STATIC_ASSERT_SUGID_CLEAR_MODE(kAlways, LIZARDFS_SUGID_CLEAR_MODE_ALWAYS);
92 				STATIC_ASSERT_SUGID_CLEAR_MODE(kOsx, LIZARDFS_SUGID_CLEAR_MODE_OSX);
93 				STATIC_ASSERT_SUGID_CLEAR_MODE(kBsd, LIZARDFS_SUGID_CLEAR_MODE_BSD);
94 				STATIC_ASSERT_SUGID_CLEAR_MODE(kExt, LIZARDFS_SUGID_CLEAR_MODE_EXT);
95 				STATIC_ASSERT_SUGID_CLEAR_MODE(kXfs, LIZARDFS_SUGID_CLEAR_MODE_XFS);
96 			#undef STATIC_ASSERT_SUGID_CLEAR_MODE
97 		}
98 	}
99 }
100 
101 static thread_local liz_err_t gLastErrorCode(LIZARDFS_STATUS_OK);
102 
to_entry(const Client::EntryParam & param,liz_entry * entry)103 static void to_entry(const Client::EntryParam &param, liz_entry *entry) {
104 	assert(entry);
105 	entry->ino = param.ino;
106 	entry->generation = param.generation;
107 	entry->attr = param.attr;
108 	entry->attr_timeout = param.attr_timeout;
109 	entry->entry_timeout = param.entry_timeout;
110 }
111 
to_attr_reply(const Client::AttrReply & attr_reply,liz_attr_reply * reply)112 static void to_attr_reply(const Client::AttrReply &attr_reply, liz_attr_reply *reply) {
113 	assert(reply);
114 	reply->attr = attr_reply.attr;
115 	reply->attr_timeout = attr_reply.attrTimeout;
116 }
117 
to_stat(const Client::Stats & stats,liz_stat_t * buf)118 static void to_stat(const Client::Stats &stats, liz_stat_t *buf) {
119 	assert(buf);
120 	buf->total_space = stats.total_space;
121 	buf->avail_space = stats.avail_space;
122 	buf->trash_space = stats.trash_space;
123 	buf->reserved_space = stats.reserved_space;
124 	buf->inodes = stats.inodes;
125 }
126 
liz_last_err()127 liz_err_t liz_last_err() {
128 	return gLastErrorCode;
129 }
130 
liz_error_conv(liz_err_t lizardfs_error_code)131 liz_err_t liz_error_conv(liz_err_t lizardfs_error_code) {
132 	if (lizardfs_error_code < 0) {
133 		return EINVAL;
134 	} else {
135 		return lizardfs_error_conv(lizardfs_error_code);
136 	}
137 }
138 
liz_error_string(liz_err_t lizardfs_error_code)139 const char *liz_error_string(liz_err_t lizardfs_error_code) {
140 	return lizardfs_error_string(lizardfs_error_code);
141 }
142 
liz_create_context()143 liz_context_t *liz_create_context() {
144 	try {
145 		Client::Context *ret = new Client::Context(getuid(), getgid(), getpid(), 0);
146 		return (liz_context_t *)ret;
147 	} catch (...) {
148 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
149 		return nullptr;
150 	}
151 }
152 
liz_create_user_context(uid_t uid,gid_t gid,pid_t pid,mode_t umask)153 liz_context_t *liz_create_user_context(uid_t uid, gid_t gid, pid_t pid, mode_t umask) {
154 	try {
155 		Client::Context *ret = new Client::Context(uid, gid, pid, umask);
156 		return (liz_context_t *)ret;
157 	} catch (...) {
158 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
159 		return nullptr;
160 	}
161 }
162 
liz_destroy_context(liz_context_t * ctx)163 void liz_destroy_context(liz_context_t *ctx) {
164 	Client::Context *client_ctx = (Client::Context *)ctx;
165 	delete client_ctx;
166 }
167 
liz_set_lock_owner(liz_fileinfo_t * fileinfo,uint64_t lock_owner)168 void liz_set_lock_owner(liz_fileinfo_t *fileinfo, uint64_t lock_owner) {
169 	Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
170 	fi->lock_owner = lock_owner;
171 }
172 
liz_init(const char * host,const char * port,const char * mountpoint)173 liz_t *liz_init(const char *host, const char *port, const char *mountpoint) {
174 	try {
175 		Client *ret = new Client(host, port, mountpoint);
176 		gLastErrorCode = LIZARDFS_STATUS_OK;
177 		return (liz_t *)ret;
178 	} catch (...) {
179 		gLastErrorCode = LIZARDFS_ERROR_CANTCONNECT;
180 		return nullptr;
181 	}
182 }
183 
liz_init_with_params(struct liz_init_params * params)184 liz_t *liz_init_with_params(struct liz_init_params *params) {
185 	assert(params != nullptr);
186 	assert(params->host != nullptr);
187 	assert(params->port != nullptr);
188 	assert(params->mountpoint != nullptr);
189 	assert(params->sugid_clear_mode >= 0);
190 	assert(params->sugid_clear_mode < LIZARDFS_SUGID_CLEAR_MODE_END_);
191 
192 	Client::FsInitParams init_params(params->bind_host != nullptr ? params->bind_host : "",
193 			params->host, params->port, params->mountpoint);
194 
195 	init_params.meta = params->meta;
196 	if (params->subfolder != nullptr) {
197 		init_params.subfolder = params->subfolder;
198 	}
199 	if (params->password != nullptr) {
200 		md5ctx md5_ctx;
201 		init_params.password_digest.resize(16);
202 		md5_init(&md5_ctx);
203 		md5_update(&md5_ctx,(uint8_t *)(params->password), strlen(params->password));
204 		md5_final(init_params.password_digest.data(), &md5_ctx);
205 	} else if (params->md5_pass) {
206 		int ret = md5_parse(init_params.password_digest, params->md5_pass);
207 		if (ret < 0) {
208 			gLastErrorCode = LIZARDFS_ERROR_EINVAL;
209 			return nullptr;
210 		}
211 	}
212 
213 	#define COPY_PARAM(PARAM) do { \
214 		static_assert(std::is_same<decltype(init_params.PARAM), decltype(params->PARAM)>::value, \
215 			"liz_init_params member incompatible with FsInitParams"); \
216 		init_params.PARAM = params->PARAM; \
217 	} while (0)
218 		COPY_PARAM(do_not_remember_password);
219 		COPY_PARAM(delayed_init);
220 		COPY_PARAM(report_reserved_period);
221 		COPY_PARAM(io_retries);
222 		COPY_PARAM(chunkserver_round_time_ms);
223 		COPY_PARAM(chunkserver_connect_timeout_ms);
224 		COPY_PARAM(chunkserver_wave_read_timeout_ms);
225 		COPY_PARAM(total_read_timeout_ms);
226 		COPY_PARAM(cache_expiration_time_ms);
227 		COPY_PARAM(readahead_max_window_size_kB);
228 		COPY_PARAM(prefetch_xor_stripes);
229 		COPY_PARAM(bandwidth_overuse);
230 		COPY_PARAM(write_cache_size);
231 		COPY_PARAM(write_workers);
232 		COPY_PARAM(write_window_size);
233 		COPY_PARAM(chunkserver_write_timeout_ms);
234 		COPY_PARAM(cache_per_inode_percentage);
235 		COPY_PARAM(symlink_cache_timeout_s);
236 		COPY_PARAM(debug_mode);
237 		COPY_PARAM(keep_cache);
238 		COPY_PARAM(direntry_cache_timeout);
239 		COPY_PARAM(direntry_cache_size);
240 		COPY_PARAM(entry_cache_timeout);
241 		COPY_PARAM(attr_cache_timeout);
242 		COPY_PARAM(mkdir_copy_sgid);
243 		init_params.sugid_clear_mode = (SugidClearMode)params->sugid_clear_mode;
244 		COPY_PARAM(use_rw_lock);
245 		COPY_PARAM(acl_cache_timeout);
246 		COPY_PARAM(acl_cache_size);
247 		COPY_PARAM(verbose);
248 	#undef COPY_PARAM
249 
250 	if (params->io_limits_config_file != nullptr) {
251 		init_params.io_limits_config_file = params->io_limits_config_file;
252 	}
253 
254 	try {
255 		Client *ret = new Client(init_params);
256 		gLastErrorCode = LIZARDFS_STATUS_OK;
257 		return (liz_t *)ret;
258 	} catch (...) {
259 		gLastErrorCode = LIZARDFS_ERROR_CANTCONNECT;
260 		return nullptr;
261 	}
262 }
263 
liz_update_groups(liz_t * instance,liz_context_t * ctx,gid_t * gids,int gid_num)264 int liz_update_groups(liz_t *instance, liz_context_t *ctx, gid_t *gids, int gid_num) {
265 	Client &client = *(Client *)instance;
266 	Client::Context &client_ctx = *(Client::Context *)ctx;
267 	Client::Context::GroupsContainer gids_backup(std::move(client_ctx.gids));
268 	try {
269 		client_ctx.gids.assign(gids, gids + gid_num);
270 		std::error_code ec;
271 		client.updateGroups(client_ctx, ec);
272 		gLastErrorCode = ec.value();
273 		if (ec) {
274 			client_ctx.gids = std::move(gids_backup);
275 			return -1;
276 		}
277 	} catch (...) {
278 		client_ctx.gids = std::move(gids_backup);
279 		gLastErrorCode = LIZARDFS_ERROR_GROUPNOTREGISTERED;
280 		return -1;
281 	}
282 	return 0;
283 }
284 
liz_lookup(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,liz_entry * entry)285 int liz_lookup(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
286 	       liz_entry *entry) {
287 	Client &client = *(Client *)instance;
288 	Client::Context &context = *(Client::Context *)ctx;
289 	Client::EntryParam entry_param;
290 	std::error_code ec;
291 	client.lookup(context, parent, path, entry_param, ec);
292 	gLastErrorCode = ec.value();
293 	if (ec) {
294 		return -1;
295 	} else {
296 		to_entry(entry_param, entry);
297 	}
298 	return 0;
299 }
300 
liz_mknod(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,mode_t mode,dev_t rdev,liz_entry * entry)301 int liz_mknod(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
302 	      mode_t mode, dev_t rdev, liz_entry *entry) {
303 	Client &client = *(Client *)instance;
304 	Client::Context &context = *(Client::Context *)ctx;
305 	Client::EntryParam entry_param;
306 	std::error_code ec;
307 	client.mknod(context, parent, path, mode, rdev, entry_param, ec);
308 	gLastErrorCode = ec.value();
309 	if (ec) {
310 		return -1;
311 	} else {
312 		to_entry(entry_param, entry);
313 	}
314 	return 0;
315 }
316 
liz_link(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_inode_t parent,const char * name,struct liz_entry * entry)317 int liz_link(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, liz_inode_t parent,
318 	      const char *name, struct liz_entry *entry) {
319 	Client &client = *(Client *)instance;
320 	Client::Context &context = *(Client::Context *)ctx;
321 	Client::EntryParam entry_param;
322 	std::error_code ec;
323 	client.link(context, inode, parent, name, entry_param, ec);
324 	gLastErrorCode = ec.value();
325 	if (ec) {
326 		return -1;
327 	}
328 	to_entry(entry_param, entry);
329 	return 0;
330 }
331 
liz_symlink(liz_t * instance,liz_context_t * ctx,const char * link,liz_inode_t parent,const char * name,struct liz_entry * entry)332 int liz_symlink(liz_t *instance, liz_context_t *ctx, const char *link, liz_inode_t parent,
333 	      const char *name, struct liz_entry *entry) {
334 	Client &client = *(Client *)instance;
335 	Client::Context &context = *(Client::Context *)ctx;
336 	Client::EntryParam entry_param;
337 	std::error_code ec;
338 	client.symlink(context, link, parent, name, entry_param, ec);
339 	gLastErrorCode = ec.value();
340 	if (ec) {
341 		return -1;
342 	}
343 	to_entry(entry_param, entry);
344 	return 0;
345 }
346 
liz_open(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,int flags)347 liz_fileinfo *liz_open(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, int flags) {
348 	Client &client = *(Client *)instance;
349 	Client::Context &context = *(Client::Context *)ctx;
350 	std::error_code ec;
351 	liz_fileinfo *fi = (liz_fileinfo *)client.open(context, inode, flags, ec);
352 	gLastErrorCode = ec.value();
353 	return fi;
354 }
355 
liz_read(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,char * buffer)356 ssize_t liz_read(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
357 	         size_t size, char *buffer) {
358 	Client &client = *(Client *)instance;
359 	Client::Context &context = *(Client::Context *)ctx;
360 	std::error_code ec;
361 	auto ret = client.read(context, (Client::FileInfo *)fileinfo, offset, size, ec);
362 	if (ec) {
363 		gLastErrorCode = ec.value();
364 		return -1;
365 	}
366 	return ret.copyToBuffer((uint8_t *)buffer, offset, size);
367 }
368 
liz_readv(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,const struct iovec * iov,int iovcnt)369 ssize_t liz_readv(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
370 	          size_t size, const struct iovec *iov, int iovcnt) {
371 	Client &client = *(Client *)instance;
372 	Client::Context &context = *(Client::Context *)ctx;
373 	std::error_code ec;
374 	auto ret = client.read(context, (Client::FileInfo *)fileinfo, offset, size, ec);
375 	if (ec) {
376 		gLastErrorCode = ec.value();
377 		return -1;
378 	}
379 	small_vector<struct iovec, 8> reply;
380 	ret.toIoVec(reply, offset, size);
381 	return copyIoVec(iov, iovcnt, reply.data(), reply.size());
382 }
383 
liz_write(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo,off_t offset,size_t size,const char * buffer)384 ssize_t liz_write(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo, off_t offset,
385 	          size_t size, const char *buffer){
386 	Client &client = *(Client *)instance;
387 	Client::Context &context = *(Client::Context *)ctx;
388 	std::error_code ec;
389 	std::size_t write_ret = client.write(context, (Client::FileInfo *)fileinfo, offset, size,
390 	                                     buffer, ec);
391 	gLastErrorCode = ec.value();
392 	return ec ? -1 : write_ret;
393 }
394 
liz_release(liz_t * instance,liz_fileinfo * fileinfo)395 int liz_release(liz_t *instance, liz_fileinfo *fileinfo) {
396 	Client &client = *(Client *)instance;
397 	std::error_code ec;
398 	client.release((Client::FileInfo *)fileinfo, ec);
399 	gLastErrorCode = ec.value();
400 	return ec ? -1 : 0;
401 }
402 
liz_flush(liz_t * instance,liz_context_t * ctx,liz_fileinfo * fileinfo)403 int liz_flush(liz_t *instance, liz_context_t *ctx, liz_fileinfo *fileinfo) {
404 	Client &client = *(Client *)instance;
405 	Client::Context &context = *(Client::Context *)ctx;
406 	std::error_code ec;
407 	client.flush(context, (Client::FileInfo *)fileinfo, ec);
408 	gLastErrorCode = ec.value();
409 	return ec ? -1 : 0;
410 }
411 
liz_getattr(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_attr_reply * reply)412 int liz_getattr(liz_t *instance, liz_context_t *ctx, liz_inode_t inode,
413 	        liz_attr_reply *reply) {
414 	Client &client = *(Client *)instance;
415 	Client::Context &context = *(Client::Context *)ctx;
416 	Client::AttrReply r;
417 	std::error_code ec;
418 	client.getattr(context, inode, r, ec);
419 	gLastErrorCode = ec.value();
420 	if (ec) {
421 		return -1;
422 	} else if (reply) {
423 		to_attr_reply(r, reply);
424 	}
425 	return 0;
426 }
427 
liz_destroy(liz_t * instance)428 void liz_destroy(liz_t *instance) {
429 	Client *client = (Client *)instance;
430 	delete client;
431 }
432 
liz_opendir(liz_t * instance,liz_context_t * ctx,liz_inode_t inode)433 struct liz_fileinfo *liz_opendir(liz_t *instance, liz_context_t *ctx, liz_inode_t inode) {
434 	Client &client = *(Client *)instance;
435 	Client::Context &context = *(Client::Context *)ctx;
436 	std::error_code ec;
437 	liz_fileinfo *fi = (liz_fileinfo *)client.opendir(context, inode, ec);
438 	gLastErrorCode = ec.value();
439 	return fi;
440 }
441 
liz_readdir(liz_t * instance,liz_context_t * ctx,struct liz_fileinfo * fileinfo,off_t offset,size_t max_entries,struct liz_direntry * buf,size_t * num_entries)442 int liz_readdir(liz_t *instance, liz_context_t *ctx, struct liz_fileinfo *fileinfo,
443 		off_t offset, size_t max_entries, struct liz_direntry *buf, size_t *num_entries) {
444 	Client &client = *(Client *)instance;
445 	Client::Context &context = *(Client::Context *)ctx;
446 	std::error_code ec;
447 
448 	if (max_entries > 0) {
449 		buf->name = NULL;
450 	} else {
451 		gLastErrorCode = LIZARDFS_ERROR_EINVAL;
452 		return -1;
453 	}
454 
455 	Client::ReadDirReply reply = client.readdir(context, (Client::FileInfo *)fileinfo,
456 	                                            offset, max_entries, ec);
457 	*num_entries = 0;
458 	gLastErrorCode = ec.value();
459 	if (ec) {
460 		return -1;
461 	}
462 	if (reply.empty()) {
463 		return 0;
464 	}
465 
466 	size_t total_name_size = 0;
467 	for (const auto &dir_entry : reply) {
468 		total_name_size += dir_entry.name.size() + 1;
469 	}
470 
471 	char *p_namebuf;
472 	try {
473 		p_namebuf = new char[total_name_size];
474 	} catch (...) {
475 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
476 		return -1;
477 	}
478 
479 	for (const auto &dir_entry : reply) {
480 		buf->name = p_namebuf;
481 		buf->attr = dir_entry.attr;
482 		buf->next_entry_offset = dir_entry.nextEntryOffset;
483 		buf++;
484 
485 		auto s = dir_entry.name.size();
486 		dir_entry.name.copy(p_namebuf, s);
487 		p_namebuf[s] = '\0';
488 		p_namebuf += s + 1;
489 	}
490 
491 	*num_entries = reply.size();
492 	return 0;
493 }
494 
liz_destroy_direntry(struct liz_direntry * buf,size_t)495 void liz_destroy_direntry(struct liz_direntry *buf, size_t /*num_entries*/) {
496 	if (buf->name) {
497 		delete[] buf->name;
498 	}
499 }
500 
liz_releasedir(liz_t * instance,struct liz_fileinfo * fileinfo)501 int liz_releasedir(liz_t *instance, struct liz_fileinfo *fileinfo) {
502 	Client &client = *(Client *)instance;
503 	std::error_code ec;
504 	client.releasedir((Client::FileInfo *)fileinfo, ec);
505 	gLastErrorCode = ec.value();
506 	return ec ? -1 : 0;
507 }
508 
convert_named_inodes(liz_namedinode_entry * out_entries,uint32_t * num_entries,const std::vector<NamedInodeEntry> & input)509 static int convert_named_inodes(liz_namedinode_entry *out_entries, uint32_t *num_entries,
510 	                     const std::vector<NamedInodeEntry> &input) {
511 	*num_entries = 0;
512 	if (input.empty()) {
513 		return 0;
514 	}
515 
516 	size_t total_name_size = 0;
517 	for (const auto &ni : input) {
518 		total_name_size += ni.name.size() + 1;
519 	}
520 
521 	char *p_namebuf;
522 	try {
523 		p_namebuf = new char[total_name_size];
524 	} catch (...) {
525 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
526 		return -1;
527 	}
528 
529 	for (const auto &ni : input) {
530 		out_entries->ino = ni.inode;
531 		out_entries->name = p_namebuf;
532 		out_entries++;
533 
534 		auto s = ni.name.size();
535 		ni.name.copy(p_namebuf, s);
536 		p_namebuf[s] = '\0';
537 		p_namebuf += s + 1;
538 	}
539 
540 	*num_entries = input.size();
541 	return 0;
542 }
543 
liz_readreserved(liz_t * instance,liz_context_t * ctx,uint32_t offset,uint32_t max_entries,struct liz_namedinode_entry * out_entries,uint32_t * num_entries)544 int liz_readreserved(liz_t *instance, liz_context_t *ctx, uint32_t offset, uint32_t max_entries,
545 	             struct liz_namedinode_entry *out_entries, uint32_t *num_entries) {
546 	Client &client = *(Client *)instance;
547 	Client::Context &context = *(Client::Context *)ctx;
548 	std::error_code ec;
549 	auto named_inodes = client.readreserved(context, offset, max_entries, ec);
550 	gLastErrorCode = ec.value();
551 	if (ec) {
552 		return -1;
553 	}
554 	return convert_named_inodes(out_entries, num_entries, named_inodes);
555 }
556 
liz_readtrash(liz_t * instance,liz_context_t * ctx,uint32_t offset,uint32_t max_entries,struct liz_namedinode_entry * out_entries,uint32_t * num_entries)557 int liz_readtrash(liz_t *instance, liz_context_t *ctx, uint32_t offset, uint32_t max_entries,
558 	          struct liz_namedinode_entry *out_entries, uint32_t *num_entries) {
559 	Client &client = *(Client *)instance;
560 	Client::Context &context = *(Client::Context *)ctx;
561 	std::error_code ec;
562 	auto named_inodes = client.readtrash(context, offset, max_entries, ec);
563 	gLastErrorCode = ec.value();
564 	if (ec) {
565 		return -1;
566 	}
567 	return convert_named_inodes(out_entries, num_entries, named_inodes);
568 }
569 
liz_free_namedinode_entries(struct liz_namedinode_entry * entries,uint32_t num_entries)570 void liz_free_namedinode_entries(struct liz_namedinode_entry *entries, uint32_t num_entries) {
571 	assert(num_entries > 0);
572 	(void)num_entries;
573 	delete[] entries->name;
574 }
575 
liz_mkdir(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,mode_t mode,struct liz_entry * entry)576 int liz_mkdir(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
577 		mode_t mode, struct liz_entry *entry) {
578 	Client &client = *(Client *)instance;
579 	Client::Context &context = *(Client::Context *)ctx;
580 	Client::EntryParam entry_param;
581 	std::error_code ec;
582 	client.mkdir(context, parent, path, mode, entry_param, ec);
583 	if (!ec) {
584 		to_entry(entry_param, entry);
585 	}
586 	gLastErrorCode = ec.value();
587 	return ec ? -1 : 0;
588 }
589 
liz_rmdir(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path)590 int liz_rmdir(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path) {
591 	Client &client = *(Client *)instance;
592 	Client::Context &context = *(Client::Context *)ctx;
593 	std::error_code ec;
594 	client.rmdir(context, parent, path, ec);
595 	gLastErrorCode = ec.value();
596 	return ec ? -1 : 0;
597 }
598 
liz_makesnapshot(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,liz_inode_t dst_parent,const char * dst_name,int can_overwrite,uint32_t * job_id)599 int liz_makesnapshot(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, liz_inode_t dst_parent,
600 	             const char *dst_name, int can_overwrite, uint32_t *job_id) {
601 	static_assert(sizeof(LizardClient::JobId) <= sizeof(uint32_t), "JobId type too large");
602 	Client &client = *(Client *)instance;
603 	Client::Context &context = *(Client::Context *)ctx;
604 	std::error_code ec;
605 	LizardClient::JobId ret = client.makesnapshot(context, inode, dst_parent, dst_name, can_overwrite, ec);
606 	if (job_id) {
607 		*job_id = ret;
608 	}
609 	gLastErrorCode = ec.value();
610 	return ec ? -1 : 0;
611 }
612 
liz_getgoal(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,char * goal_name)613 int liz_getgoal(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, char *goal_name) {
614 	Client &client = *(Client *)instance;
615 	Client::Context &context = *(Client::Context *)ctx;
616 	std::error_code ec;
617 	std::string goal = client.getgoal(context, inode, ec);
618 	gLastErrorCode = ec.value();
619 	if (ec) {
620 		return -1;
621 	}
622 	size_t copied = goal.copy(goal_name, LIZARDFS_MAX_GOAL_NAME - 1);
623 	goal_name[copied] = '\0';
624 
625 	return 0;
626 }
627 
liz_setgoal(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,const char * goal_name,int is_recursive)628 int liz_setgoal(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, const char *goal_name,
629 	        int is_recursive) {
630 	Client &client = *(Client *)instance;
631 	Client::Context &context = *(Client::Context *)ctx;
632 	std::error_code ec;
633 	client.setgoal(context, inode, goal_name, is_recursive ? SMODE_RMASK : 0, ec);
634 	gLastErrorCode = ec.value();
635 	return ec ? -1 : 0;
636 }
637 
liz_readlink(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,char * buf,size_t size)638 int liz_readlink(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, char *buf, size_t size) {
639 	Client &client = *(Client *)instance;
640 	Client::Context &context = *(Client::Context *)ctx;
641 	std::error_code ec;
642 	std::string link = client.readlink(context, inode, ec);
643 	gLastErrorCode = ec.value();
644 	if (ec) {
645 		return -1;
646 	}
647 	link.copy(buf, size);
648 	return link.size();
649 }
650 
liz_unlink(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path)651 int liz_unlink(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path) {
652 	Client &client = *(Client *)instance;
653 	Client::Context &context = *(Client::Context *)ctx;
654 	std::error_code ec;
655 	client.unlink(context, parent, path, ec);
656 	gLastErrorCode = ec.value();
657 	return ec ? -1 : 0;
658 }
659 
liz_undel(liz_t * instance,liz_context_t * ctx,liz_inode_t inode)660 int liz_undel(liz_t *instance, liz_context_t *ctx, liz_inode_t inode) {
661 	Client &client = *(Client *)instance;
662 	Client::Context &context = *(Client::Context *)ctx;
663 	std::error_code ec;
664 	client.undel(context, inode, ec);
665 	gLastErrorCode = ec.value();
666 	return ec ? -1 : 0;
667 }
668 
liz_setattr(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,struct stat * stbuf,int to_set,struct liz_attr_reply * reply)669 int liz_setattr(liz_t *instance, liz_context_t *ctx, liz_inode_t inode, struct stat *stbuf,
670 	        int to_set, struct liz_attr_reply *reply) {
671 	Client &client = *(Client *)instance;
672 	Client::Context &context = *(Client::Context *)ctx;
673 	Client::AttrReply r;
674 	std::error_code ec;
675 	client.setattr(context, inode, stbuf, to_set, r, ec);
676 	if (!ec) {
677 		to_attr_reply(r, reply);
678 	}
679 	gLastErrorCode = ec.value();
680 	return ec ? -1 : 0;
681 }
682 
liz_fsync(liz_t * instance,liz_context_t * ctx,struct liz_fileinfo * fileinfo)683 int liz_fsync(liz_t *instance, liz_context_t *ctx, struct liz_fileinfo *fileinfo) {
684 	Client &client = *(Client *)instance;
685 	Client::Context &context = *(Client::Context *)ctx;
686 	std::error_code ec;
687 	client.fsync(context, (Client::FileInfo *)fileinfo, ec);
688 	gLastErrorCode = ec.value();
689 	return ec ? -1 : 0;
690 }
691 
liz_rename(liz_t * instance,liz_context_t * ctx,liz_inode_t parent,const char * path,liz_inode_t new_parent,const char * new_path)692 int liz_rename(liz_t *instance, liz_context_t *ctx, liz_inode_t parent, const char *path,
693 	       liz_inode_t new_parent, const char *new_path) {
694 	Client &client = *(Client *)instance;
695 	Client::Context &context = *(Client::Context *)ctx;
696 	std::error_code ec;
697 	client.rename(context, parent, path, new_parent, new_path, ec);
698 	gLastErrorCode = ec.value();
699 	return ec ? -1 : 0;
700 }
701 
liz_statfs(liz_t * instance,liz_stat_t * buf)702 int liz_statfs(liz_t *instance, liz_stat_t *buf) {
703 	Client &client = *(Client *)instance;
704 	Client::Stats stats;
705 	std::error_code ec;
706 	client.statfs(stats, ec);
707 	gLastErrorCode = ec.value();
708 	if (ec) {
709 		return -1;
710 	}
711 	to_stat(stats, buf);
712 	return 0;
713 }
714 
liz_setxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name,const uint8_t * value,size_t size,int flags)715 int liz_setxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name,
716 	         const uint8_t *value, size_t size, int flags) {
717 	Client &client = *(Client *)instance;
718 	Client::Context &context = *(Client::Context *)ctx;
719 	std::error_code ec;
720 	client.setxattr(context, ino, name, std::vector<uint8_t>(value, value + size), flags, ec);
721 	gLastErrorCode = ec.value();
722 	return ec ? -1 : 0;
723 }
724 
liz_getxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name,size_t size,size_t * out_size,uint8_t * buf)725 int liz_getxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name,
726 	         size_t size, size_t *out_size, uint8_t *buf) {
727 	Client &client = *(Client *)instance;
728 	Client::Context &context = *(Client::Context *)ctx;
729 	std::error_code ec;
730 	auto ret = client.getxattr(context, ino, name, ec);
731 	gLastErrorCode = ec.value();
732 	if (ec) {
733 		return -1;
734 	}
735 	std::memcpy(buf, ret.data(), std::min(size, ret.size()));
736 	if (out_size) {
737 		*out_size = ret.size();
738 	}
739 	return 0;
740 }
741 
liz_listxattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,size_t size,size_t * out_size,char * buf)742 int liz_listxattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, size_t size,
743 	          size_t *out_size, char *buf) {
744 	Client &client = *(Client *)instance;
745 	Client::Context &context = *(Client::Context *)ctx;
746 	std::error_code ec;
747 	auto ret = client.listxattr(context, ino, ec);
748 	gLastErrorCode = ec.value();
749 	if (ec) {
750 		return -1;
751 	}
752 	std::memcpy(buf, ret.data(), std::min(size, ret.size()));
753 	if (out_size) {
754 		*out_size = ret.size();
755 	}
756 	return 0;
757 }
758 
liz_removexattr(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const char * name)759 int liz_removexattr(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const char *name) {
760 	Client &client = *(Client *)instance;
761 	Client::Context &context = *(Client::Context *)ctx;
762 	std::error_code ec;
763 	client.removexattr(context, ino, name, ec);
764 	gLastErrorCode = ec.value();
765 	return ec ? -1 : 0;
766 }
767 
liz_create_acl()768 liz_acl_t *liz_create_acl() {
769 	try {
770 		return (liz_acl_t *)new RichACL;
771 	} catch (...) {
772 		return nullptr;
773 	}
774 }
775 
liz_destroy_acl(liz_acl_t * acl)776 void liz_destroy_acl(liz_acl_t *acl) {
777 	delete (RichACL *)acl;
778 }
779 
liz_print_acl(liz_acl_t * acl,char * buf,size_t size,size_t * reply_size)780 int liz_print_acl(liz_acl_t *acl, char *buf, size_t size, size_t *reply_size) {
781 	assert(acl);
782 	assert(buf || size == 0);
783 	RichACL &richacl = *(RichACL *)acl;
784 	std::string repr = richacl.toString();
785 	assert(reply_size);
786 	*reply_size = repr.size();
787 	if (size < repr.size()) {
788 		gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
789 		return -1;
790 	}
791 	repr.copy(buf, size);
792 
793 	return 0;
794 }
795 
liz_add_acl_entry(liz_acl_t * acl,const liz_acl_ace_t * ace)796 void liz_add_acl_entry(liz_acl_t *acl, const liz_acl_ace_t *ace) {
797 	assert(acl);
798 	assert(ace);
799 	RichACL &richacl = *(RichACL *)acl;
800 	richacl.insert(RichACL::Ace(ace->type, ace->flags, ace->mask, ace->id));
801 }
802 
liz_get_acl_entry(const liz_acl_t * acl,int n,liz_acl_ace_t * ace)803 int liz_get_acl_entry(const liz_acl_t *acl, int n, liz_acl_ace_t *ace) {
804 	assert(acl);
805 	assert(ace);
806 	const RichACL &richacl = *(RichACL *)acl;
807 	if ((size_t)n > richacl.size()) {
808 		gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
809 		return -1;
810 	}
811 	auto it = std::next(richacl.begin(), n);
812 	ace->type = it->type;
813 	ace->flags = it->flags;
814 	ace->mask = it->mask;
815 	ace->id = it->id;
816 	return 0;
817 }
818 
liz_get_acl_size(const liz_acl_t * acl)819 size_t liz_get_acl_size(const liz_acl_t *acl) {
820 	assert(acl);
821 	const RichACL &richacl = *(RichACL *)acl;
822 	return richacl.size();
823 }
824 
liz_setacl(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,const liz_acl_t * acl)825 int liz_setacl(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, const liz_acl_t *acl) {
826 	assert(instance);
827 	assert(ctx);
828 	assert(acl);
829 	Client &client = *(Client *)instance;
830 	Client::Context &context = *(Client::Context *)ctx;
831 	std::error_code ec;
832 	try {
833 		const RichACL &richacl = *(RichACL *)acl;
834 		client.setacl(context, ino, richacl, ec);
835 		gLastErrorCode = ec.value();
836 		return ec ? -1 : 0;
837 	} catch (...) {
838 		gLastErrorCode = LIZARDFS_ERROR_ENOATTR;
839 		return -1;
840 	}
841 }
842 
liz_getacl(liz_t * instance,liz_context_t * ctx,liz_inode_t ino,liz_acl_t ** acl)843 int liz_getacl(liz_t *instance, liz_context_t *ctx, liz_inode_t ino, liz_acl_t **acl) {
844 	assert(instance);
845 	assert(ctx);
846 	assert(acl);
847 	Client &client = *(Client *)instance;
848 	Client::Context &context = *(Client::Context *)ctx;
849 	std::error_code ec;
850 	*acl = nullptr;
851 	try {
852 		RichACL richacl = client.getacl(context, ino, ec);
853 		gLastErrorCode = ec.value();
854 		if (ec) {
855 			return -1;
856 		}
857 		*acl = (liz_acl_t *)new RichACL(std::move(richacl));
858 	} catch (...) {
859 		gLastErrorCode = LIZARDFS_ERROR_ENOATTR;
860 		return -1;
861 	}
862 	return 0;
863 }
864 
liz_get_chunks_info(liz_t * instance,liz_context_t * ctx,liz_inode_t inode,uint32_t chunk_index,liz_chunk_info_t * buffer,uint32_t buffer_size,uint32_t * reply_size)865 int liz_get_chunks_info(liz_t *instance, liz_context_t *ctx, liz_inode_t inode,
866 	                    uint32_t chunk_index, liz_chunk_info_t *buffer, uint32_t buffer_size,
867 	                    uint32_t *reply_size) {
868 	assert(instance && ctx && buffer && reply_size);
869 
870 	Client &client = *(Client *)instance;
871 	Client::Context &context = *(Client::Context *)ctx;
872 
873 	if (buffer_size > 0) {
874 		buffer->parts = NULL;
875 	} else {
876 		gLastErrorCode = LIZARDFS_ERROR_EINVAL;
877 		return -1;
878 	}
879 
880 	std::error_code ec;
881 	auto chunks = client.getchunksinfo(context, inode, chunk_index, buffer_size, ec);
882 	gLastErrorCode = ec.value();
883 	if (ec) {
884 		return -1;
885 	}
886 
887 	*reply_size = chunks.size();
888 	if (chunks.size() > buffer_size) {
889 		gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
890 		return -1;
891 	}
892 
893 	std::size_t strings_size = 0;
894 	std::size_t parts_table_size = 0;
895 	for(const auto &chunk : chunks) {
896 		parts_table_size += chunk.chunk_parts.size() * sizeof(liz_chunk_part_info_t);
897 		for(const auto &part : chunk.chunk_parts) {
898 			strings_size += part.label.size() + 1;
899 		}
900 	}
901 
902 	uint8_t *data_buffer = (uint8_t *)std::malloc(parts_table_size + strings_size);
903 	if (data_buffer == NULL) {
904 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
905 		return -1;
906 	}
907 
908 	auto buf_part = (liz_chunk_part_info_t *)data_buffer;
909 	auto buf_string = (char *)(data_buffer + parts_table_size);
910 	auto buf_chunk = buffer;
911 	for(const auto &chunk : chunks) {
912 		buf_chunk->chunk_id = chunk.chunk_id;
913 		buf_chunk->chunk_version = chunk.chunk_version;
914 		buf_chunk->parts = buf_part;
915 		buf_chunk->parts_size = chunk.chunk_parts.size();
916 
917 		for(const auto &part : chunk.chunk_parts) {
918 			buf_part->addr = part.address.ip;
919 			buf_part->port = part.address.port;
920 			buf_part->part_type_id = part.chunkType.getId();
921 			buf_part->label = buf_string;
922 			std::strcpy(buf_string, part.label.c_str());
923 
924 			buf_string += part.label.size() + 1;
925 			++buf_part;
926 		}
927 		++buf_chunk;
928 	}
929 
930 	gLastErrorCode = LIZARDFS_STATUS_OK;
931 	return 0;
932 }
933 
liz_get_chunkservers_info(liz_t * instance,liz_chunkserver_info_t * servers,uint32_t size,uint32_t * reply_size)934 int liz_get_chunkservers_info(liz_t *instance, liz_chunkserver_info_t *servers, uint32_t size,
935 	                 uint32_t *reply_size) {
936 	Client &client = *(Client *)instance;
937 	std::error_code ec;
938 
939 	if (size > 0) {
940 		servers->label = nullptr;
941 	} else {
942 		gLastErrorCode = LIZARDFS_ERROR_EINVAL;
943 		return -1;
944 	}
945 
946 	std::vector<ChunkserverListEntry> entries = client.getchunkservers(ec);
947 	gLastErrorCode = ec.value();
948 	if (ec) {
949 		return -1;
950 	}
951 	*reply_size = entries.size();
952 	if (entries.size() > size) {
953 		gLastErrorCode = LIZARDFS_ERROR_WRONGSIZE;
954 		return -1;
955 	}
956 	size_t total_str_size = 0;
957 	for (const ChunkserverListEntry &entry : entries) {
958 		total_str_size += entry.label.size() + 1;
959 	}
960 
961 	char *str_buf = (char *)malloc(total_str_size);
962 	if (str_buf == nullptr) {
963 		gLastErrorCode = LIZARDFS_ERROR_OUTOFMEMORY;
964 		return -1;
965 	}
966 	for (const ChunkserverListEntry &entry : entries) {
967 		servers->version = entry.version;
968 		servers->ip = entry.servip;
969 		servers->port = entry.servport;
970 		servers->used_space = entry.usedspace;
971 		servers->total_space = entry.totalspace;
972 		servers->error_counter = entry.errorcounter;
973 		servers->label = strcpy(str_buf, entry.label.c_str());
974 		str_buf += entry.label.size() + 1;
975 		servers++;
976 	}
977 	gLastErrorCode = LIZARDFS_STATUS_OK;
978 	return 0;
979 }
980 
liz_destroy_chunkservers_info(liz_chunkserver_info_t * servers)981 void liz_destroy_chunkservers_info(liz_chunkserver_info_t *servers) {
982 	if (servers) {
983 		free(servers->label);
984 	}
985 }
986 
liz_destroy_chunks_info(liz_chunk_info_t * buffer)987 void liz_destroy_chunks_info(liz_chunk_info_t *buffer) {
988 	if (buffer && buffer->parts) {
989 		std::free(buffer->parts);
990 	}
991 }
992 
liz_setlk(liz_t * instance,liz_context_t * ctx,liz_fileinfo_t * fileinfo,const liz_lock_info * lock,liz_lock_register_interrupt_t handler,void * priv)993 int liz_setlk(liz_t *instance, liz_context_t *ctx, liz_fileinfo_t *fileinfo,
994 	      const liz_lock_info *lock, liz_lock_register_interrupt_t handler, void *priv) {
995 	Client &client = *(Client *)instance;
996 	Client::Context &context = *(Client::Context *)ctx;
997 	Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
998 	gLastErrorCode = 0;
999 
1000 	lzfs_locks::FlockWrapper flock_wrapper;
1001 	flock_wrapper.l_type = lock->l_type;
1002 	flock_wrapper.l_start = lock->l_start;
1003 	flock_wrapper.l_len = lock->l_len;
1004 	flock_wrapper.l_pid = lock->l_pid;
1005 	std::error_code ec;
1006 	liz_lock_interrupt_info_t interrupt_info;
1007 	std::function<int(const lzfs_locks::InterruptData &)> lambda;
1008 	if (handler) {
1009 		lambda = [&handler, &interrupt_info, priv](const lzfs_locks::InterruptData &data) {
1010 			interrupt_info.owner = data.owner;
1011 			interrupt_info.ino = data.ino;
1012 			interrupt_info.reqid = data.reqid;
1013 			return handler(&interrupt_info, priv);
1014 		};
1015 	}
1016 	client.setlk(context, fi->inode, fi, flock_wrapper, lambda, ec);
1017 	gLastErrorCode = ec.value();
1018 	return ec ? -1 : 0;
1019 }
1020 
liz_getlk(liz_t * instance,liz_context_t * ctx,liz_fileinfo_t * fileinfo,liz_lock_info * lock)1021 int liz_getlk(liz_t *instance, liz_context_t *ctx, liz_fileinfo_t *fileinfo, liz_lock_info *lock) {
1022 	Client &client = *(Client *)instance;
1023 	Client::Context &context = *(Client::Context *)ctx;
1024 	Client::FileInfo *fi = (Client::FileInfo *)fileinfo;
1025 	gLastErrorCode = 0;
1026 
1027 	lzfs_locks::FlockWrapper flock_wrapper;
1028 	flock_wrapper.l_type = lock->l_type;
1029 	flock_wrapper.l_start = lock->l_start;
1030 	flock_wrapper.l_len = lock->l_len;
1031 	flock_wrapper.l_pid = lock->l_pid;
1032 	std::error_code ec;
1033 	client.getlk(context, fi->inode, fi, flock_wrapper, ec);
1034 	if (ec) {
1035 		gLastErrorCode = ec.value();
1036 		return -1;
1037 	}
1038 	lock->l_type = flock_wrapper.l_type;
1039 	lock->l_start = flock_wrapper.l_start;
1040 	lock->l_len = flock_wrapper.l_len;
1041 	lock->l_pid = flock_wrapper.l_pid;
1042 	return 0;
1043 }
1044 
liz_setlk_interrupt(liz_t * instance,const liz_lock_interrupt_info_t * interrupt_info)1045 int liz_setlk_interrupt(liz_t *instance, const liz_lock_interrupt_info_t *interrupt_info) {
1046 	if (interrupt_info == nullptr) {
1047 		return 0;
1048 	}
1049 	Client &client = *(Client *)instance;
1050 	lzfs_locks::InterruptData interrupt_data;
1051 	interrupt_data.owner = interrupt_info->owner;
1052 	interrupt_data.ino = interrupt_info->ino;
1053 	interrupt_data.reqid = interrupt_info->reqid;
1054 	std::error_code ec;
1055 	client.setlk_interrupt(interrupt_data, ec);
1056 	if (ec) {
1057 		gLastErrorCode = ec.value();
1058 		return -1;
1059 	}
1060 	return 0;
1061 }
1062