ln.c
来自「Linux下文件工具。」· C语言 代码 · 共 575 行 · 第 1/2 页
C
575 行
if (unlink (dest) && errno != ENOENT) { error (0, errno, _("cannot remove %s"), quote (dest)); return 1; } } else if (errno != ENOENT) { error (0, errno, _("accessing %s"), quote (dest)); return 1; } if (verbose) { printf ((symbolic_link ? _("create symbolic link %s to %s") : _("create hard link %s to %s")), quote_n (0, dest), quote_n (1, source)); if (backup_succeeded) printf (_(" (backup: %s)"), quote (dest_backup)); putchar ('\n'); } if ((*linkfunc) (source, dest) == 0) { return 0; } error (0, errno, (symbolic_link ? _("creating symbolic link %s to %s") : _("creating hard link %s to %s")), quote_n (0, dest), quote_n (1, source)); if (dest_backup) { if (rename (dest_backup, dest)) error (0, errno, _("cannot un-backup %s"), quote (dest)); } return 1;}voidusage (int status){ if (status != 0) fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else { printf (_("\Usage: %s [OPTION]... TARGET [LINK_NAME]\n\ or: %s [OPTION]... TARGET... DIRECTORY\n\ or: %s [OPTION]... --target-directory=DIRECTORY TARGET...\n\"), program_name, program_name, program_name); fputs (_("\Create a link to the specified TARGET with optional LINK_NAME.\n\If LINK_NAME is omitted, a link with the same basename as the TARGET is\n\created in the current directory. When using the second form with more\n\than one TARGET, the last argument must be a directory; create links\n\in DIRECTORY to each TARGET. Create hard links by default, symbolic\n\links with --symbolic. When creating hard links, each TARGET must exist.\n\\n\"), stdout); fputs (_("\Mandatory arguments to long options are mandatory for short options too.\n\"), stdout); fputs (_("\ --backup[=CONTROL] make a backup of each existing destination file\n\ -b like --backup but does not accept an argument\n\ -d, -F, --directory hard link directories (super-user only)\n\ -f, --force remove existing destination files\n\"), stdout); fputs (_("\ -n, --no-dereference treat destination that is a symlink to a\n\ directory as if it were a normal file\n\ -i, --interactive prompt whether to remove destinations\n\ -s, --symbolic make symbolic links instead of hard links\n\"), stdout); fputs (_("\ -S, --suffix=SUFFIX override the usual backup suffix\n\ --target-directory=DIRECTORY specify the DIRECTORY in which to create\n\ the links\n\ -v, --verbose print name of each file before linking\n\"), stdout); fputs (HELP_OPTION_DESCRIPTION, stdout); fputs (VERSION_OPTION_DESCRIPTION, stdout); fputs (_("\\n\The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\The version control method may be selected via the --backup option or through\n\the VERSION_CONTROL environment variable. Here are the values:\n\\n\"), stdout); fputs (_("\ none, off never make backups (even if --backup is given)\n\ numbered, t make numbered backups\n\ existing, nil numbered if numbered backups exist, simple otherwise\n\ simple, never always make simple backups\n\"), stdout); printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT); } exit (status);}intmain (int argc, char **argv){ int c; int errors; int make_backups = 0; char *backup_suffix_string; char *version_control_string = NULL; char *target_directory = NULL; int target_directory_specified; unsigned int n_files; char **file; int dest_is_dir; program_name = argv[0]; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); atexit (close_stdout); /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless we'll actually use backup_suffix_string. */ backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX"); symbolic_link = remove_existing_files = interactive = verbose = hard_dir_link = 0; errors = 0; while ((c = getopt_long (argc, argv, "bdfinsvFS:V:", long_options, NULL)) != -1) { switch (c) { case 0: /* Long-named option. */ break; case 'V': /* FIXME: this is deprecated. Remove it in 2001. */ error (0, 0, _("warning: --version-control (-V) is obsolete; support for\ it\nwill be removed in some future release. Use --backup=%s instead." ), optarg); /* Fall through. */ case 'b': make_backups = 1; if (optarg) version_control_string = optarg; break; case 'd': case 'F': hard_dir_link = 1; break; case 'f': remove_existing_files = 1; interactive = 0; break; case 'i': remove_existing_files = 0; interactive = 1; break; case 'n': dereference_dest_dir_symlinks = 0; break; case 's':#ifdef S_ISLNK symbolic_link = 1;#else error (1, 0, _("symbolic links are not supported on this system"));#endif break; case TARGET_DIRECTORY_OPTION: target_directory = optarg; break; case 'v': verbose = 1; break; case 'S': make_backups = 1; backup_suffix_string = optarg; break; case_GETOPT_HELP_CHAR; case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: usage (1); break; } } n_files = argc - optind; file = argv + optind; if (n_files == 0) { error (0, 0, _("missing file argument")); usage (1); } target_directory_specified = (target_directory != NULL); if (!target_directory) target_directory = file[n_files - 1]; /* If there's only one file argument, then pretend `.' was given as the second argument. */ if (n_files == 1) { static char *dummy[2]; dummy[0] = file[0]; dummy[1] = "."; file = dummy; n_files = 2; dest_is_dir = 1; } else { dest_is_dir = isdir (target_directory); } if (symbolic_link) linkfunc = symlink; else linkfunc = link; if (target_directory_specified && !dest_is_dir) { error (0, 0, _("%s: specified target directory is not a directory"), quote (target_directory)); usage (1); } if (backup_suffix_string) simple_backup_suffix = xstrdup (backup_suffix_string); backup_type = (make_backups ? xget_version (_("backup type"), version_control_string) : none); if (target_directory_specified || n_files > 2) { unsigned int i; unsigned int last_file_idx = (target_directory_specified ? n_files - 1 : n_files - 2); if (!target_directory_specified && !dest_is_dir) error (1, 0, _("when making multiple links, last argument must be a directory")); for (i = 0; i <= last_file_idx; ++i) errors += do_link (file[i], target_directory); } else { struct stat source_stats; const char *source; char *dest; char *new_dest; source = file[0]; dest = file[1]; /* When the destination is specified with a trailing slash and the source exists but is not a directory, convert the user's command `ln source dest/' to `ln source dest/basename(source)'. */ if (dest[strlen (dest) - 1] == '/' && lstat (source, &source_stats) == 0 && !S_ISDIR (source_stats.st_mode)) { PATH_BASENAME_CONCAT (new_dest, dest, source); } else { new_dest = dest; } errors = do_link (source, new_dest); } exit (errors != 0);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?