8 | *
9 | * @author Sergey Tselovalnikov
10 | * @since 05.06.15
11 | */
12 | public final class AccessConstants {
13 | public static final int R_OK = Access.R_OK.intValue(); /* Test for read permission. */
14 | public static final int W_OK = Access.W_OK.intValue(); /* Test for write permission. */
15 | public static final int X_OK = Access.X_OK.intValue(); /* Test for execute permission. */
16 | public static final int F_OK = Access.F_OK.intValue(); /* Test for existence. */
17 |
18 | private AccessConstants() {}
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/DirectoryFiller.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | /**
4 | * Base interface for the transfer-object for the readdir() call.
5 | */
6 | public interface DirectoryFiller {
7 | /**
8 | * Pass the given files to the FUSE interfaces.
9 | *
10 | * @param files A list of filenames without directory.
11 | * @return true if the operation succeeds, false if a problem happens when passing any of the files to FUSE.
12 | */
13 | public boolean add(Iterable
15 | * If this flag is set, the .fd field is valid, otherwise the
16 | * .mem fields is valid.
17 | */
18 | FUSE_BUF_IS_FD(1 << 1),
19 |
20 | /**
21 | * Seek on the file descriptor
22 | *
23 | * If this flag is set then the .pos field is valid and is
24 | * used to seek to the given offset before performing
25 | * operation on file descriptor.
26 | */
27 | FUSE_BUF_FD_SEEK(1 << 2),
28 |
29 | /**
30 | * Retry operation on file descriptor
31 | *
32 | * If this flag is set then retry operation on file descriptor
33 | * until .size bytes have been copied or an error or EOF is
34 | * detected.
35 | */
36 | FUSE_BUF_FD_RETRY(1 << 3),
37 |
38 | /**
39 | * JNR does not work without null value enum
40 | */
41 | NULL_VALUE(0);
42 |
43 | private final int value;
44 |
45 | FuseBufFlags(int value) {
46 | this.value = value;
47 | }
48 |
49 | /**
50 | * Special JNR method, see jnr.ffi.util.EnumMapper#getNumberValueMethod(java.lang.Class, java.lang.Class)
51 | */
52 | @Override
53 | public int intValue() {
54 | return value;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/FuseException.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import java.io.IOException;
4 |
5 | final class FuseException extends IOException {
6 | private static long serialVersionUID = -3323428017667312747L;
7 |
8 | FuseException(int returnCode) {
9 | super("FUSE returned error code " + returnCode);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/FuseFilesystem.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import java.io.IOException;
4 | import java.nio.ByteBuffer;
5 | import java.nio.file.Path;
6 | import java.util.concurrent.locks.ReentrantLock;
7 | import java.util.logging.Logger;
8 | import java.util.regex.Pattern;
9 | import jnr.ffi.Pointer;
10 | import jnr.ffi.types.gid_t;
11 | import jnr.ffi.types.pid_t;
12 | import jnr.ffi.types.uid_t;
13 |
14 | /**
15 | * Fuse file system.
16 | * All documentation from "fuse.h"
17 | *
18 | * @see http://fuse.sourceforge.net/doxygen/index.html
19 | * @see http://fuse.sourceforge.net/wiki/
20 | */
21 | public abstract class FuseFilesystem {
22 | private static final String defaultFilesystemName = "userfs-";
23 | private static final Pattern regexNormalizeFilesystemName = Pattern.compile("[^a-zA-Z]");
24 |
25 | /**
26 | * Perform destroy-time cleanup. Takes two {@link FuseFilesystem}s arguments which should be equal in most cases, but may
27 | * not in the case of a wrapped filesystem object for logging ({@link LoggedFuseFilesystem}).
28 | *
29 | * @param mountedFilesystem The {@link FuseFilesystem} object that is actually mounted (the one receiving the destroy call)
30 | * @param userFilesystem The {@link FuseFilesystem} that the user believes is mounted (the one that the user called .mount on)
31 | */
32 | final static void _destroy(FuseFilesystem mountedFilesystem, FuseFilesystem userFilesystem) {
33 | final Path oldMountPoint;
34 | mountedFilesystem.mountLock.lock();
35 | userFilesystem.mountLock.lock();
36 | try {
37 | if (!mountedFilesystem.isMounted())
38 | throw new IllegalStateException("destroy called on a non-mounted filesystem");
39 |
40 | oldMountPoint = mountedFilesystem.mountPoint;
41 | Fuse.destroyed(mountedFilesystem);
42 | userFilesystem.mountPoint = null;
43 | mountedFilesystem.mountPoint = null;
44 | } finally {
45 | userFilesystem.mountLock.unlock();
46 | mountedFilesystem.mountLock.unlock();
47 | }
48 | mountedFilesystem.afterUnmount(oldMountPoint);
49 | }
50 |
51 | private final ReentrantLock mountLock = new ReentrantLock();
52 | private final AutoUnmountHook unmountHook = new AutoUnmountHook();
53 | private volatile Path mountPoint = null;
54 | private Logger logger = null;
55 |
56 | protected abstract void afterUnmount(Path mountPoint);
57 |
58 | protected abstract void beforeMount(Path mountPoint);
59 |
60 | public final boolean isMounted() {
61 | return getMountPoint() != null;
62 | }
63 |
64 | void _destroy() {
65 | _destroy(this, this);
66 | }
67 |
68 | /**
69 | * Returns the raw fuse_context structure. Only valid when called while a filesystem operation is taking place.
70 | *
71 | * @return The fuse_context structure by reference.
72 | */
73 | protected final StructFuseContext getFuseContext() {
74 | if (!isMounted())
75 | throw new IllegalStateException("Cannot get FUSE context if the filesystem is not mounted.");
76 |
77 | return Fuse.getFuseContext();
78 | }
79 |
80 | /**
81 | * Returns the gid field of the fuse context. Only valid when called while a filesystem operation is taking place.
82 | *
83 | * @return The group ID of the process executing an operation on this filesystem.
84 | */
85 | protected @gid_t long getFuseContextGid() {
86 | return getFuseContext().gid.get();
87 | }
88 |
89 | /**
90 | * Returns the pid field of the fuse context. Only valid when called while a filesystem operation is taking place.
91 | *
92 | * @return The process ID of the process executing an operation on this filesystem.
93 | */
94 | protected @pid_t long getFuseContextPid() {
95 | return getFuseContext().pid.get();
96 | }
97 |
98 | /**
99 | * Returns the uid field of the fuse context. Only valid when called while a filesystem operation is taking place.
100 | *
101 | * @return The user ID of the user running the process executing an operation of this filesystem.
102 | */
103 | protected @uid_t long getFuseContextUid() {
104 | return getFuseContext().uid.get();
105 | }
106 |
107 | final String getFuseName() {
108 | String name = getName();
109 | if (name == null)
110 | return defaultFilesystemName;
111 |
112 | name = regexNormalizeFilesystemName.matcher(name).replaceAll("");
113 | if (name.isEmpty())
114 | return defaultFilesystemName;
115 |
116 | return name.toLowerCase();
117 | }
118 |
119 | protected final Logger getLogger() {
120 | return logger;
121 | }
122 |
123 | public final Path getMountPoint() {
124 | return this.mountPoint;
125 | }
126 |
127 | protected abstract String getName();
128 |
129 | protected abstract String[] getOptions();
130 |
131 | final AutoUnmountHook getUnmountHook() {
132 | return unmountHook;
133 | }
134 |
135 | /**
136 | * Populates a {@link StatWrapper} with somewhat-sane, usually-better-than-zero values. Subclasses may override this to
137 | * customize the default parameters applied to the stat structure, or to prevent such behavior in the first place (by
138 | * overriding this method with an empty one).
139 | *
140 | * @param stat The StructStat object to write to.
141 | * @param uid The UID under which the JVM is running.
142 | * @param gid The GID under which the JVM is running.
143 | */
144 | protected StructStat defaultStat(StructStat stat) {
145 | // Set some sensible defaults
146 | stat.mode(0).setAllTimesMillis(Fuse.getInitTime()).nlink(1).uid(Fuse.getUid()).gid(Fuse.getGid());
147 | return stat;
148 | }
149 |
150 | public final FuseFilesystem log(boolean logging) {
151 | return log(logging ? Logger.getLogger(getClass().getCanonicalName()) : null);
152 | }
153 |
154 | public final FuseFilesystem log(Logger logger) {
155 | mountLock.lock();
156 | try {
157 | if (mountPoint != null)
158 | throw new IllegalStateException("Cannot turn logging on/orr when filesystem is already mounted.");
159 | this.logger = logger;
160 | } finally {
161 | mountLock.unlock();
162 | }
163 | return this;
164 | }
165 |
166 | final void mount(Path mountPoint, boolean blocking) throws IOException {
167 | mountLock.lock();
168 | try {
169 | if (isMounted()) {
170 | mountLock.unlock();
171 | throw new IllegalStateException(getFuseName() + " is already mounted at " + this.mountPoint);
172 | }
173 | this.mountPoint = mountPoint;
174 | } finally {
175 | mountLock.unlock();
176 | }
177 | beforeMount(mountPoint);
178 | }
179 |
180 | final void unmount() throws IOException {
181 | if (!isMounted())
182 | throw new IllegalStateException("Tried to unmount a filesystem which is not mounted");
183 | }
184 |
185 | final class AutoUnmountHook extends Thread {
186 | @Override
187 | public final void run() {
188 | try {
189 | Fuse.unmount(FuseFilesystem.this);
190 | } catch (final Exception e) {
191 | // Can't do much here in a shutdown hook. Silently ignore.
192 | }
193 | }
194 | }
195 |
196 | ////////////////////////////////
197 | /**
198 | * Get file attributes.
199 | *
200 | * Similar to stat(). The 'st_dev' and 'st_blksize' fields are ignored.
201 | * The 'st_ino' field is ignored except if the 'use_ino' mount option is given.
202 | *
203 | * @param path
204 | * @param stat
205 | * @return
206 | */
207 | protected abstract int getattr(String path, StructStat stat);
208 |
209 | /**
210 | * Read the target of a symbolic link.
211 | *
212 | * The buffer should be filled with a null terminated string.
213 | * The buffer size argument includes the space for the terminating null character.
214 | * If the linkname is too long to fit in the buffer, it should be truncated. The return value should be 0 for success.
215 | *
216 | * @param path
217 | * @param buffer
218 | * @param size
219 | * @return
220 | */
221 | protected abstract int readlink(String path, ByteBuffer buffer, long size);
222 |
223 | /**
224 | * Create a file node.
225 | *
226 | * This is called for creation of all non-directory, non-symlink nodes.
227 | * If the filesystem defines a create() method, then for regular files that will be called instead.
228 | *
229 | * @param path
230 | * @param mode
231 | * @param dev
232 | * @return
233 | */
234 | protected abstract int mknod(String path, long mode, long dev);
235 |
236 | /**
237 | * Create a directory.
238 | *
239 | * Note that the mode argument may not have the type specification bits set, i.e. S_ISDIR(mode) can be false.
240 | * To obtain the correct directory type bits use mode|S_IFDIR
241 | *
242 | * @param path
243 | * @param mode
244 | * @return
245 | */
246 | protected abstract int mkdir(String path, long mode);
247 |
248 | /**
249 | * Remove a file.
250 | *
251 | * @param path
252 | * @return
253 | */
254 | protected abstract int unlink(String path);
255 |
256 | /**
257 | * Remove a directory.
258 | *
259 | * @param path
260 | * @return
261 | */
262 | protected abstract int rmdir(String path);
263 |
264 | /**
265 | * Create a symbolic link.
266 | *
267 | * @param path
268 | * @param target
269 | * @return
270 | */
271 | protected abstract int symlink(String path, String target);
272 |
273 | /**
274 | * Rename a file.
275 | *
276 | * @param path
277 | * @param newName
278 | * @return
279 | */
280 | protected abstract int rename(String path, String newName);
281 |
282 | /**
283 | * Create a hard link to a file.
284 | *
285 | * @param path
286 | * @param target
287 | * @return
288 | */
289 | protected abstract int link(String path, String target);
290 |
291 | /**
292 | * Change the permission bits of a file.
293 | *
294 | * @param path
295 | * @param mode
296 | * @return
297 | */
298 | protected abstract int chmod(String path, long mode);
299 |
300 | /**
301 | * Change the owner and group of a file.
302 | *
303 | * @param path
304 | * @param uid
305 | * @param gid
306 | * @return
307 | */
308 | protected abstract int chown(String path, long uid, long gid);
309 |
310 | /**
311 | * Change the size of a file.
312 | *
313 | * @param path
314 | * @param offset
315 | * @return
316 | */
317 | protected abstract int truncate(String path, long offset);
318 |
319 | /**
320 | * File open operation.
321 | *
322 | * No creation (O_CREAT, O_EXCL) and by default also no truncation (O_TRUNC) flags will be passed to open().
323 | * If an application specifies O_TRUNC, fuse first calls truncate() and then open().
324 | * Only if 'atomic_o_trunc' has been specified and kernel version is 2.6.24 or later, O_TRUNC is passed on to open.
325 | *
326 | * Unless the 'default_permissions' mount option is given, open should check if the operation is permitted for the given flags.
327 | * Optionally open may also return an arbitrary filehandle in the fuse_file_info structure, which will be passed to all file operations.
328 | *
329 | * Changed in version 2.2
330 | *
331 | * @param path
332 | * @param info
333 | * @return
334 | */
335 | protected abstract int open(String path, StructFuseFileInfo info);
336 |
337 | /**
338 | * Read data from an open file.
339 | *
340 | * Read should return exactly the number of bytes requested except on EOF or error,
341 | * otherwise the rest of the data will be substituted with zeroes.
342 | * An exception to this is when the 'direct_io' mount option is specified,
343 | * in which case the return value of the read system call will reflect the return value of this operation.
344 | *
345 | * Changed in version 2.2
346 | *
347 | * @param path
348 | * @param buffer
349 | * @param size
350 | * @param offset
351 | * @param info
352 | * @return
353 | */
354 | protected abstract int read(String path, ByteBuffer buffer, long size, long offset, StructFuseFileInfo info);
355 |
356 | /**
357 | * Write data to an open file.
358 | *
359 | * Write should return exactly the number of bytes requested except on error.
360 | * An exception to this is when the 'direct_io' mount option is specified (see read operation).
361 | *
362 | * Changed in version 2.2
363 | *
364 | * @param path
365 | * @param buf
366 | * @param bufSize
367 | * @param writeOffset
368 | * @param info
369 | * @return
370 | */
371 | protected abstract int write(String path, ByteBuffer buf, long bufSize, long writeOffset, StructFuseFileInfo info);
372 |
373 | /**
374 | * Get file system statistics.
375 | *
376 | * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
377 | *
378 | * Replaced 'struct statfs' parameter with 'struct statvfs' in version 2.5
379 | *
380 | * @param path
381 | * @param statvfs
382 | * @return
383 | */
384 | protected abstract int statfs(String path, StructStatvfs statvfs);
385 |
386 | /**
387 | * Possibly flush cached data.
388 | *
389 | * BIG NOTE: This is not equivalent to fsync(). It's not a request to sync dirty data.
390 | *
391 | * Flush is called on each close() of a file descriptor.
392 | * So if a filesystem wants to return write errors in close() and the file has cached dirty data,
393 | * this is a good place to write back data and return any errors. Since many applications ignore close() errors this is not always useful.
394 | *
395 | * NOTE: The flush() method may be called more than once for each open(). This happens if more than one file descriptor refers to an opened file due to dup(), dup2() or fork() calls. It is not possible to determine if a flush is final, so each flush should be treated equally. Multiple write-flush sequences are relatively rare, so this shouldn't be a problem.
396 | *
397 | * Filesystems shouldn't assume that flush will always be called after some writes, or that if will be called at all.
398 | *
399 | * Changed in version 2.2
400 | *
401 | * @param path
402 | * @param info
403 | * @return
404 | */
405 | protected abstract int flush(String path, StructFuseFileInfo info);
406 |
407 | /**
408 | * Release an open file.
409 | *
410 | * Release is called when there are no more references to an open file: all file descriptors are closed and all memory mappings are unmapped.
411 | *
412 | * For every open() call there will be exactly one release() call with the same flags and file descriptor.
413 | * It is possible to have a file opened more than once, in which case only the last release will mean, that no more reads/writes will happen on the file.
414 | * The return value of release is ignored.
415 | *
416 | * Changed in version 2.2
417 | *
418 | * @param path
419 | * @param info
420 | * @return
421 | */
422 | protected abstract int release(String path, StructFuseFileInfo info);
423 |
424 | /**
425 | * Synchronize file contents.
426 | *
427 | * If the datasync parameter is non-zero, then only the user data should be flushed, not the meta data.
428 | *
429 | * Changed in version 2.2
430 | *
431 | * @param path
432 | * @param datasync
433 | * @param info
434 | * @return
435 | */
436 | protected abstract int fsync(String path, int datasync, StructFuseFileInfo info);
437 |
438 | /**
439 | * Set extended attribute.
440 | *
441 | * Set the attribute NAME of the file pointed to by PATH to VALUE (which
442 | * is SIZE bytes long).
443 | *
444 | * @param flags see {@link XAttrConstants}
445 | * @return Return 0 on success, -1 for errors.
446 | */
447 | protected abstract int setxattr(String path, String xattr, ByteBuffer value, long size, int flags, int position);
448 |
449 | /**
450 | * Get extended attribute.
451 | *
452 | * Get the attribute NAME of the file pointed to by PATH to VALUE (which is
453 | * SIZE bytes long).
454 | *
455 | * @return Return 0 on success, -1 for errors.
456 | */
457 | protected abstract int getxattr(String path, String xattr, XattrFiller filler, long size, long position);
458 |
459 | /**
460 | * List extended attributes.
461 | *
462 | * The retrieved list is placed
463 | * in list, a caller-allocated buffer whose size (in bytes) is specified
464 | * in the argument size. The list is the set of (null-terminated)
465 | * names, one after the other. Names of extended attributes to which
466 | * the calling process does not have access may be omitted from the
467 | * list. The length of the attribute name list is returned
468 | *
469 | * @param path
470 | * @param filler
471 | * @return
472 | */
473 | protected abstract int listxattr(String path, XattrListFiller filler);
474 |
475 | /**
476 | * Remove extended attributes.
477 | * Remove the attribute NAME from the file pointed to by PATH.
478 | *
479 | * @param path
480 | * @param xattr
481 | * @return 0 on success, -1 for errors.
482 | */
483 | protected abstract int removexattr(String path, String xattr);
484 |
485 | /**
486 | * Open directory.
487 | *
488 | * Unless the 'default_permissions' mount option is given, this method should check if opendir is permitted for this directory.
489 | * Optionally opendir may also return an arbitrary filehandle in the fuse_file_info structure,
490 | * which will be passed to readdir, closedir and fsyncdir.
491 | *
492 | * Introduced in version 2.3
493 | *
494 | * @param path
495 | * @param info
496 | * @return
497 | */
498 | protected abstract int opendir(String path, StructFuseFileInfo info);
499 |
500 | /**
501 | * Read directory.
502 | *
503 | * The filesystem may choose between two modes of operation:
504 | *
505 | *
524 | * Introduced in version 2.3
525 | *
526 | * @param path
527 | * @param info
528 | * @return
529 | */
530 | protected abstract int releasedir(String path, StructFuseFileInfo info);
531 |
532 | /**
533 | * Synchronize directory contents.
534 | *
535 | * If the datasync parameter is non-zero, then only the user data should be flushed, not the meta data
536 | *
537 | * Introduced in version 2.3
538 | *
539 | * @param path
540 | * @param datasync
541 | * @param info
542 | * @return
543 | */
544 | protected abstract int fsyncdir(String path, int datasync, StructFuseFileInfo info);
545 |
546 | /**
547 | * Initialize filesystem.
548 | *
549 | * The return value will passed in the private_data field of fuse_context to all file operations and as a parameter to the destroy() method.
550 | *
551 | * Introduced in version 2.3 Changed in version 2.6
552 | */
553 | protected abstract void init();
554 |
555 | /**
556 | * Clean up filesystem
557 | *
558 | * Called on filesystem exit.
559 | *
560 | * Introduced in version 2.3
561 | */
562 | protected abstract void destroy();
563 |
564 | /**
565 | * Check file access permissions.
566 | *
567 | * This will be called for the access() system call.
568 | * If the 'default_permissions' mount option is given, this method is not called.
569 | *
570 | * This method is not called under Linux kernel versions 2.4.x
571 | *
572 | * Introduced in version 2.5
573 | *
574 | * @param mask see {@link AccessConstants}
575 | * @return -ENOENT if the path doesn't exist, -EACCESS if the requested permission isn't available, or 0 for success
576 | * @return
577 | */
578 | protected abstract int access(String path, int access);
579 |
580 | /**
581 | * Create and open a file.
582 | *
583 | * If the file does not exist, first create it with the specified mode, and then open it.
584 | *
585 | * If this method is not implemented or under Linux kernel versions earlier than 2.6.15,
586 | * the mknod() and open() methods will be called instead.
587 | *
588 | * Introduced in version 2.5
589 | *
590 | * @param path
591 | * @param mode
592 | * @param info
593 | * @return
594 | */
595 | protected abstract int create(String path, long mode, StructFuseFileInfo info);
596 |
597 | /**
598 | * Change the size of an open file.
599 | *
600 | * This method is called instead of the truncate() method if the truncation was invoked from an ftruncate() system call.
601 | *
602 | * If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the truncate() method will be called instead.
603 | *
604 | * Introduced in version 2.5
605 | *
606 | * @param path
607 | * @param offset
608 | * @param info
609 | * @return
610 | */
611 | protected abstract int ftruncate(String path, long offset, StructFuseFileInfo info);
612 |
613 | /**
614 | * Get attributes from an open file.
615 | *
616 | * This method is called instead of the getattr() method if the file information is available.
617 | *
618 | * Currently this is only called after the create() method if that is implemented (see above).
619 | * Later it may be called for invocations of fstat() too.
620 | *
621 | * Introduced in version 2.5
622 | *
623 | * @param path
624 | * @param stat
625 | * @param info
626 | * @return
627 | */
628 | protected abstract int fgetattr(String path, StructStat stat, StructFuseFileInfo info);
629 |
630 | /**
631 | * Perform POSIX file locking operation.
632 | *
633 | * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
634 | *
635 | * For the meaning of fields in 'struct flock' see the man page for fcntl(2). The l_whence field will always be set to SEEK_SET.
636 | *
637 | * For checking lock ownership, the 'fuse_file_info->owner' argument must be used.
638 | *
639 | * For F_GETLK operation, the library will first check currently held locks,
640 | * and if a conflicting lock is found it will return information without calling this method.
641 | * This ensures, that for local locks the l_pid field is correctly filled in.
642 | * The results may not be accurate in case of race conditions and in the presence of hard links,
643 | * but it's unlikely that an application would rely on accurate GETLK results in these cases.
644 | * If a conflicting lock is not found, this method will be called, and the filesystem may fill out l_pid by a meaningful value,
645 | * or it may leave this field zero.
646 | *
647 | * For F_SETLK and F_SETLKW the l_pid field will be set to the pid of the process performing the locking operation.
648 | *
649 | * Note: if this method is not implemented, the kernel will still allow file locking to work locally.
650 | * Hence it is only interesting for network filesystems and similar.
651 | *
652 | * Introduced in version 2.6
653 | *
654 | * @param path
655 | * @param info
656 | * @param command
657 | * @param flock
658 | * @return
659 | */
660 | protected abstract int lock(String path, StructFuseFileInfo info, int command, StructFlock flock);
661 |
662 | /**
663 | * Change the access and modification times of a file with nanosecond resolution.
664 | *
665 | * This supersedes the old utime() interface. New applications should use this.
666 | *
667 | * See the utimensat(2) man page for details.
668 | *
669 | * Introduced in version 2.6
670 | *
671 | * @param path
672 | * @param timeBuffer
673 | * @return
674 | */
675 | protected abstract int utimens(String path, StructTimeBuffer timeBuffer);
676 |
677 | /**
678 | * Map block index within file to block index within device/
679 | *
680 | * Note: This makes sense only for block device backed filesystems mounted with the 'blkdev' option
681 | *
682 | * Introduced in version 2.6
683 | *
684 | * @param path
685 | * @param info
686 | * @return
687 | */
688 | protected abstract int bmap(String path, StructFuseFileInfo info);
689 |
690 | /**
691 | * Ioctl.
692 | *
693 | * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in 64bit environment.
694 | * The size and direction of data is determined by _IOC_*() decoding of cmd.
695 | * For _IOC_NONE, data will be NULL, for _IOC_WRITE data is out area, for _IOC_READ in area and if both are set in/out area.
696 | * In all non-NULL cases, the area is of _IOC_SIZE(cmd) bytes.
697 | *
698 | * @param flags See {
699 | * @IoctlFlags}
700 | */
701 | protected abstract int ioctl(String path, int cmd, Pointer arg, StructFuseFileInfo fi, long flags, Pointer data);
702 |
703 | /**
704 | * Poll for IO readiness events.
705 | *
706 | * Note: If ph is non-NULL, the client should notify when IO readiness events occur by calling
707 | * fuse_notify_poll() with the specified ph.
708 | *
709 | * Regardless of the number of times poll with a non-NULL ph is received, single notification is enough to clear all.
710 | * Notifying more times incurs overhead but doesn't harm correctness.
711 | *
712 | * The callee is responsible for destroying ph with fuse_pollhandle_destroy() when no longer in use.
713 | *
714 | * @param reventsp A pointer to a bitmask of the returned events satisfied.
715 | */
716 | protected abstract int poll(String path, StructFuseFileInfo fi, StructFusePollHandle ph, Pointer reventsp);
717 |
718 | /**
719 | * Write contents of buffer to an open file.
720 | *
721 | * Similar to the write() method, but data is supplied in a generic buffer.
722 | * Use fuse_buf_copy() to transfer data to the destination.
723 | */
724 | protected abstract int write_buf(String path, StructFuseBufvec buf, long off, StructFuseFileInfo fi);
725 |
726 | /**
727 | * Store data from an open file in a buffer.
728 | *
729 | * Similar to the read() method, but data is stored and returned in a generic buffer.
730 | *
731 | * No actual copying of data has to take place, the source file descriptor may simply be stored in the buffer for later data transfer.
732 | *
733 | * The buffer must be allocated dynamically and stored at the location pointed to by bufp.
734 | * If the buffer contains memory regions, they too must be allocated using malloc().
735 | * The allocated memory will be freed by the caller.
736 | */
737 | protected abstract int read_buf(String path, Pointer bufp, long size, long off, StructFuseFileInfo fi);
738 |
739 | /**
740 | * Perform BSD file locking operation
741 | *
742 | * The op argument will be either LOCK_SH, LOCK_EX or LOCK_UN
743 | *
744 | * Nonblocking requests will be indicated by ORing LOCK_NB to
745 | * the above operations
746 | *
747 | * For more information see the flock(2) manual page.
748 | *
749 | * Additionally fi->owner will be set to a value unique to this open file.
750 | * This same value will be supplied to ->release() when the file is released.
751 | *
752 | * Note: if this method is not implemented, the kernel will still allow file locking to work locally.
753 | * Hence it is only interesting for network filesystems and similar.
754 | *
755 | * @param op see {@link ru.serce.jnrfuse.struct.Flock}
756 | */
757 | protected abstract int flock(String path, StructFuseFileInfo fi, int op);
758 |
759 | /**
760 | * Allocates space for an open file.
761 | *
762 | * This function ensures that required space is allocated for specified file.
763 | * If this function returns success then any subsequent write request to specified range is guaranteed not to fail because of lack
764 | * of space on the file system media.
765 | */
766 | protected abstract int fallocate(String path, int mode, long off, long length, StructFuseFileInfo fi);
767 | }
768 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/IoctlFlags.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | /**
4 | * @author Sergey Tselovalnikov
5 | * @since 05.06.15
6 | */
7 | final class IoctlFlags {
8 |
9 | // flags
10 | public static final int _IOC_NONE = 0;
11 | public static final int _IOC_READ = 2;
12 | public static final int _IOC_WRITE = 1;
13 |
14 |
15 | // macros
16 | public static final int _IOC_SIZEBITS = 14;
17 | public static final int _IOC_TYPEBITS = 8;
18 | public static final int _IOC_NRBITS = 8;
19 | public static final int _IOC_NRSHIFT = 0;
20 |
21 | public static int _IOC_TYPESHIFT() {
22 | return (_IOC_NRSHIFT + _IOC_NRBITS);
23 | }
24 |
25 | public static int _IOC_SIZESHIFT() {
26 | return (_IOC_TYPESHIFT() + _IOC_TYPEBITS);
27 | }
28 |
29 | public static int _IOC_SIZEMASK() {
30 | return ((1 << _IOC_SIZEBITS) - 1);
31 | }
32 |
33 | public static int _IOC_SIZE(int nr) {
34 | return (((nr) >> _IOC_SIZESHIFT()) & _IOC_SIZEMASK());
35 | }
36 |
37 | private IoctlFlags() {
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/JNRUtil.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import com.kenai.jffi.MemoryIO;
4 | import java.lang.reflect.Field;
5 | import java.nio.ByteBuffer;
6 | import jnr.ffi.Pointer;
7 | import jnr.ffi.StructLayout;
8 |
9 | final class JNRUtil {
10 | public static ByteBuffer toByteBuffer(Pointer pointer, long capacity) {
11 | if (capacity > Integer.MAX_VALUE)
12 | throw new IllegalArgumentException("Capacity too big: " + capacity);
13 | return MemoryIO.getInstance().newDirectByteBuffer(pointer.address(), (int) capacity);
14 | }
15 |
16 | public static String toString(StructLayout layout, Pointer p) {
17 | StringBuilder sb = new StringBuilder();
18 | Field[] fields = layout.getClass().getDeclaredFields();
19 | sb.append(layout.getClass().getSimpleName()).append(" { \n");
20 | final String fieldPrefix = " ";
21 | for (Field field : fields) {
22 | try {
23 | sb.append(fieldPrefix)
24 | .append(field.getType().getSimpleName()).append(' ').append(field.getName()).append(": ")
25 | .append(field.getType().getMethod("toString", Pointer.class).invoke(p))
26 | .append('\n');
27 | } catch (Throwable ex) {
28 | throw new RuntimeException(ex);
29 | }
30 | }
31 | sb.append("}\n");
32 |
33 | return sb.toString();
34 | }
35 |
36 | private JNRUtil() {
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/LibDl.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | public interface LibDl {
4 | public static final int RTLD_LAZY = 0x1;
5 | public static final int RTLD_NOW = 0x2;
6 | public static final int RTLD_GLOBAL = 0x100;
7 |
8 | public void dlopen(String file, int mode);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/LibFuse.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.types.size_t;
5 | import jnr.ffi.types.ssize_t;
6 |
7 | public interface LibFuse {
8 | static interface LibFuseProbe {
9 | }
10 |
11 | static interface LibMacFuseProbe extends LibFuseProbe {
12 | String macfuse_version();
13 | }
14 |
15 | StructFuseContext fuse_get_context();
16 |
17 | /**
18 | * Main function of FUSE.
19 | *
20 | * This function does the following:
21 | * - parses command line options (-d -s and -h)
22 | * - passes relevant mount options to the fuse_mount()
23 | * - installs signal handlers for INT, HUP, TERM and PIPE
24 | * - registers an exit handler to unmount the filesystem on program exit
25 | * - creates a fuse handle
26 | * - registers the operations
27 | * - calls either the single-threaded or the multi-threaded event loop
28 | *
29 | * @param argc the argument counter passed to the main() function
30 | * @param argv the argument vector passed to the main() function
31 | * @param op the file system operation
32 | * @param user_data user data supplied in the context during the init() method
33 | * @return 0 on success, nonzero on failure
34 | */
35 | int fuse_main_real(int argc, String[] argv, StructFuseOperations op, @size_t int size, Pointer user_data);
36 |
37 | @size_t long fuse_buf_size(Pointer bufv); // StructFuseBufvec
38 |
39 | @ssize_t long fuse_buf_copy(Pointer dstv, Pointer srcv, int flags); // StructFuseBufvec
40 |
41 | void fuse_pollhandle_destroy(Pointer ph); // StructFusePollhandle
42 |
43 | int fuse_notify_poll(Pointer ph); // StructFusePollhandle
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/LoggedFuseFilesystem.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.nio.file.Path;
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 | import jnr.ffi.Pointer;
8 |
9 | final class LoggedFuseFilesystem extends FuseFilesystem {
10 | private static interface LoggedMethod
10 | * Generic data buffer for I/O, extended attributes, etc... Data may
11 | * be supplied as a memory pointer or as a file descriptor
12 | */
13 | class StructFuseBuf {
14 | static final class Layout extends StructLayout {
15 | /**
16 | * Size of data in bytes
17 | */
18 | public final size_t size = new size_t();
19 |
20 | /**
21 | * Buffer flags
22 | */
23 | public final Enum
28 | * Used unless FUSE_BUF_IS_FD flag is set.
29 | */
30 | public final Pointer mem = new Pointer();
31 |
32 | /**
33 | * File descriptor
34 | *
35 | * Used if FUSE_BUF_IS_FD flag is set.
36 | */
37 | public final Signed32 fd = new Signed32();
38 |
39 | /**
40 | * File position
41 | *
42 | * Used if FUSE_BUF_FD_SEEK flag is set.
43 | */
44 | public final off_t pos = new off_t();
45 |
46 | private Layout(Runtime runtime) {
47 | super(runtime);
48 | }
49 | }
50 | static final Layout layout = new Layout(Runtime.getSystemRuntime());
51 |
52 | private final Pointer p;
53 |
54 | public StructFuseBuf(Pointer p) {
55 | this.p = p;
56 | }
57 |
58 | public final long size() {
59 | return layout.size.get(p);
60 | }
61 |
62 | public final FuseBufFlags flags() {
63 | return layout.flags.get(p);
64 | }
65 |
66 | public final int fd() {
67 | return layout.fd.get(p);
68 | }
69 |
70 | public final long pos() {
71 | return layout.pos.get(p);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseBufvec.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.*;
4 | import jnr.ffi.Runtime;
5 |
6 | /**
7 | * Data buffer vector
8 | *
9 | * An array of data buffers, each containing a memory pointer or a
10 | * file descriptor.
11 | *
12 | * Allocate dynamically to add more than one buffer.
13 | *
14 | * @author Sergey Tselovalnikov
15 | * @since 02.06.15
16 | */
17 | public class StructFuseBufvec {
18 | private static final class Layout extends StructLayout {
19 | public final size_t count = new size_t(); // Number of buffers in the array
20 | public final size_t idx = new size_t(); // Index of current buffer within the array
21 | public final size_t off = new size_t(); // Current offset within the current buffer
22 | public final StructFuseBuf.Layout buf = inner(StructFuseBuf.layout); // Array of buffers
23 |
24 | private Layout(Runtime runtime) {
25 | super(runtime);
26 | }
27 | }
28 |
29 | static final Layout layout = new Layout(Runtime.getSystemRuntime());
30 |
31 | private final Pointer p;
32 |
33 | public StructFuseBufvec(Pointer p) {
34 | this.p = p;
35 | }
36 |
37 | public final long cout() {
38 | return layout.count.get(p);
39 | }
40 |
41 | public final long idx() {
42 | return layout.idx.get(p);
43 | }
44 |
45 | public final long off() {
46 | return layout.off.get(p);
47 | }
48 |
49 | public final StructFuseBuf buf() {
50 | return new StructFuseBuf(p.getPointer(layout.buf.offset()));
51 | }
52 |
53 | /**
54 | * Similar to FUSE_BUFVEC_INIT macros
55 | */
56 | public static void init(StructFuseBufvec buf, long size) {
57 | layout.count.set(buf.p, 1);
58 | layout.idx.set(buf.p, 0);
59 | layout.off.set(buf.p, 0);
60 | layout.buf.size.set(buf.p, size);
61 | layout.buf.flags.set(buf.p, 0);
62 | layout.buf.mem.set(buf.p, 0);
63 | layout.buf.fd.set(buf.p, -1);
64 | layout.buf.pos.set(buf.p, 0);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseConnInfo.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.StructLayout;
6 | import jnr.ffi.TypeAlias;
7 |
8 | class StructFuseConnInfo {
9 | static final class Layout extends StructLayout {
10 | Layout(Runtime runtime) {
11 | super(runtime);
12 | }
13 | public final int32_t proto_major = new int32_t();
14 | public final int32_t proto_minor = new int32_t();
15 | public final int32_t async_read = new int32_t();
16 | public final int32_t max_write = new int32_t();
17 | public final int32_t max_readahead = new int32_t();
18 | public final int32_t enable = new int32_t();
19 | public final int32_t want = new int32_t();
20 | private final Padding reserved = new Padding(getRuntime().findType(TypeAlias.int32_t), 25);
21 | }
22 |
23 | static final Layout layout = new Layout(Runtime.getSystemRuntime());
24 | private final Pointer p;
25 |
26 | public StructFuseConnInfo(Pointer p) {
27 | this.p = p;
28 | }
29 |
30 | public final void setOptions(final boolean setVolumeName, final boolean caseInsensitive) {
31 | layout.want.set(p, (setVolumeName ? 0x2 : 0x0) | (caseInsensitive ? 0x1 : 0x0));
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseContext.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Runtime;
4 | import jnr.ffi.Struct;
5 |
6 | abstract class StructFuseContext extends Struct {
7 | public final Pointer fuse = new Pointer();
8 | public final uid_t uid = new uid_t();
9 | public final gid_t gid = new gid_t();
10 | public final pid_t pid = new pid_t();
11 | public final Pointer private_data = new Pointer();
12 |
13 | public StructFuseContext(Runtime runtime) {
14 | super(runtime);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseFileInfo.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.StructLayout;
6 |
7 | public class StructFuseFileInfo {
8 | private static final class Layout extends StructLayout {
9 |
10 | private Layout(Runtime runtime) {
11 | super(runtime);
12 | }
13 |
14 | public final Signed32 flags = new Signed32();
15 | public final SignedLong fh_old = new SignedLong();
16 | public final Signed32 writepage = new Signed32();
17 | public final Signed32 flags_bitfield = new Signed32();
18 | public final Unsigned64 fh = new Unsigned64();
19 | public final Unsigned64 lock_owner = new Unsigned64();
20 | }
21 | private static final Layout layout = new Layout(Runtime.getSystemRuntime());
22 |
23 | private final Pointer p;
24 | private final String path;
25 |
26 | StructFuseFileInfo(Pointer p, String path) {
27 | this.p = p;
28 | this.path = path;
29 | }
30 |
31 | @Override
32 | public final java.lang.String toString() {
33 | if (path != null)
34 | return path + "\n" + JNRUtil.toString(layout, p);
35 | return JNRUtil.toString(layout, p);
36 | }
37 |
38 | // FuseFileInfo(final FuseFileInfo fileinfo) {
39 | // this(null, fileinfo);
40 | // }
41 | public final boolean append() {
42 | return (layout.flags.intValue(p) & O_APPEND) != 0;
43 | }
44 |
45 | public final StructFuseFileInfo append(boolean append) {
46 | layout.flags.set(p, (layout.flags.get(p) & ~O_APPEND) | (append ? O_APPEND : 0));
47 | return this;
48 | }
49 |
50 | public final boolean create() {
51 | return (layout.flags.get(p) & O_CREAT) != 0;
52 | }
53 |
54 | public final StructFuseFileInfo create(boolean create) {
55 | layout.flags.set(p, (layout.flags.get(p) & ~O_CREAT) | (create ? O_CREAT : 0));
56 | return this;
57 | }
58 |
59 | public final boolean noblock() {
60 | return (layout.flags.get(p) & O_NONBLOCK) != 0;
61 | }
62 |
63 | public final StructFuseFileInfo noblock(boolean value) {
64 | layout.flags.set(p, (layout.flags.get(p) & ~O_NONBLOCK) | (value ? O_NONBLOCK : 0));
65 | return this;
66 | }
67 |
68 | public final boolean direct_io() {
69 | return (layout.flags_bitfield.get(p) & BIT_DIRECT_IO) != 0;
70 | }
71 |
72 | public final StructFuseFileInfo direct_io(boolean direct_io) {
73 | if (direct_io)
74 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) | BIT_DIRECT_IO);
75 | else
76 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) & ~BIT_DIRECT_IO);
77 | return this;
78 | }
79 |
80 | public final long fh() {
81 | return layout.fh.get(p);
82 | }
83 |
84 | public final StructFuseFileInfo fh(long fh) {
85 | layout.fh.set(p, fh);
86 | return this;
87 | }
88 |
89 | public final long fh_old() {
90 | return layout.fh_old.get(p);
91 | }
92 |
93 | public final StructFuseFileInfo fh_old(long fh_old) {
94 | layout.fh_old.set(p, fh_old);
95 | return this;
96 | }
97 |
98 | public final int flags() {
99 | return layout.flags.intValue(p);
100 | }
101 |
102 | public final StructFuseFileInfo flags(int flags) {
103 | layout.flags.set(p, flags);
104 | return this;
105 | }
106 |
107 | public final boolean flockrelease() {
108 | return (layout.flags_bitfield.get(p) & BIT_FLOCKRELEASE) != 0;
109 | }
110 |
111 | public final StructFuseFileInfo flockrelease(boolean flockrelease) {
112 | if (flockrelease)
113 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) | BIT_FLOCKRELEASE);
114 | else
115 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) & ~BIT_FLOCKRELEASE);
116 | return this;
117 | }
118 |
119 | public final boolean flush() {
120 | return (layout.flags_bitfield.get(p) & BIT_FLUSH) != 0;
121 | }
122 |
123 | public final StructFuseFileInfo flush(boolean flush) {
124 | if (flush)
125 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) | BIT_FLUSH);
126 | else
127 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) & ~BIT_FLUSH);
128 |
129 | return this;
130 | }
131 |
132 | public final boolean keep_cache() {
133 | return (layout.flags_bitfield.get(p) & BIT_KEEP_CACHE) != 0;
134 | }
135 |
136 | public final StructFuseFileInfo keep_cache(boolean keep_cache) {
137 | if (keep_cache)
138 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) | BIT_KEEP_CACHE);
139 | else
140 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) & ~BIT_KEEP_CACHE);
141 |
142 | return this;
143 | }
144 |
145 | public final long lock_owner() {
146 | return layout.lock_owner.longValue(p);
147 | }
148 |
149 | public final StructFuseFileInfo lock_owner(long lock_owner) {
150 | layout.lock_owner.set(p, lock_owner);
151 | return this;
152 | }
153 |
154 | public final boolean nonseekable() {
155 | return (layout.flags_bitfield.get(p) & BIT_NONSEEKABLE) != 0;
156 | }
157 |
158 | public final StructFuseFileInfo nonseekable(boolean nonseekable) {
159 | if (nonseekable)
160 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) | BIT_NONSEEKABLE);
161 | else
162 | layout.flags_bitfield.set(p, layout.flags_bitfield.get(p) & ~BIT_NONSEEKABLE);
163 |
164 | return this;
165 | }
166 |
167 | public final int openMode() {
168 | return layout.flags.intValue(p) & openMask;
169 | }
170 |
171 | public final StructFuseFileInfo openMode(int openMode) {
172 | layout.flags.set(p, (layout.flags.get(p) & ~openMask) | openMode);
173 | return this;
174 | }
175 |
176 | public final boolean truncate() {
177 | return (layout.flags.get(p) & O_TRUNC) != 0;
178 | }
179 |
180 | public final StructFuseFileInfo truncate(boolean truncate) {
181 | layout.flags.set(p, (layout.flags.get(p) & ~O_TRUNC) | (truncate ? O_TRUNC : 0));
182 | return this;
183 | }
184 |
185 | public final boolean writepage() {
186 | return layout.writepage.get(p) != 0;
187 | }
188 |
189 | public final StructFuseFileInfo writepage(boolean writepage) {
190 | layout.writepage.set(p, writepage ? 1 : 0);
191 | return this;
192 | }
193 |
194 | public static final int openMask = 03;
195 | public static final int O_RDONLY = 00;
196 | public static final int O_WRONLY = 01;
197 | public static final int O_RDWR = 02;
198 | public static final int O_CREAT = 0100;
199 | public static final int O_EXCL = 0200;
200 | public static final int O_NOCTTY = 0400;
201 | public static final int O_TRUNC = 01000;
202 | public static final int O_APPEND = 02000;
203 | public static final int O_NONBLOCK = 04000;
204 | public static final int O_NDELAY = O_NONBLOCK;
205 | public static final int O_SYNC = 010000;
206 | public static final int O_ASYNC = 020000;
207 | public static final int O_DIRECT = 040000;
208 | public static final int O_DIRECTORY = 0200000;
209 | public static final int O_NOFOLLOW = 0400000;
210 | public static final int O_NOATIME = 01000000;
211 | public static final int O_CLOEXEC = 02000000;
212 |
213 | private static final int BIT_DIRECT_IO = 1 << 0;
214 | private static final int BIT_KEEP_CACHE = 1 << 1;
215 | private static final int BIT_FLUSH = 1 << 2;
216 | private static final int BIT_NONSEEKABLE = 1 << 3;
217 | private static final int BIT_FLOCKRELEASE = 1 << 4;
218 | }
219 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseOperations.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.NativeType;
4 | import jnr.ffi.Struct;
5 | import co.paralleluniverse.fuse.StructFuseOperationsIfaces.*;
6 | import static jnr.ffi.provider.jffi.ClosureHelper.toNative;
7 |
8 | class StructFuseOperations extends Struct {
9 | private final Function<_getattr> getattr = function(_getattr.class);
10 | private final Function<_readlink> readlink = function(_readlink.class);
11 | private final Pointer getdir = new Pointer();
12 | private final Function<_mknod> mknod = function(_mknod.class);
13 | private final Function<_mkdir> mkdir = function(_mkdir.class);
14 | private final Function<_unlink> unlink = function(_unlink.class);
15 | private final Function<_rmdir> rmdir = function(_rmdir.class);
16 | private final Function<_symlink> symlink = function(_symlink.class);
17 | private final Function<_rename> rename = function(_rename.class);
18 | private final Function<_link> link = function(_link.class);
19 | private final Function<_chmod> chmod = function(_chmod.class);
20 | private final Function<_chown> chown = function(_chown.class);
21 | private final Function<_truncate> truncate = function(_truncate.class);
22 | private final Pointer utime = new Pointer();
23 | private final Function<_open> open = function(_open.class);
24 | private final Function<_read> read = function(_read.class);
25 | private final Function<_write> write = function(_write.class);
26 | private final Function<_statfs> statfs = function(_statfs.class);
27 | private final Function<_flush> flush = function(_flush.class);
28 | private final Function<_release> release = function(_release.class);
29 | private final Function<_fsync> fsync = function(_fsync.class);
30 | private final Pointer setxattr = new Pointer();
31 | private final Pointer getxattr = new Pointer();
32 | private final Function<_listxattr> listxattr = function(_listxattr.class);
33 | private final Function<_removexattr> removexattr = function(_removexattr.class);
34 | private final Function<_opendir> opendir = function(_opendir.class);
35 | private final Function<_readdir> readdir = function(_readdir.class);
36 | private final Function<_releasedir> releasedir = function(_releasedir.class);
37 | private final Function<_fsyncdir> fsyncdir = function(_fsyncdir.class);
38 | private final Function<_init> init = function(_init.class);
39 | private final Function<_destroy> destroy = function(_destroy.class);
40 | private final Function<_access> access = function(_access.class);
41 | private final Function<_create> create = function(_create.class);
42 | private final Function<_ftruncate> ftruncate = function(_ftruncate.class);
43 | private final Function<_fgetattr> fgetattr = function(_fgetattr.class);
44 | private final Function<_lock> lock = function(_lock.class);
45 | private final Function<_utimens> utimens = function(_utimens.class);
46 | private final Function<_bmap> bmap = function(_bmap.class);
47 | /**
48 | * Flag indicating that the filesystem can accept a NULL path
49 | * as the first argument for the following operations:
50 | *
51 | * read, write, flush, release, fsync, readdir, releasedir,
52 | * fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
53 | *
54 | * If this flag is set these operations continue to work on
55 | * unlinked files even if "-ohard_remove" option was specified.
56 | */
57 | private final Padding flag_nullpath_ok = new Padding(NativeType.UCHAR, 1);
58 | /**
59 | * Flag indicating that the path need not be calculated for
60 | * the following operations:
61 | *
62 | * read, write, flush, release, fsync, readdir, releasedir,
63 | * fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
64 | *
65 | * Closely related to flag_nullpath_ok, but if this flag is
66 | * set then the path will not be calculaged even if the file
67 | * wasn't unlinked. However the path can still be non-NULL if
68 | * it needs to be calculated for some other reason.
69 | */
70 | private final Padding flag_nopath = new Padding(NativeType.UCHAR, 1);
71 | /**
72 | * Flag indicating that the filesystem accepts special
73 | * UTIME_NOW and UTIME_OMIT values in its utimens operation.
74 | */
75 | private final Padding flag_utime_omit_ok = new Padding(NativeType.UCHAR, 1);
76 | /**
77 | * Reserved flags, don't set
78 | */
79 | private final Padding flag_reserved = new Padding(NativeType.UCHAR, 1);
80 | private final Function<_ioctl> ioctl = function(_ioctl.class);
81 | private final Function<_poll> poll = function(_poll.class);
82 | private final Pointer write_buf = new Pointer();
83 | private final Pointer read_buf = new Pointer();
84 | private final Function<_flock> flock = function(_flock.class);
85 | private final Function<_fallocate> fallocate = function(_fallocate.class);
86 |
87 | @SuppressWarnings("unused")
88 | public StructFuseOperations(jnr.ffi.Runtime runtime, FuseFilesystem fs) {
89 | super(runtime);
90 | final Filesystem filesystem = new Filesystem(fs);
91 | getattr.set(filesystem);
92 | readlink.set(filesystem);
93 | mknod.set(filesystem);
94 | mkdir.set(filesystem);
95 | unlink.set(filesystem);
96 | rmdir.set(filesystem);
97 | symlink.set(filesystem);
98 | rename.set(filesystem);
99 | link.set(filesystem);
100 | chmod.set(filesystem);
101 | chown.set(filesystem);
102 | truncate.set(filesystem);
103 | utime.set((jnr.ffi.Pointer) null);
104 | open.set(filesystem);
105 | read.set(filesystem);
106 | write.set(filesystem);
107 | statfs.set(filesystem);
108 | flush.set(filesystem);
109 | release.set(filesystem);
110 | fsync.set(filesystem);
111 | switch (Platform.platform()) {
112 | case MAC:
113 | case MAC_MACFUSE:
114 | setxattr.set(toNative(_setxattr_MAC.class, filesystem));
115 | getxattr.set(toNative(_getxattr_MAC.class, filesystem));
116 | break;
117 | default:
118 | setxattr.set(toNative(_setxattr_NOT_MAC.class, filesystem));
119 | getxattr.set(toNative(_getxattr_NOT_MAC.class, filesystem));
120 | }
121 | listxattr.set(filesystem);
122 | removexattr.set(filesystem);
123 | opendir.set(filesystem);
124 | readdir.set(filesystem);
125 | releasedir.set(filesystem);
126 | fsyncdir.set(filesystem);
127 | init.set(filesystem);
128 | destroy.set(filesystem);
129 | access.set(filesystem);
130 | create.set(filesystem);
131 | ftruncate.set(filesystem);
132 | fgetattr.set(filesystem);
133 | lock.set(filesystem);
134 | utimens.set(filesystem);
135 | bmap.set(filesystem);
136 | ioctl.set(filesystem);
137 | poll.set(filesystem);
138 | flock.set(filesystem);
139 | fallocate.set(filesystem);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFuseOperationsIfaces.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.annotations.Delegate;
5 | import jnr.ffi.annotations.In;
6 | import jnr.ffi.annotations.Out;
7 | import jnr.ffi.types.dev_t;
8 | import jnr.ffi.types.gid_t;
9 | import jnr.ffi.types.mode_t;
10 | import jnr.ffi.types.off_t;
11 | import jnr.ffi.types.size_t;
12 | import jnr.ffi.types.u_int32_t;
13 | import jnr.ffi.types.uid_t;
14 |
15 | final class StructFuseOperationsIfaces {
16 | public static interface _init { @Delegate void _init(Pointer conn); }
17 | public static interface _destroy { @Delegate void _destroy(); }
18 | public static interface _readlink { @Delegate int _readlink(String path, Pointer buffer, @size_t long size); }
19 | public static interface _mknod { @Delegate int _mknod(String path, @mode_t long mode, @dev_t long dev); }
20 | public static interface _mkdir { @Delegate int _mkdir(String path, @mode_t long mode); }
21 | public static interface _unlink { @Delegate int _unlink(String path); }
22 | public static interface _rmdir { @Delegate int _rmdir(String path); }
23 | public static interface _symlink { @Delegate int _symlink(String path, String target); }
24 | public static interface _rename { @Delegate int _rename(String path, String newName); }
25 | public static interface _link { @Delegate int _link(String path, String target); }
26 | public static interface _chmod { @Delegate int _chmod(String path, @mode_t long mode); }
27 | public static interface _chown { @Delegate int _chown(String path, @uid_t long uid, @gid_t long gid); }
28 | public static interface _truncate { @Delegate int _truncate(String path, @off_t long offset); }
29 | public static interface _open { @Delegate int _open(String path, Pointer info); }
30 | public static interface _read { @Delegate int _read(String path, @Out Pointer buffer, @size_t long size, @off_t long offset, Pointer info); }
31 | public static interface _write { @Delegate int _write(String path, @In Pointer buffer, @size_t long size, @off_t long offset, Pointer info); }
32 | public static interface _flush { @Delegate int _flush(String path, Pointer info); }
33 | public static interface _fsync { @Delegate int _fsync(String path, int datasync, @In Pointer info); }
34 | public static interface _release { @Delegate int _release(String path, Pointer info); }
35 | public static interface _opendir { @Delegate int _opendir(String path, Pointer info); }
36 | public static interface _readdir { @Delegate int _readdir(String path, Pointer buf, Pointer fillFunction, @off_t long offset, @In Pointer info); }
37 | public static interface _releasedir { @Delegate int _releasedir(String path, Pointer info); }
38 | public static interface _fsyncdir { @Delegate int _fsyncdir(String path, int datasync, @In Pointer info); }
39 | public static interface _access { @Delegate int _access(String path, int access); }
40 | public static interface _create { @Delegate int _create(String path, @mode_t long mode, Pointer info); }
41 | public static interface _ftruncate { @Delegate int _ftruncate(String path, @off_t long offset, @In Pointer info); }
42 | public static interface _utimens { @Delegate int _utimens(String path, Pointer timebuffer); }
43 | public static interface _bmap { @Delegate int _bmap(String path, Pointer info); }
44 | public static interface _statfs { @Delegate int _statfs(String path, @Out Pointer statsvfs); }
45 | public static interface _lock { @Delegate int _lock(String path, Pointer info, int cmd, Pointer flock); }
46 | public static interface _getattr { @Delegate int _getattr(String path, Pointer stat); }
47 | public static interface _fgetattr { @Delegate int _fgetattr(String path, Pointer stat, Pointer info); }
48 |
49 | public static interface _listxattr { @Delegate int _listxattr(String path, Pointer buffer, @size_t long size); }
50 | public static interface _removexattr { @Delegate int _removexattr(String path, String xattr); }
51 |
52 | public static interface _getxattr_MAC { @Delegate int _getxattr(String path, String xattr, Pointer buffer, @size_t long size, @u_int32_t long position); }
53 | public static interface _setxattr_MAC { @Delegate int _setxattr(String path, String xattr, Pointer value, @size_t long size, int flags, int position); }
54 |
55 | public static interface _getxattr_NOT_MAC { @Delegate int _getxattr(String path, String xattr, Pointer buffer, @size_t long size); }
56 | public static interface _setxattr_NOT_MAC { @Delegate int _setxattr(String path, String xattr, Pointer value, @size_t long size, int flags); }
57 |
58 | public static interface _ioctl { @Delegate void _ioctl(String path, int cmd, Pointer arg, Pointer fi, @u_int32_t long flags, Pointer data); }
59 | public static interface _poll { @Delegate void _poll(String path, Pointer fi, Pointer ph, Pointer reventsp); }
60 | public static interface _write_buf { @Delegate void _write_buf(String path, Pointer buf, @off_t long off, Pointer fi); }
61 | public static interface _read_buf { @Delegate void _read_buf(String path, Pointer bufp, @size_t long size, @off_t long off, Pointer fi); }
62 | public static interface _flock { @Delegate void _flock(String path, Pointer fi, int op); }
63 | public static interface _fallocate { @Delegate void _fallocate(String path, int mode, @off_t long off, @off_t long length, Pointer fi); }
64 |
65 | private StructFuseOperationsIfaces() {
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructFusePollHandle.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.StructLayout;
5 | import jnr.ffi.Runtime;
6 |
7 | /**
8 | * @see "fuse_lowlevel.c"
9 | *
10 | *
506 | *
513 | * Introduced in version 2.3
514 | *
515 | * @param path
516 | * @param filler
517 | * @return
518 | */
519 | protected abstract int readdir(String path, StructFuseFileInfo info, DirectoryFiller filler);
520 |
521 | /**
522 | * Release directory.
523 | *
11 | * struct fuse_pollhandle {
12 | * uint64_t kh;
13 | * struct fuse_chan *ch;
14 | * struct fuse_ll *f;
15 | * };
16 | *
17 | *
18 | * @author Sergey Tselovalnikov
19 | * @since 02.06.15
20 | */
21 | public class StructFusePollHandle {
22 | private static final class Layout extends StructLayout {
23 | public final Unsigned64 kh = new Unsigned64();
24 | // TODO struct fuse_chan *ch;
25 | public final Pointer ch = new Pointer();
26 | // TODO struct fuse_ll *f;
27 | public final Pointer f = new Pointer();
28 |
29 | protected Layout(Runtime runtime) {
30 | super(runtime);
31 | }
32 | }
33 |
34 | private static final Layout layout = new Layout(Runtime.getSystemRuntime());
35 | private final Pointer p;
36 |
37 | public StructFusePollHandle(Pointer p) {
38 | this.p = p;
39 | }
40 |
41 | public long kh() {
42 | return layout.kh.get(p);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructStat.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.StructLayout;
6 |
7 | public class StructStat {
8 | private static final class Layout extends StructLayout {
9 | public final dev_t st_dev; // Device.
10 | public final ino_t st_ino; // File serial number.
11 | public final mode_t st_mode; // File mode.
12 | public final nlink_t st_nlink; // Link count.
13 | public final uid_t st_uid; // User ID of the file's owner.
14 | public final gid_t st_gid; // Group ID of the file's group.
15 | public final dev_t st_rdev; //
16 | public final StructTimespec.Layout st_atime; // Time of last access.
17 | public final StructTimespec.Layout st_mtime; // Time of last modification.
18 | public final StructTimespec.Layout st_ctime; // Time of last status change.
19 | public final StructTimespec.Layout st_birthtime;
20 | public final off_t st_size; // Size of file, in bytes.
21 | public final blkcnt_t st_blocks; // Number 512-byte blocks allocated.
22 | public final blksize_t st_blksize; // Optimal block size for I/O.
23 | public final int32_t st_gen;
24 | public final int32_t st_lspare;
25 | public final int64_t st_qspare;
26 |
27 | private Layout(Runtime runtime) {
28 | super(runtime);
29 |
30 | switch (Platform.platform()) {
31 | case LINUX_X86_64: {
32 | this.st_dev = new dev_t();
33 | this.st_ino = new ino_t();
34 | this.st_nlink = new nlink_t();
35 | this.st_mode = new mode_t();
36 | this.st_uid = new uid_t();
37 | this.st_gid = new gid_t();
38 | int32_t __pad0 = new int32_t();
39 | this.st_rdev = new dev_t();
40 | this.st_size = new off_t();
41 | this.st_blksize = new blksize_t();
42 | this.st_blocks = new blkcnt_t();
43 | this.st_atime = inner(new StructTimespec.Layout(getRuntime()));
44 | this.st_mtime = inner(new StructTimespec.Layout(getRuntime()));
45 | this.st_ctime = inner(new StructTimespec.Layout(getRuntime()));
46 | this.st_birthtime = null;
47 | this.st_gen = null;
48 | this.st_lspare = null;
49 | this.st_qspare = null;
50 | break;
51 | }
52 | case LINUX_ARM:
53 | case LINUX_I686: {
54 | this.st_dev = new dev_t();
55 | int16_t __pad1 = new int16_t();
56 | u_int32_t __st_ino = new u_int32_t();
57 | this.st_mode = new mode_t();
58 | this.st_nlink = new nlink_t();
59 | this.st_uid = new uid_t();
60 | this.st_gid = new gid_t();
61 | this.st_rdev = new dev_t();
62 | int16_t __pad2 = new int16_t();
63 | this.st_size = new off_t();
64 | this.st_blksize = new blksize_t();
65 | this.st_blocks = new blkcnt_t();
66 | this.st_atime = inner(new StructTimespec.Layout(getRuntime()));
67 | this.st_mtime = inner(new StructTimespec.Layout(getRuntime()));
68 | this.st_ctime = inner(new StructTimespec.Layout(getRuntime()));
69 | this.st_ino = new ino_t();
70 | this.st_birthtime = null;
71 | this.st_gen = null;
72 | this.st_lspare = null;
73 | this.st_qspare = null;
74 | break;
75 | }
76 | case LINUX_PPC: {
77 | this.st_dev = new dev_t();
78 | this.st_ino = new ino_t();
79 | this.st_mode = new mode_t();
80 | this.st_nlink = new nlink_t();
81 | this.st_uid = new uid_t();
82 | this.st_gid = new gid_t();
83 | this.st_rdev = new dev_t();
84 | int16_t __pad0 = new int16_t();
85 | this.st_size = new off_t();
86 | this.st_blksize = new blksize_t();
87 | this.st_blocks = new blkcnt_t();
88 | this.st_atime = inner(new StructTimespec.Layout(getRuntime()));
89 | this.st_mtime = inner(new StructTimespec.Layout(getRuntime()));
90 | this.st_ctime = inner(new StructTimespec.Layout(getRuntime()));
91 | this.st_birthtime = null;
92 | this.st_gen = null;
93 | this.st_lspare = null;
94 | this.st_qspare = null;
95 | break;
96 | }
97 | case MAC: {
98 | this.st_dev = new dev_t();
99 | this.st_mode = new mode_t();
100 | this.st_nlink = new nlink_t();
101 | this.st_ino = new ino_t();
102 | this.st_uid = new uid_t();
103 | this.st_gid = new gid_t();
104 | this.st_rdev = new dev_t();
105 | this.st_atime = inner(new StructTimespec.Layout(getRuntime()));
106 | this.st_mtime = inner(new StructTimespec.Layout(getRuntime()));
107 | this.st_ctime = inner(new StructTimespec.Layout(getRuntime()));
108 | this.st_birthtime = inner(new StructTimespec.Layout(getRuntime()));
109 | this.st_size = new off_t();
110 | this.st_blocks = new blkcnt_t();
111 | this.st_blksize = new blksize_t();
112 | this.st_gen = new int32_t();
113 | this.st_lspare = new int32_t();
114 | this.st_qspare = new int64_t();
115 | break;
116 | }
117 | case FREEBSD:
118 | case MAC_MACFUSE: {
119 | this.st_dev = new dev_t();
120 | this.st_ino = new ino_t();
121 | this.st_mode = new mode_t();
122 | this.st_nlink = new nlink_t();
123 | this.st_uid = new uid_t();
124 | this.st_gid = new gid_t();
125 | this.st_rdev = new dev_t();
126 | this.st_atime = inner(new StructTimespec.Layout(getRuntime()));
127 | this.st_mtime = inner(new StructTimespec.Layout(getRuntime()));
128 | this.st_ctime = inner(new StructTimespec.Layout(getRuntime()));
129 | this.st_size = new off_t();
130 | this.st_blocks = new blkcnt_t();
131 | this.st_blksize = new blksize_t();
132 | this.st_birthtime = null;
133 | this.st_gen = null;
134 | this.st_lspare = null;
135 | this.st_qspare = null;
136 | break;
137 | }
138 | default:
139 | throw new AssertionError();
140 | }
141 | }
142 |
143 | }
144 |
145 | private static final Layout layout = new Layout(Runtime.getSystemRuntime());
146 |
147 | private final Pointer p;
148 | final String path;
149 |
150 | public StructStat(Pointer p, String path) {
151 | this.p = p;
152 | this.path = path;
153 | }
154 |
155 | private void setTime(StructTimespec.Layout layout, long sec, long nsec) {
156 | StructTimespec.set(layout, p, sec, nsec);
157 | }
158 |
159 | public StructStat atime(long sec) {
160 | return atime(sec, 0);
161 | }
162 |
163 | public StructStat atime(long sec, long nsec) {
164 | setTime(layout.st_atime, sec, nsec);
165 | return this;
166 | }
167 |
168 | public StructStat blksize(long blksize) {
169 | layout.st_blksize.set(p, blksize);
170 | return this;
171 | }
172 |
173 | public StructStat blocks(long blocks) {
174 | layout.st_blocks.set(p, blocks);
175 | return this;
176 | }
177 |
178 | public StructStat ctime(long sec) {
179 | return ctime(sec, 0);
180 | }
181 |
182 | public StructStat ctime(long sec, long nsec) {
183 | setTime(layout.st_ctime, sec, nsec);
184 | return this;
185 | }
186 |
187 | public StructStat dev(long dev) {
188 | layout.st_dev.set(p, dev);
189 | return this;
190 | }
191 |
192 | public StructStat gen(long gen) {
193 | if (layout.st_gen != null)
194 | layout.st_gen.set(p, gen);
195 | return this;
196 | }
197 |
198 | public StructStat gid(long gid) {
199 | layout.st_gid.set(p, gid);
200 | return this;
201 | }
202 |
203 | public StructStat ino(long ino) {
204 | layout.st_ino.set(p, ino);
205 | return this;
206 | }
207 |
208 | public StructStat lspare(long lspare) {
209 | if (layout.st_lspare != null)
210 | layout.st_lspare.set(p, lspare);
211 | return this;
212 | }
213 |
214 | public long mode() {
215 | return layout.st_mode.get(p);
216 | }
217 |
218 | public StructStat mode(long bits) {
219 | layout.st_mode.set(p, bits);
220 | return this;
221 | }
222 |
223 | public StructStat mtime(long sec) {
224 | return mtime(sec, 0);
225 | }
226 |
227 | public StructStat mtime(long sec, long nsec) {
228 | setTime(layout.st_mtime, sec, nsec);
229 | return this;
230 | }
231 |
232 | public StructStat nlink(long nlink) {
233 | layout.st_nlink.set(p, nlink);
234 | return this;
235 | }
236 |
237 | public StructStat qspare(long qspare) {
238 | if (layout.st_qspare != null)
239 | layout.st_qspare.set(p, qspare);
240 | return this;
241 | }
242 |
243 | public StructStat rdev(long rdev) {
244 | layout.st_rdev.set(p, rdev);
245 | return this;
246 | }
247 |
248 | public StructStat setAllTimes(long sec, long nsec) {
249 | return setTimes(sec, nsec, sec, nsec, sec, nsec);
250 | }
251 |
252 | public StructStat setAllTimesMillis(long millis) {
253 | final long sec = millis / 1000L;
254 | final long nsec = (millis % 1000L) * 1000000L;
255 | return setAllTimes(sec, nsec);
256 | }
257 |
258 | public StructStat setAllTimesSec(long sec) {
259 | return setAllTimesSec(sec, sec, sec);
260 | }
261 |
262 | public StructStat setAllTimesSec(long atime, long mtime, long ctime) {
263 | return setAllTimesSec(atime, mtime, ctime, ctime);
264 | }
265 |
266 | public StructStat setAllTimesSec(long atime, long mtime, long ctime, long birthtime) {
267 | return setTimes(atime, 0, mtime, 0, ctime, 0);
268 | }
269 |
270 | public StructStat setTimes(long atime_sec, long atime_nsec, long mtime_sec,
271 | long mtime_nsec, long ctime_sec, long ctime_nsec) {
272 | return setTimes(atime_sec, atime_nsec, mtime_sec, mtime_nsec, ctime_sec, ctime_nsec, ctime_sec, ctime_nsec);
273 | }
274 |
275 | public StructStat setTimes(long atime_sec, long atime_nsec, long mtime_sec, long mtime_nsec,
276 | long ctime_sec, long ctime_nsec, long birthtime_sec, long birthtime_nsec) {
277 | setTime(layout.st_atime, atime_sec, atime_nsec);
278 | setTime(layout.st_mtime, mtime_sec, mtime_nsec);
279 | setTime(layout.st_ctime, ctime_sec, ctime_nsec);
280 | if (layout.st_birthtime != null)
281 | setTime(layout.st_birthtime, birthtime_sec, birthtime_nsec);
282 | return this;
283 | }
284 |
285 | public StructStat size(long size) {
286 | layout.st_size.set(p, size);
287 | return this;
288 | }
289 |
290 | public StructStat uid(long uid) {
291 | layout.st_uid.set(p, uid);
292 | return this;
293 | }
294 |
295 | @Override
296 | public java.lang.String toString() {
297 | if (path != null)
298 | return path + "\n" + JNRUtil.toString(layout, p);
299 | return JNRUtil.toString(layout, p);
300 | }
301 | }
302 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructStatvfs.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.StructLayout;
6 | import jnr.ffi.Platform.CPU;
7 |
8 | public class StructStatvfs {
9 | /* Definitions for the flag in `f_flag'.*/
10 | public static final int ST_RDONLY = 1; // Mount read-only.
11 | public static final int ST_NOSUID = 2; // Ignore suid and sgid bits.
12 | public static final int ST_NODEV = 4; // Disallow access to device special files.
13 | public static final int ST_NOEXEC = 8; // Disallow program execution.
14 | public static final int ST_SYNCHRONOUS = 16; // Writes are synced at once.
15 | public static final int ST_MANDLOCK = 64; // Allow mandatory locks on an FS.
16 | public static final int ST_WRITE = 128; // Write on file/directory/symlink.
17 | public static final int ST_APPEND = 256; // Append-only file.
18 | public static final int ST_IMMUTABLE = 512; // Immutable file.
19 | public static final int ST_NOATIME = 1024; // Do not update access times.
20 | public static final int ST_NODIRATIME = 2048;// Do not update directory access times.
21 | public static final int ST_RELATIME = 4096; // Update atime relative to mtime/ctime.
22 |
23 | private static final class Layout extends StructLayout {
24 | public final SignedLong f_bsize; // file system block size
25 | public final SignedLong f_frsize; // fragment size
26 | public final blkcnt_t f_blocks; // size of fs in f_frsize units
27 | public final blkcnt_t f_bfree; // # free blocks
28 | public final blkcnt_t f_bavail; // # free blocks for non-root
29 | public final fsfilcnt_t f_files; // # inodes
30 | public final fsfilcnt_t f_ffree; // # free inodes
31 | public final fsfilcnt_t f_favail; // # free inodes for non-root
32 | public final Signed32 f_unused;
33 | public final UnsignedLong f_flag; // mount flags
34 | public final UnsignedLong f_namemax;// maximum filename length
35 | public final Signed32[] __f_spare;
36 |
37 | private Layout(Runtime runtime) {
38 | super(runtime);
39 |
40 | switch (Platform.platform()) {
41 | case FREEBSD: {
42 | this.f_bavail = new blkcnt_t();
43 | this.f_bfree = new blkcnt_t();
44 | this.f_blocks = new blkcnt_t();
45 | this.f_ffree = new fsfilcnt_t();
46 | this.f_favail = new fsfilcnt_t();
47 | this.f_files = new fsfilcnt_t();
48 | this.f_bsize = new SignedLong();
49 | SignedLong __pad0 = new SignedLong();
50 | this.f_frsize = new SignedLong();
51 | break;
52 | }
53 | default: {
54 | this.f_bsize = new SignedLong();
55 | this.f_frsize = new SignedLong();
56 | this.f_blocks = new blkcnt_t();
57 | this.f_bfree = new blkcnt_t();
58 | this.f_bavail = new blkcnt_t();
59 | this.f_files = new fsfilcnt_t();
60 | this.f_ffree = new fsfilcnt_t();
61 | this.f_favail = new fsfilcnt_t();
62 | }
63 |
64 | }
65 | final boolean is32bit = (jnr.ffi.Platform.getNativePlatform().getCPU() == CPU.I386 || jnr.ffi.Platform.getNativePlatform().getCPU() == CPU.ARM);
66 | this.f_unused = is32bit ? new Signed32() : null;
67 | this.f_flag = new UnsignedLong();
68 | this.f_namemax = new UnsignedLong();
69 | this.__f_spare = array(new Signed32[6]);
70 | }
71 | }
72 |
73 | private static final Layout layout = new Layout(Runtime.getSystemRuntime());
74 | private final Pointer p;
75 | private final String path;
76 |
77 | public StructStatvfs(Pointer p, String path) {
78 | this.p = p;
79 | this.path = path;
80 | }
81 |
82 | public final long bavail() {
83 | return layout.f_bavail.get(p);
84 | }
85 |
86 | public final StructStatvfs bavail(long f_bavail) {
87 | layout.f_bavail.set(p, f_bavail);
88 | return this;
89 | }
90 |
91 | public final long bfree() {
92 | return layout.f_bfree.get(p);
93 | }
94 |
95 | public final StructStatvfs bfree(long f_bfree) {
96 | layout.f_bfree.set(p, f_bfree);
97 | return this;
98 | }
99 |
100 | public final long blocks() {
101 | return layout.f_blocks.get(p);
102 | }
103 |
104 | public final StructStatvfs blocks(long f_blocks) {
105 | layout.f_blocks.set(p, f_blocks);
106 | return this;
107 | }
108 |
109 | public final long bsize() {
110 | return layout.f_bsize.get(p);
111 | }
112 |
113 | public final StructStatvfs bsize(long f_bsize) {
114 | layout.f_bsize.set(p, f_bsize);
115 | return this;
116 | }
117 |
118 | public final long favail() {
119 | return layout.f_favail.get(p);
120 | }
121 |
122 | public final StructStatvfs favail(long f_favail) {
123 | layout.f_favail.set(p, f_favail);
124 | return this;
125 | }
126 |
127 | public final long ffree() {
128 | return layout.f_ffree.get(p);
129 | }
130 |
131 | public final StructStatvfs ffree(long f_ffree) {
132 | layout.f_ffree.set(p, f_ffree);
133 | return this;
134 | }
135 |
136 | public final long files() {
137 | return layout.f_files.get(p);
138 | }
139 |
140 | public final StructStatvfs files(long f_files) {
141 | layout.f_files.set(p, f_files);
142 | return this;
143 | }
144 |
145 | public final long frsize() {
146 | return layout.f_frsize.get(p);
147 | }
148 |
149 | public final StructStatvfs frsize(long f_frsize) {
150 | layout.f_frsize.set(p, f_frsize);
151 | return this;
152 | }
153 |
154 | public final long flags() {
155 | return layout.f_flag.get(p);
156 | }
157 |
158 | public final StructStatvfs flags(long f_flags) {
159 | layout.f_flag.set(p, f_flags);
160 | return this;
161 | }
162 |
163 | public final StructStatvfs set(long blockSize, long fragmentSize, long freeBlocks, long availBlocks, long totalBlocks,
164 | long freeFiles, long availFiles, long totalFiles) {
165 | return setSizes(blockSize, fragmentSize).setBlockInfo(freeBlocks, availBlocks, totalBlocks).setFileInfo(freeFiles,
166 | availFiles, totalFiles);
167 | }
168 |
169 | public final StructStatvfs setBlockInfo(long freeBlocks, long availBlocks, long totalBlocks) {
170 | return bfree(freeBlocks).bavail(availBlocks).blocks(totalBlocks);
171 | }
172 |
173 | public final StructStatvfs setFileInfo(long freeFiles, long availFiles, long totalFiles) {
174 | return ffree(freeFiles).favail(availFiles).files(totalFiles);
175 | }
176 |
177 | public final StructStatvfs setSizes(long blockSize, long fragmentSize) {
178 | return bsize(blockSize).frsize(fragmentSize);
179 | }
180 |
181 | @Override
182 | public final java.lang.String toString() {
183 | if (path != null)
184 | return path + "\n" + JNRUtil.toString(layout, p);
185 | return JNRUtil.toString(layout, p);
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructTimeBuffer.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.StructLayout;
6 |
7 | public final class StructTimeBuffer {
8 | static final class Layout extends StructLayout {
9 | Layout(Runtime runtime) {
10 | super(runtime);
11 | }
12 | public final StructTimespec.Layout actime = inner(new StructTimespec.Layout(getRuntime()));
13 | public final StructTimespec.Layout modtime = inner(new StructTimespec.Layout(getRuntime()));
14 | }
15 | static final Layout layout = new Layout(Runtime.getSystemRuntime());
16 |
17 | private final Pointer p;
18 |
19 | StructTimeBuffer(Pointer p) {
20 | this.p = p;
21 | }
22 |
23 | public long ac_nsec() {
24 | return layout.actime.tv_nsec.get(p);
25 | }
26 |
27 | public long ac_sec() {
28 | return layout.actime.tv_sec.get(p);
29 | }
30 |
31 | public StructTimeBuffer ac_set(double time) {
32 | StructTimespec.set(layout.actime, p, time);
33 | return this;
34 | }
35 |
36 | public StructTimeBuffer ac_set(long sec, long nsec) {
37 | StructTimespec.set(layout.actime, p, sec, nsec);
38 | return this;
39 | }
40 |
41 | public StructTimeBuffer ac_setMillis(long millis) {
42 | StructTimespec.setMillis(layout.actime, p, millis);
43 | return this;
44 | }
45 |
46 | public StructTimeBuffer ac_setSeconds(long seconds) {
47 | StructTimespec.setSeconds(layout.actime, p, seconds);
48 | return this;
49 | }
50 |
51 | public long mod_nsec() {
52 | return layout.modtime.tv_nsec.get(p);
53 | }
54 |
55 | public long mod_sec() {
56 | return layout.modtime.tv_sec.get(p);
57 | }
58 |
59 | public final StructTimeBuffer mod_set(double time) {
60 | StructTimespec.set(layout.modtime, p, time);
61 | return this;
62 | }
63 |
64 | public StructTimeBuffer mod_set(long sec, final long nsec) {
65 | StructTimespec.set(layout.modtime, p, sec, nsec);
66 | return this;
67 | }
68 |
69 | public StructTimeBuffer mod_setMillis(long millis) {
70 | StructTimespec.setMillis(layout.modtime, p, millis);
71 | return this;
72 | }
73 |
74 | public StructTimeBuffer mod_setSeconds(long seconds) {
75 | StructTimespec.setSeconds(layout.modtime, p, seconds);
76 | return this;
77 | }
78 |
79 | public StructTimeBuffer both_set(double time) {
80 | ac_set(time);
81 | mod_set(time);
82 | return this;
83 | }
84 |
85 | public StructTimeBuffer both_set(long sec, long nsec) {
86 | ac_set(sec, nsec);
87 | mod_set(sec, nsec);
88 | return this;
89 | }
90 |
91 | public StructTimeBuffer both_setMillis(long millis) {
92 | ac_setMillis(millis);
93 | mod_setMillis(millis);
94 | return this;
95 | }
96 |
97 | public StructTimeBuffer both_setSeconds(long seconds) {
98 | ac_setSeconds(seconds);
99 | mod_setSeconds(seconds);
100 | return this;
101 | }
102 |
103 | @Override
104 | public java.lang.String toString() {
105 | return layout.toString();
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/StructTimespec.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import jnr.ffi.Pointer;
4 | import jnr.ffi.Runtime;
5 | import jnr.ffi.Struct;
6 | import jnr.ffi.StructLayout;
7 |
8 | final class StructTimespec {
9 | static final class Layout extends StructLayout {
10 | Layout(Runtime runtime) {
11 | super(runtime);
12 | }
13 | public final SignedLong tv_sec = new SignedLong();
14 | public final SignedLong tv_nsec = new SignedLong();
15 | }
16 | static final Layout layout = new Layout(Runtime.getSystemRuntime());
17 |
18 | private final Pointer p;
19 |
20 | public StructTimespec(Pointer p) {
21 | this.p = p;
22 | }
23 |
24 | public long nsec() {
25 | return layout.tv_nsec.longValue(p);
26 | }
27 |
28 | public long sec() {
29 | return layout.tv_sec.longValue(p);
30 | }
31 |
32 | public void set(double time) {
33 | set(layout, p, time);
34 | }
35 |
36 | public void set(long sec, long nsec) {
37 | set(layout, p, sec, nsec);
38 | }
39 |
40 | public void setMillis(long millis) {
41 | set(millis / 1000L, (millis % 1000L) * 1000000L);
42 | }
43 |
44 | public void setSeconds(long seconds) {
45 | set(seconds);
46 | }
47 |
48 | static void set(StructTimespec.Layout layout, Pointer p, double time) {
49 | set(layout, p, (long) time, (long) (time * 1000000000d));
50 | }
51 |
52 | static void set(StructTimespec.Layout layout, Pointer p, long sec, long nsec) {
53 | layout.tv_sec.set(p, sec);
54 | layout.tv_nsec.set(p, nsec);
55 | }
56 |
57 | static void setMillis(StructTimespec.Layout layout, Pointer p, long millis) {
58 | set(layout, p, millis / 1000L, (millis % 1000L) * 1000000L);
59 | }
60 |
61 | static void setSeconds(StructTimespec.Layout layout, Pointer p, long seconds) {
62 | set(layout, p, seconds);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/TypeMode.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | public class TypeMode {
4 | public static final int S_IFIFO = 0010000; // named pipe (fifo)
5 | public static final int S_IFCHR = 0020000; // character special
6 | public static final int S_IFDIR = 0040000; // directory
7 | public static final int S_IFBLK = 0060000; // block special
8 | public static final int S_IFREG = 0100000; // regular
9 | public static final int S_IFLNK = 0120000; // symbolic link
10 | public static final int S_IFSOCK = 0140000; // socket
11 | public static final int S_IFMT = 0170000; // file mask for type checks
12 | public static final int S_ISUID = 0004000; // set user id on execution
13 | public static final int S_ISGID = 0002000; // set group id on execution
14 | public static final int S_ISVTX = 0001000; // save swapped text even after use
15 | public static final int S_IRUSR = 0000400; // read permission, owner
16 | public static final int S_IWUSR = 0000200; // write permission, owner
17 | public static final int S_IXUSR = 0000100; // execute/search permission, owner
18 | public static final int S_IRGRP = 0000040; // read permission, group
19 | public static final int S_IWGRP = 0000020; // write permission, group
20 | public static final int S_IXGRP = 0000010; // execute/search permission, group
21 | public static final int S_IROTH = 0000004; // read permission, other
22 | public static final int S_IWOTH = 0000002; // write permission, other
23 | public static final int S_IXOTH = 0000001; // execute permission, other
24 |
25 | public static final int ALL_READ = S_IRUSR | S_IRGRP | S_IROTH;
26 | public static final int ALL_WRITE = S_IWUSR | S_IWGRP | S_IWOTH;
27 | public static final int S_IXUGO = S_IXUSR | S_IXGRP | S_IXOTH;
28 |
29 | public static boolean S_ISTYPE(int mode, int mask) {
30 | return (mode & S_IFMT) == mask;
31 | }
32 |
33 | public static boolean S_ISDIR(int mode) {
34 | return S_ISTYPE(mode, S_IFDIR);
35 | }
36 |
37 | public static boolean S_ISCHR(int mode) {
38 | return S_ISTYPE(mode, S_IFCHR);
39 | }
40 |
41 | public static boolean S_ISBLK(int mode) {
42 | return S_ISTYPE(mode, S_IFBLK);
43 | }
44 |
45 | public static boolean S_ISREG(int mode) {
46 | return S_ISTYPE(mode, S_IFREG);
47 | }
48 |
49 | public static boolean S_ISFIFO(int mode) {
50 | return S_ISTYPE(mode, S_IFIFO);
51 | }
52 |
53 | public static boolean S_ISLNK(int mode) {
54 | return S_ISTYPE(mode, S_IFLNK);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/XAttrConstants.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | /**
4 | * The following constants should be used for the fifth parameter of
5 | * `*setxattr'.
6 | *
7 | * @author Sergey Tselovalnikov
8 | * @since 05.06.15
9 | */
10 | final class XAttrConstants {
11 | public static final int XATTR_CREATE = 1; /* set value, fail if attr already exists. */
12 | public static final int XATTR_REPLACE = 2; /* set value, fail if attr does not exist. */
13 |
14 | private XAttrConstants() {
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/XattrFiller.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.Arrays;
5 |
6 | public final class XattrFiller {
7 | private final ByteBuffer buffer;
8 | private final long maxSize;
9 | private final int position;
10 | private byte[] value = null;
11 | private boolean isSet = false;
12 |
13 | XattrFiller(ByteBuffer buffer, long size, int position) {
14 | this.buffer = buffer;
15 | maxSize = size;
16 | this.position = position;
17 | }
18 |
19 | long getSize() {
20 | return value == null ? 0 : value.length;
21 | }
22 |
23 | public final void set(byte[] value) {
24 | if (buffer != null && value != null) {
25 | if (isSet)
26 | throw new IllegalStateException("Cannot set the xattr twice.");
27 |
28 | isSet = true;
29 | if (value.length > position + maxSize)
30 | value = Arrays.copyOf(value, position + (int) maxSize);
31 |
32 | buffer.put(value, position, value.length);
33 | }
34 | this.value = value;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/co/paralleluniverse/fuse/XattrListFiller.java:
--------------------------------------------------------------------------------
1 | package co.paralleluniverse.fuse;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.Arrays;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | public final class XattrListFiller {
9 | private final ByteBuffer buffer;
10 | private final long maxSize;
11 | private long currentSize = 0;
12 | private final Set