/* Resolve link target and either navigate inside directory link points to or * navigate to directory where target is located pointing cursor on * it (the follow_dirs flag controls behaviour). */ static void follow_link(FileView *view, int follow_dirs) { char *dir, *file; char full_path[PATH_MAX]; char linkto[PATH_MAX + NAME_MAX]; dir_entry_t *const entry = &curr_view->dir_entry[curr_view->list_pos]; get_full_path_of(entry, sizeof(full_path), full_path); if(get_link_target_abs(full_path, entry->origin, linkto, sizeof(linkto)) != 0) { show_error_msg("Error", "Can't read link."); return; } if(!path_exists(linkto, DEREF)) { show_error_msg("Broken Link", "Can't access link destination. It might be broken."); return; } chosp(linkto); if(is_dir(linkto) && !follow_dirs) { dir = strdup(entry->name); file = NULL; } else { dir = strdup(linkto); remove_last_path_component(dir); file = get_last_path_component(linkto); } if(dir[0] != '\0') { navigate_to(view, dir); } if(file != NULL) { const int pos = find_file_pos_in_list(view, file); if(pos >= 0) { flist_set_pos(view, pos); } } free(dir); }
/* Checks whether path matches pattern in the autocommand. Returns non-zero if * so, otherwise zero is returned. */ static int is_pattern_match(const aucmd_info_t *autocmd, const char path[]) { const char *const part = (strchr(autocmd->pattern, '/') == NULL) ? get_last_path_component(path) : path; /* Leading start shouldn't match dot at the first character. Can't be * handled by globs->regex translation. */ if(autocmd->pattern[0] == '*' && part[0] == '.') { return 0; } return (regexec(&autocmd->regex, part, 0, NULL, 0) == 0)^autocmd->negated; }
TEST(chase_links_causes_link_to_be_resolved, IF(not_windows)) { assert_success(os_mkdir("dir", 0700)); /* symlink() is not available on Windows, but other code is fine. */ #ifndef _WIN32 assert_success(symlink("dir", "dir-link")); #endif assert_non_null(get_cwd(curr_view->curr_dir, sizeof(curr_view->curr_dir))); assert_true(change_directory(curr_view, "dir-link") >= 0); assert_string_equal("dir", get_last_path_component(curr_view->curr_dir)); /* Go out of the directory so that we can remove it. */ assert_true(change_directory(curr_view, "..") >= 0); assert_success(rmdir("dir")); assert_success(remove("dir-link")); }
extern int basename_main(int argc, char **argv) { int m, n; char *s; if ((argc < 2) || (**(argv + 1) == '-')) { show_usage(); } argv++; s = get_last_path_component(*argv); if (argc>2) { argv++; n = strlen(*argv); m = strlen(s); if (m>=n && strncmp(s+m-n, *argv, n)==0) s[m-n] = '\0'; } printf("%s\n", s); return EXIT_SUCCESS; }
/* Reads data to be displayed handling error cases. Returns zero on success, 1 * if file is a directory, 2 on file reading error, 3 on issues with viewer or * 4 on empty input. */ static int get_view_data(view_info_t *vi, const char file_to_view[]) { FILE *fp; const char *const viewer = get_viewer_for_file(get_last_path_component(file_to_view)); if(is_null_or_empty(viewer)) { if(is_dir(file_to_view)) { return 1; } else if((fp = fopen(file_to_view, "rb")) == NULL) { return 2; } } else if((fp = use_info_prog(viewer)) == NULL) { return 3; } vi->lines = is_null_or_empty(viewer) ? read_file_lines(fp, &vi->nlines) : read_stream_lines(fp, &vi->nlines); fclose(fp); if(vi->lines == NULL || vi->nlines == 0) { return 4; } return 0; }
/* Extracts last part of the path into buf. Assumes that size of the buf is * large enough. */ static void extract_last_path_component(const char path[], char buf[]) { const char *const last = get_last_path_component(path); snprintf(buf, until_first(last, '/') - last + 1, "%s", last); }
extern int grep_main(int argc, char **argv) { int opt; #if defined BB_FEATURE_GREP_CONTEXT || defined BB_FEATURE_GREP_EGREP_ALIAS char *junk; #endif #ifdef BB_FEATURE_CLEAN_UP /* destroy command strings on exit */ atexit(destroy_regexes); #endif #ifdef BB_FEATURE_GREP_EGREP_ALIAS junk = get_last_path_component(argv[0]); if (junk && strcmp(junk, "egrep") == 0) reflags |= REG_EXTENDED; #endif /* do normal option parsing */ while ((opt = getopt(argc, argv, "iHhlnqvsce:f:" #ifdef BB_FEATURE_GREP_CONTEXT "A:B:C:" #endif #ifdef BB_FEATURE_GREP_EGREP_ALIAS "E" #endif )) > 0) { switch (opt) { case 'i': ignore_case++; break; case 'l': print_files_with_matches++; break; case 'H': print_filename++; break; case 'h': print_filename--; break; case 'n': print_line_num++; break; case 'q': be_quiet++; break; case 'v': invert_search++; break; case 's': suppress_err_msgs++; break; case 'c': print_match_counts++; break; case 'e': add_regex(optarg); break; #ifdef BB_FEATURE_GREP_EGREP_ALIAS case 'E': reflags |= REG_EXTENDED; break; #endif case 'f': load_regexes_from_file(optarg); break; #ifdef BB_FEATURE_GREP_CONTEXT case 'A': lines_after = strtoul(optarg, &junk, 10); if(*junk != '\0') error_msg_and_die("invalid context length argument"); break; case 'B': lines_before = strtoul(optarg, &junk, 10); if(*junk != '\0') error_msg_and_die("invalid context length argument"); before_buf = (char **)xcalloc(lines_before, sizeof(char *)); break; case 'C': lines_after = lines_before = strtoul(optarg, &junk, 10); if(*junk != '\0') error_msg_and_die("invalid context length argument"); before_buf = (char **)xcalloc(lines_before, sizeof(char *)); break; #endif /* BB_FEATURE_GREP_CONTEXT */ default: show_usage(); } } /* if we didn't get a pattern from a -e and no command file was specified, * argv[optind] should be the pattern. no pattern, no worky */ if (nregexes == 0) { if (argv[optind] == NULL) show_usage(); else { add_regex(argv[optind]); optind++; } } /* sanity checks */ if (print_match_counts || be_quiet || print_files_with_matches) { print_line_num = 0; #ifdef BB_FEATURE_GREP_CONTEXT lines_before = 0; lines_after = 0; #endif } /* argv[(optind)..(argc-1)] should be names of file to grep through. If * there is more than one file to grep, we will print the filenames */ if ((argc-1) - (optind) > 0) print_filename++; /* If no files were specified, or '-' was specified, take input from * stdin. Otherwise, we grep through all the files specified. */ if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { grep_file(stdin); } else { int i; FILE *file; for (i = optind; i < argc; i++) { cur_file = argv[i]; file = fopen(cur_file, "r"); if (file == NULL) { if (!suppress_err_msgs) perror_msg("%s", cur_file); } else { grep_file(file); fclose(file); } } } return !matched; /* invert return value 0 = success, 1 = failed */ }
static fssh_status_t command_ln(int argc, const char* const* argv) { bool force = false; bool symbolic = false; bool dereference = true; // parse parameters int argi = 1; for (argi = 1; argi < argc; argi++) { const char *arg = argv[argi]; if (arg[0] != '-') break; if (arg[1] == '\0') { fprintf(stderr, "Error: Invalid option \"-\"\n"); return FSSH_B_BAD_VALUE; } for (int i = 1; arg[i]; i++) { switch (arg[i]) { case 'f': force = true; break; case 's': symbolic = true; break; case 'n': dereference = false; break; default: fprintf(stderr, "Error: Unknown option \"-%c\"\n", arg[i]); return FSSH_B_BAD_VALUE; } } } if (argc - argi != 2) { fprintf(stderr, "Usage: %s [Options] <source> <target>\n", argv[0]); return FSSH_B_BAD_VALUE; } const char *source = argv[argi]; const char *target = argv[argi + 1]; // check, if the the target is an existing directory struct fssh_stat st; char targetBuffer[FSSH_B_PATH_NAME_LENGTH]; fssh_status_t error = _kern_read_stat(-1, target, dereference, &st, sizeof(st)); if (error == FSSH_B_OK) { if (FSSH_S_ISDIR(st.fssh_st_mode)) { // get source leaf char leaf[FSSH_B_FILE_NAME_LENGTH]; error = get_last_path_component(source, leaf, sizeof(leaf)); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to get leaf name of source " "path: %s\n", fssh_strerror(error)); return error; } // compose a new path int len = strlen(target) + 1 + strlen(leaf); if (len > (int)sizeof(targetBuffer)) { fprintf(stderr, "Error: Resulting target path is too long.\n"); return FSSH_B_BAD_VALUE; } strcpy(targetBuffer, target); strcat(targetBuffer, "/"); strcat(targetBuffer, leaf); target = targetBuffer; } } // check, if the target exists error = _kern_read_stat(-1, target, false, &st, sizeof(st)); if (error == FSSH_B_OK) { if (!force) { fprintf(stderr, "Error: Can't create link. \"%s\" is in the way.\n", target); return FSSH_B_FILE_EXISTS; } // unlink the entry error = _kern_unlink(-1, target); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to remove \"%s\" to make way for " "link: %s\n", target, fssh_strerror(error)); return error; } } // finally create the link if (symbolic) { error = _kern_create_symlink(-1, target, source, FSSH_S_IRWXU | FSSH_S_IRWXG | FSSH_S_IRWXO); } else error = _kern_create_link(target, source); if (error != FSSH_B_OK) { fprintf(stderr, "Error: Failed to create link: %s\n", fssh_strerror(error)); } return error; }
static int64_t do_copy(const char *src, const char *dest, size_t blen, int vb, int recursive, int force, int interactive) { int r = -1; char dest_path[PATH_MAX]; char src_path[PATH_MAX]; DIR *dir = NULL; struct dirent *dp; dentry_type_t src_type = get_type(src); dentry_type_t dest_type = get_type(dest); const size_t src_len = str_size(src); if (src_type == TYPE_FILE) { char *src_fname; /* Initialize the src_path with the src argument */ str_cpy(src_path, src_len + 1, src); str_rtrim(src_path, '/'); /* Get the last component name from the src path */ src_fname = get_last_path_component(src_path); /* Initialize dest_path with the dest argument */ str_cpy(dest_path, PATH_MAX, dest); if (dest_type == TYPE_DIR) { /* e.g. cp file_name /data */ /* e.g. cp file_name /data/ */ /* dest is a directory, * append the src filename to it. */ merge_paths(dest_path, PATH_MAX, src_fname); dest_type = get_type(dest_path); } else if (dest_type == TYPE_NONE) { if (dest_path[str_size(dest_path) - 1] == '/') { /* e.g. cp /textdemo /data/dirnotexists/ */ printf("The dest directory %s does not exists", dest_path); goto exit; } } if (dest_type == TYPE_DIR) { printf("Cannot overwrite existing directory %s\n", dest_path); goto exit; } else if (dest_type == TYPE_FILE) { /* e.g. cp file_name existing_file */ /* dest already exists, * if force is set we will try to remove it. * if interactive is set user input is required. */ if (force && !interactive) { if (unlink(dest_path) != 0) { printf("Unable to remove %s\n", dest_path); goto exit; } } else if (!force && interactive) { bool overwrite = get_user_decision(false, "File already exists: %s. Overwrite? [y/N]: ", dest_path); if (overwrite) { printf("Overwriting file: %s\n", dest_path); if (unlink(dest_path) != 0) { printf("Unable to remove %s\n", dest_path); goto exit; } } else { printf("Not overwriting file: %s\n", dest_path); r = 0; goto exit; } } else { printf("File already exists: %s\n", dest_path); goto exit; } } /* call copy_file and exit */ r = (copy_file(src, dest_path, blen, vb) < 0); } else if (src_type == TYPE_DIR) { /* e.g. cp -r /x/srcdir /y/destdir/ */ if (!recursive) { printf("Cannot copy the %s directory without the " "-r option\n", src); goto exit; } else if (dest_type == TYPE_FILE) { printf("Cannot overwrite a file with a directory\n"); goto exit; } char *src_dirname; /* Initialize src_path with the content of src */ str_cpy(src_path, src_len + 1, src); str_rtrim(src_path, '/'); src_dirname = get_last_path_component(src_path); str_cpy(dest_path, PATH_MAX, dest); switch (dest_type) { case TYPE_DIR: if (str_cmp(src_dirname, "..") && str_cmp(src_dirname, ".")) { /* The last component of src_path is * not '.' or '..' */ merge_paths(dest_path, PATH_MAX, src_dirname); if (mkdir(dest_path, 0) != 0) { printf("Unable to create " "dest directory %s\n", dest_path); goto exit; } } break; default: case TYPE_NONE: /* dest does not exists, this means the user wants * to specify the name of the destination directory * * e.g. cp -r /src /data/new_dir_src */ if (mkdir(dest_path, 0) != 0) { printf("Unable to create " "dest directory %s\n", dest_path); goto exit; } break; } dir = opendir(src); if (!dir) { /* Something strange is happening... */ printf("Unable to open src %s directory\n", src); goto exit; } /* Copy every single directory entry of src into the * destination directory. */ while ((dp = readdir(dir))) { struct stat src_s; struct stat dest_s; char src_dent[PATH_MAX]; char dest_dent[PATH_MAX]; str_cpy(src_dent, PATH_MAX, src); merge_paths(src_dent, PATH_MAX, dp->d_name); str_cpy(dest_dent, PATH_MAX, dest_path); merge_paths(dest_dent, PATH_MAX, dp->d_name); /* Check if we are copying a directory into itself */ stat(src_dent, &src_s); stat(dest_path, &dest_s); if (dest_s.index == src_s.index && dest_s.fs_handle == src_s.fs_handle) { printf("Cannot copy a directory " "into itself\n"); goto exit; } if (vb) printf("copy %s %s\n", src_dent, dest_dent); /* Recursively call do_copy() */ r = do_copy(src_dent, dest_dent, blen, vb, recursive, force, interactive); if (r) goto exit; } } else printf("Unable to open source file %s\n", src); exit: if (dir) closedir(dir); return r; }