[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]
Summary
ln - make links between files
Lines of code: 619
Principal syscall: linkat(), symlinkat()
Support syscalls: stat(), lstat()
Options: 29 (14 short, 15 long)
Descended from ln introduced in Version 1 UNIX (1971)
Added to Fileutils in October 1992 [First version]
Number of revisions: 228
A key idea behind ln is the distinction between hard links and symbolic links: Hard links reference the same inode, but symbolic links are distinct inodes with no data. Mechanically, the difference lies in the syscall used to create the files. This utility has a large number of corner cases documented in do_link()
convert_abs_rel()
- Returns the relative link between source and target pathsdo_link()
- The primary link procedureerrno_nonexisting()
- Checks if an input error is due to a nonexistent filetarget_directory_operand()
- Detects if the full path/target is a directory
die()
- Exit with mandatory non-zero error and message to stderrerror()
- Outputs error message to standard error with possible process terminationforce_linkat()
- Creates a hard link (from gnulib)force_symblinkat()
- Creates a symbolic link (from gnulib)
Setup
Most of the logical control for ln is managed through global variables:
dereference_dest_dir_symlinks
- Flag to assume target is a symlinkdest_set
- The destination inode triple for hard linkshard_dir_link
- Flag that forces links to other links to actually use the targetinteractive
- Flag to query the user before removing existing fileslogical
- Flag to ensure that hard links are logicalrelative
- Flag to make symbolic links relativeremove_existing_files
- Flag to force removal of existing filessymbolic_link
- Flag to differentiate between making hard/symbolic linksverbose
- Flag to list all activities for the user
main()
introduces several local variables for additional processing:
*backup_suffix
- The suffix used for backup files (-b, -s)c
- The character for the next option to process**file
- Pointer to a list of filesmake_backups
- Flag used to force backups (-b)n_files
- The number of files specifiedno_target_directory
- Flag to assume that the target is a normal file (-T)ok
- The final return status*target_directory
- The destination directory (-t)*version_control_string
- The user chosen backup option (-b)
Parsing
Parsing ln considers the following questions:
- Are we creating hard or symbolic links?
- Should we force remove files? Query the user and notify the user?
- Should files be backed up? If so, by what method?
- Are the targets directories?
- Any special handling of symlinks?
Parsing failures
These failure cases are explicitly checked:
- Missing target information
- Specifying a target directory with no-target-directory flag
- Missing destination operands
- Extra operands
- Forcing directory handling on a file
- Using an unknown backup type
- Trying to use relative linking without specifying a symlink
- Unknown options
User specified parsing failures result in a short error message followed by the usage instructions. Access related parsing errors die with an error message.
Execution
The ln utility is dominated by checks for many edge cases, especially those involving target types and hard/symbolic link nuances.
After parsing, we prepare variables needed for the linking operation, including the backup type/name and the correct file names expected by do_link
. The link process kicks off by:
- Getting the source file information via
stat()
orlstat()
as appropriate. - Then we check if a destination file already exists so it can be removed
- We convert absolute names to relative names as needed by a link
- Create the hard or symbolic link with the appropriate gnulib wrapper
- Update file entry as needed
- Free name allocations previously malloc'd
Failure cases:
- Unable to
stat()
source file - Attempting to hard link a directory
- Unable to remove target file
- Attempting to overwrite an existing hard link
- Trying to link the same file for a source and target
- Trying to overwrite a directory
- Unable to create a backup
- Failed to create a link of any type (syscall failure)
All failures at this stage output an error message to STDERR and return without displaying usage help