Difference between symbolic links and shortcuts - java

What is the difference between symbolic links and shortcuts?
As I was reading Oracle's Documentation on java.nio.file package, there I came to know about symbolic links. At first, I thought they are talking about shortcuts because at first they both appeared the same to me. But later I realised that I am kind of assuming this without a proof so i googled it and found some links about the differences between the two. But I couldn't get a clear view of what these actually are as the answers were not that good. I hope I can get an explanation here!

A symbolic link is a special file which references another path on disk. If an application opens this file (or includes it in a path), the operating system will silently follow the link.
For instance, assume you have a symbolic link l which points to a directory d with a file file in it. Observe:
$ ls d/
file
$ ls l/
file
$ touch l/file2 # Create a new file in the path under l
$ ls d/
file file2
Symbolic links (symlinks) are a feature of the filesystem part of the operating system. They can be used by any application; applications that do want to treat symlinks differently (such as backup programs, which must not blindly follow symlinks lest the number of files becomes infinite) need to take special precaution to do so.
In contrast, a shortcut is a regular file which is rendered differently by the user interface(UI). A shortcut file also contains the desired target path, but can contain additional information, such as an icon, command-line arguments, instructions to the UI to run the destination as another user, categorization of the destination, translation information and the like. For an application, a shortcut is a regular file whose contents describe the shortcut. For instance, if you open a .desktop file with an editor, you'll see information like
Icon=libreoffice-calc
Exec=libreoffice --calc %U
GenericName=Spreadsheet
GenericName[da]=Regneark
You should generally use shortcuts if you want to add an entry to the user interface (typically the graphical parts). Shortcuts allow you extended customization - for instance, Danish users will see Regneark, and English users Spreadsheet in the above example.
If, on the other hand, you want the alias to be visible to all applications, go for a symlink instead. For instance, you could have a legacy name of a file that some applications expect, or one application that can do multiple things, or the current version of a project directory.
Note that some systems do not support symlinks, and some have no use for shortcuts. If there is no graphical interface present (for instance a home router without a monitor attached), shortcuts would not be useful. On the other hand, symlinks require support by the filesystem (FAT has none) as well as the operating system (DOS/old versions of Windows lack support).

Related

Is there a way to write file atomically in Java on Linux?

Linux Api has O_TMPFILE flag to be specified with open system call creating unnamed temporary file which cannot be opened by any path. So we can use this to write data to the file "atmoically" and the linkat the given file to the real path. According to the open man page it can be implemented as simple as
char path[1000];
int fd = open("/tmp", O_TMPFILE | O_WRONLY, S_IWUSR);
write(fd, "123456", sizeof("123456"));
sprintf(path, "/proc/self/fd/%d", fd);
linkat(AT_FDCWD, path, AT_FDCWD, "/tmp/1111111", AT_SYMLINK_FOLLOW);
Is there a Java alternative (probably non crossplatform) to do atomic write to a file without writing Linux-specific JNI function? Files.createTempFile does completely different thing.
By atomic write I mean that either it cannot be opened and be read from or it contains all the data required to be writted.
I don't believe Java has an API for this, and it seems to depend on both the OS and filesystem having support, so JNI might be the only way, and even then only on Linux.
I did a quick search for what Cygwin does, seems to be a bit of a hack just to make software work, creating a file with a random name then excluding it only from their own directory listing.
I believe the closest you can get in plain Java is to create a file in some other location (kinda like a /proc/self/fd/... equivalent), and then when you are done writing it, either move it or symbolic link it from the final location. To move the file, you want it on the same filesystem partition so the file contents don't actually need to be copied. Programs watching for the file in say /tmp/ wouldn't see it until the move or sym link creation.
You could possibly play around with user accounts and filesystem permissions to ensure that no other (non SYSTEM/root) program can see the file initially even if they tried to look wherever you hid it.

how can lock a windows file or a folder using java , like locker apps?

Locker Apps is a Folder Lock application, how can I lock files or folders on Windows using Java?
Here is what I tried:
File file = new File(file path);
file.setExecutable(false);
file.setWritable(false);
file.setReadable(false);
But only file.setwritable(false); works - I can't rewrite the file. Other methods do nothing to the file.
These methods are simply setting the file system access permissions for the file. In order to understand them, you need to understand the OS / file system access control rules.
For example, on Linux file.setWriteable(false) is equivalent to running chmod u-w file to clear the "owner write" access bit:
Note:
chmod can only change any permissions on the file if you are the owner of the file, or if you are running as root.
The owner write permission means that owner (or root) can execute the file, or not. If you are neither, then that permission does not affect you.
So there are at least two possible reasons why setWriteable may not be "working".
You are not executing your Java program as the file owner or root. In that case, setWriteable will return false. But note that you don't check the result!
You are not trying to write the file as the file's owner. In that case, the access but you just removed (in Java) does not affect you.
Solutions:
There is a newer / better API for setting file permissions in Java in the java.nio.file.Files class:
public static Path setPosixFilePermissions(
Path path,
Set<PosixFilePermission> perms)
throws IOException
This allows you to set / clear all avail POSIX file permissions in one call, and it with throw an exception if it can't for any reason.
Many file systems also support more sophisticated ACL mechanisms ....
HOWEVER
None of this is equivalent to the functionality provided by a File Locker app. Why? Because any attempt to block file access via file permissions or ACLs can trivially be reversed by someone with root access. Provided you know what it is doing at a technical level.
What the Windows "Folder Lock" app can apparently encrypt files or hide them. Files can be marked as hidden natively in Java 7 and later by setting the "dos:hidden" attribute; see https://stackoverflow.com/a/42816082/139985. It is probably also using permissions and ACLs to restrict access, that can be doing on Java too. It may also be doing other things. The documentation says (unhelpfully!):
Once the files are locked, it becomes protected in every possible way and can only be accessed through the Folder Lock security application.
That sounds like marketing rather than truth, and is almost certainly untrue. However figuring out what the app is actually doing, would require me to get a Windows machine, download and install the software, and then violate the license by attempting to reverse engineer it.
But note that the above method for "hiding" is Windows specific. On Linux / Mac OS you "hide" a file from some commands by making the first character of the file name a dot (".") character.

What is a "regular file" in Java?

The class BasicFileAttributes, for examining the properties of a file in the file system, has the method isRegularFile(). Unfortunately, the Javadoc description is rather lacking:
Tells whether the file is a regular file with opaque content.
What does this mean? What exactly is a regular file with opaque content? I can tell from the other methods in the class that it's not a directory or symbolic link, so I'm inclined to think that it's everything else. However, there apparently is some type of "irregular file" because a method exists called isOther(), which returns true if it's not a directory, symbolic link, or "regular file".
So what exactly is an regular file in Java?
For example in UNIX, a regular file is one that is not special in some way. Special files include symbolic links and directories. A regular file is a sequence of bytes stored permanently in a file system.
Read this answer # UNIX & Linux stackexchange: What is a regular file?
I figure rm -i is an alias, possibly rm -i. The "regular" part doesn't
mean anything in particular, it only means that it's not a pipe,
device, socket or anything other "special".
it means the file is not a symlink, pipe, rand, null, cpu, etc.
Perhaps you have heard the linux philosophy everything is a text. This
isn't literally true, but it suggests a dominant operational context
where string processing tools can be applied to filesystem elements
directly. In this case, it means that in a more literal fashion. To
see the detection step in isolation, try the command file, as in file
/etc/passwd or file /dev/null.
From Files Reference - AIX IBM
A file is a collection of data that can be read from or written to. A file can be a program you create, text you write, data you acquire, or a device you use. Commands, printers, terminals, and application programs are all stored in files. This allows users to access diverse elements of the system in a uniform way and gives the operating system great flexibility. No format is implied when a file is created.
There are three types of files
Regular - Stores data (text, binary, and executable).
Directory - Contains information used to access other files.
Special - Defines a FIFO (first-in, first-out) file or a physical device.
Regular files are the most common. When a word processing program is used to create a document, both the program and the document are contained in regular files.
Regular files contain either text or binary information. Text files are readable by the user. Binary files are readable by the computer. Binary files can be executable files that instruct the system to accomplish a job. Commands, shell scripts, and other programs are stored in executable files.
Directories contain information the system needs to access all types of files, but they do not contain the actual file data. As a result, directories occupy less space than a regular file and give the file-system structure flexibility and depth. Each directory entry represents either a file or subdirectory and contains the name of a file and the file's i-node (index node reference) number. The i-node number represents the unique i-node that describes the location of the data associated with the file. Directories are created and controlled by a separate set of commands. See "Directories" in Operating system and device management for more information.
Special files define devices for the system or temporary files created by processes. There are three basic types of special files: FIFO (first-in, first-out), block, and character. FIFO files are also called pipes. Pipes are created by one process to temporarily allow communication with another process. These files cease to exist when the first process finishes. Block and character files define devices.
All this above is from the first link. I've checked in many other sources regarding Operational Systems differences and it seems this one is the most common definition on all sources i've found.
I am not an expert on this but at the first look BasicFileAttributes is not a class but an interface. So whatever a regular file is depends on the implementation of this interface. I can see that there is e.g. the class WindowsFileAttributs that implements this interface.
If you have a look at the OpenJDK version of this class you will find that it is
!isSymbolicLink() && !isDirectory() && !isOther();
Get all other information from the code ;-)

Create Windows Symbolic Link with Java (equivalent to MKLINK)

Could anyone please tell me how to make a symbolic link (in the same way MKLINK does) and/or remove a symbolic link with Java. I have found solutions that use Java as a wrapper and use a Windows native program to accomplish this, but I really want a pure Java solution. Thank you in advance!
Since Java 7 you can do this easily using the NIO package.
Path target = Paths.get("target");
Path link = Paths.get("link");
Files.createDirectory(target);
Files.createSymbolicLink(link, target);
Do remember that you do need the correct privileges for this. In my unit test I had to run eclipse as an administrator to make it work (same as that I couldn't create a link from a normal cmd.exe)
As far as I know window does not have real symbolic links like Unix-like system do.
However Windows has the following relevant tools:
You can map network drive, i.e. attach drive letter to specified network path. You can definitely do this using WMI. To access WMI from java take a look on tools like JaWin, Jinterop, Jintegra or write WMI script in JScript o VBScript and execute is from Java.
You can use command subst that assigns letter to local file system path. This is the closest approach to Unix soft link.
You can create desktop shortcut. Create one manually and take a look on it. Shortcut is actually regular text file (as far as I remember in INI format). You can easily create one using any language you want including java. This is not soft link but it is clickable.

What is the best way to get OS specific information in Java?

Specifically getting on Windows the "..\Documents & Settings\All Users, basicaly any path that needs the front end to be dynamically derived based on the OS your software is running on. (Now I need the answer to this)
the current users My Documents dirctory (okay this has been answered)
and basicaly any path that needs the front end to be dynamically derived based on the OS your software is running on.
My docs would probably best be handled by accessing:
System.getProperty("user.home");
Look up the docs on System.getProperty.
Any information you can get about the user's environment can be fetched from
System.getProperty("...");
For a list of what you can get, take a look here.
I don't think you'll be able to get the path you require (the All Users path) in an OS dependent way. After all - do other operating systems have an equivalent? Your best bet is to probably inspect:
System.getProperty("os.name");
to see if you are running Windows and then if so use "C:\Documents & Settings\All Users\".
But you'll be better off just constantly using
System.getProperty("user.home");
(as mentioned by other people) throughout the application. Or alternatively, allow the user to specify the directory to store whatever it is you want to store.
Specifically getting on Windows the "..\Documents & Settings\All Users, basicaly any path that needs the front end to be dynamically derived based on the OS your software is running on. (Now I need the answer to this)
The folders below the All Users dir are variable directories in windows. Details can be found in the document about KNOWNFOLDERIDs (CSIDL in older versions).
Because this values are system dependent Java does not provide a way to access the values.
I think there is in general no equivalent on other operating systems to this windows specific folder. In addition the folder Documents & Settings\All Users is only present in latest windows versions and things are handled differently for e.g Windows 2000 or XP I think.
If you really need this information you should read the microsoft docs and impement a native library or some script invoked by Runtime.exec to provide the information to your java application.

Categories

Resources