char * mc_build_filename (const char *first_element, ...) { va_list args; const char *element = first_element; GString *path; char *ret; if (element == NULL) return NULL; path = g_string_new (""); va_start (args, first_element); do { char *tmp_element; size_t len; const char *start; tmp_element = g_strdup (element); element = va_arg (args, char *); canonicalize_pathname (tmp_element); len = strlen (tmp_element); start = (tmp_element[0] == PATH_SEP) ? tmp_element + 1 : tmp_element; g_string_append (path, start); if (tmp_element[len - 1] != PATH_SEP && element != NULL) g_string_append_c (path, PATH_SEP); g_free (tmp_element); } while (element != NULL); va_end (args); g_string_prepend_c (path, PATH_SEP); ret = g_string_free (path, FALSE); canonicalize_pathname (ret); return ret; }
/* * Follow > 0: follow links, serves as loop protect, * == -1: do not follow links */ static struct vfs_s_entry * vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root, const char *a_path, int follow, int flags) { size_t pseg; struct vfs_s_entry *ent = NULL; char * const pathref = g_strdup (a_path); char *path = pathref; canonicalize_pathname (path); while (root) { while (*path == PATH_SEP) /* Strip leading '/' */ path++; if (!path[0]) { g_free (pathref); return ent; } for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++); for (ent = root->subdir; ent != NULL; ent = ent->next) if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg))) /* FOUND! */ break; if (!ent && (flags & (FL_MKFILE | FL_MKDIR))) ent = vfs_s_automake (me, root, path, flags); if (!ent) { me->verrno = ENOENT; goto cleanup; } path += pseg; /* here we must follow leading directories always; only the actual file is optional */ ent = vfs_s_resolve_symlink (me, ent, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow); if (!ent) goto cleanup; root = ent->ino; } cleanup: g_free (pathref); return NULL; }
char * mc_build_filename (const char *first_element, ...) { gboolean absolute; va_list args; const char *element = first_element; GString *path; char *ret; if (element == NULL) return NULL; path = g_string_new (""); va_start (args, first_element); absolute = (*first_element != '\0' && *first_element == PATH_SEP); do { if (*element == '\0') element = va_arg (args, char *); else { char *tmp_element; size_t len; const char *start; tmp_element = g_strdup (element); element = va_arg (args, char *); canonicalize_pathname (tmp_element); len = strlen (tmp_element); start = (tmp_element[0] == PATH_SEP) ? tmp_element + 1 : tmp_element; g_string_append (path, start); if (tmp_element[len - 1] != PATH_SEP && element != NULL) g_string_append_c (path, PATH_SEP); g_free (tmp_element); } }
/* * doing similar to $ gtar | compression | encryption */ static void start_backup( dle_t *dle, char *host, int dataf, int mesgf, int indexf) { char tmppath[PATH_MAX]; int dumpin, dumpout, compout; char *cmd = NULL; char *indexcmd = NULL; char *dirname = NULL; int l; char dumptimestr[80] = "UNUSED"; struct tm *gmtm; amandates_t *amdates = NULL; time_t prev_dumptime = 0; char *error_pn = NULL; char *compopt = NULL; char *encryptopt = skip_argument; char *tquoted; char *fquoted; char *qdisk; int infd, outfd; ssize_t nb; char buf[32768]; char *amandates_file = NULL; am_level_t *alevel = (am_level_t *)dle->levellist->data; int level = alevel->level; int native_pipe[2]; int client_pipe[2]; int data_out; have_filter = FALSE; crc32_init(&native_crc.crc); crc32_init(&client_crc.crc); /* create pipes to compute the native CRC */ if (pipe(native_pipe) < 0) { char *errmsg; char *qerrmsg; errmsg = g_strdup_printf(_("Program '%s': can't create pipe"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); return; } if (dle->encrypt == ENCRYPT_CUST || dle->compress == COMP_FAST || dle->compress == COMP_BEST || dle->compress == COMP_CUST) { have_filter = TRUE; /* create pipes to compute the client CRC */ if (pipe(client_pipe) < 0) { char *errmsg; char *qerrmsg; errmsg = g_strdup_printf(_("Application '%s': can't create pipe"), dle->program); qerrmsg = quote_string(errmsg); fdprintf(mesgf, _("sendbackup: error [%s]\n"), errmsg); dbprintf(_("ERROR %s\n"), qerrmsg); amfree(qerrmsg); amfree(errmsg); return; } data_out = client_pipe[1]; client_pipe[1] = -1; } else { data_out = dataf; dataf = -1; } error_pn = g_strconcat(get_pname(), "-smbclient", NULL); qdisk = quote_string(dle->disk); dbprintf(_("start: %s:%s lev %d\n"), host, qdisk, level); g_fprintf(stderr, _("%s: start [%s:%s level %d]\n"), get_pname(), host, qdisk, level); /* apply client-side encryption here */ if ( dle->encrypt == ENCRYPT_CUST ) { encpid = pipespawn(dle->clnt_encrypt, STDIN_PIPE, 0, &compout, &data_out, &mesgf, dle->clnt_encrypt, encryptopt, NULL); dbprintf(_("gnutar: pid %ld: %s\n"), (long)encpid, dle->clnt_encrypt); aclose(data_out); } else { compout = data_out; data_out = -1; encpid = -1; } /* now do the client-side compression */ if (dle->compress == COMP_FAST || dle->compress == COMP_BEST) { compopt = skip_argument; #if defined(COMPRESS_BEST_OPT) && defined(COMPRESS_FAST_OPT) if(dle->compress == COMP_BEST) { compopt = COMPRESS_BEST_OPT; } else { compopt = COMPRESS_FAST_OPT; } #endif comppid = pipespawn(COMPRESS_PATH, STDIN_PIPE, 0, &dumpout, &compout, &mesgf, COMPRESS_PATH, compopt, NULL); dbprintf(_("gnutar: pid %ld: %s"), (long)comppid, COMPRESS_PATH); if(compopt != skip_argument) { dbprintf(_("pid %ld: %s %s\n"), (long)comppid, COMPRESS_PATH, compopt); } else { dbprintf(_("pid %ld: %s\n"), (long)comppid, COMPRESS_PATH); } aclose(compout); } else if (dle->compress == COMP_CUST) { compopt = skip_argument; comppid = pipespawn(dle->compprog, STDIN_PIPE, 0, &dumpout, &compout, &mesgf, dle->compprog, compopt, NULL); if(compopt != skip_argument) { dbprintf(_("pid %ld: %s %s\n"), (long)comppid, dle->compprog, compopt); } else { dbprintf(_("pid %ld: %s\n"), (long)comppid, dle->compprog); } aclose(compout); } else { dumpout = compout; compout = -1; comppid = -1; } gnutar_list_dir = getconf_str(CNF_GNUTAR_LIST_DIR); if (strlen(gnutar_list_dir) == 0) gnutar_list_dir = NULL; #ifdef SAMBA_CLIENT /* { */ if (dle->device[0] == '/' && dle->device[1]=='/') amfree(incrname); else #endif /* } */ if (gnutar_list_dir) { char *basename = NULL; char number[NUM_STR_SIZE]; char *inputname = NULL; int baselevel; char *sdisk = sanitise_filename(dle->disk); basename = g_strjoin(NULL, gnutar_list_dir, "/", host, sdisk, NULL); amfree(sdisk); g_snprintf(number, sizeof(number), "%d", level); incrname = g_strjoin(NULL, basename, "_", number, ".new", NULL); unlink(incrname); /* * Open the listed incremental file from the previous level. Search * backward until one is found. If none are found (which will also * be true for a level 0), arrange to read from /dev/null. */ baselevel = level; infd = -1; while (infd == -1) { if (--baselevel >= 0) { g_snprintf(number, sizeof(number), "%d", baselevel); g_free(inputname); inputname = g_strconcat(basename, "_", number, NULL); } else { g_free(inputname); inputname = g_strdup("/dev/null"); } if ((infd = open(inputname, O_RDONLY)) == -1) { int save_errno = errno; char *qname = quote_string(inputname); dbprintf(_("gnutar: error opening '%s': %s\n"), qname, strerror(save_errno)); if (baselevel < 0) { error(_("error [opening '%s': %s]"), qname, strerror(save_errno)); /*NOTREACHED*/ } amfree(qname); } } /* * Copy the previous listed incremental file to the new one. */ if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) { error(_("error [opening '%s': %s]"), incrname, strerror(errno)); /*NOTREACHED*/ } while ((nb = read(infd, &buf, sizeof(buf))) > 0) { if (full_write(outfd, &buf, (size_t)nb) < (size_t)nb) { error(_("error [writing to '%s': %s]"), incrname, strerror(errno)); /*NOTREACHED*/ } } if (nb < 0) { error(_("error [reading from '%s': %s]"), inputname, strerror(errno)); /*NOTREACHED*/ } if (close(infd) != 0) { error(_("error [closing '%s': %s]"), inputname, strerror(errno)); /*NOTREACHED*/ } if (close(outfd) != 0) { error(_("error [closing '%s': %s]"), incrname, strerror(errno)); /*NOTREACHED*/ } tquoted = quote_string(incrname); if(baselevel >= 0) { fquoted = quote_string(inputname); dbprintf(_("doing level %d dump as listed-incremental from '%s' to '%s'\n"), level, fquoted, tquoted); amfree(fquoted); } else { dbprintf(_("doing level %d dump as listed-incremental to '%s'\n"), level, tquoted); } amfree(tquoted); amfree(inputname); amfree(basename); } else { /* no gnutar-listdir, so we're using amandates */ /* find previous dump time, failing completely if there's a problem */ amandates_file = getconf_str(CNF_AMANDATES); if(!start_amandates(amandates_file, 0)) { error(_("error [opening %s: %s]"), amandates_file, strerror(errno)); /*NOTREACHED*/ } amdates = amandates_lookup(dle->disk); prev_dumptime = EPOCH; for(l = 0; l < level; l++) { if(amdates->dates[l] > prev_dumptime) prev_dumptime = amdates->dates[l]; } finish_amandates(); free_amandates(); gmtm = gmtime(&prev_dumptime); g_snprintf(dumptimestr, sizeof(dumptimestr), "%04d-%02d-%02d %2d:%02d:%02d GMT", gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec); dbprintf(_("gnutar: doing level %d dump from amandates-derived date: %s\n"), level, dumptimestr); } dirname = amname_to_dirname(dle->device); cur_dumptime = time(0); cur_level = level; cur_disk = g_strdup(dle->disk); #ifdef GNUTAR # define PROGRAM_GNUTAR GNUTAR #else # define PROGRAM_GNUTAR "tar" #endif indexcmd = g_strjoin(NULL, PROGRAM_GNUTAR, " -tf", " -", " 2>/dev/null", " | sed", " -e", " \'s/^\\.//\'", NULL); #ifdef SAMBA_CLIENT /* { */ /* Use sambatar if the disk to back up is a PC disk */ if (dle->device[0] == '/' && dle->device[1]=='/') { char *sharename = NULL, *user_and_password = NULL, *domain = NULL; char *share = NULL, *subdir = NULL; char *pwtext = NULL; char *taropt; int passwdf = -1; size_t lpass; size_t pwtext_len; char *pw_fd_env; parsesharename(dle->device, &share, &subdir); if (!share) { amfree(share); amfree(subdir); set_pname(error_pn); amfree(error_pn); error(_("cannot parse disk entry %s for share/subdir"), qdisk); /*NOTREACHED*/ } if ((subdir) && (SAMBA_VERSION < 2)) { amfree(share); amfree(subdir); set_pname(error_pn); amfree(error_pn); error(_("subdirectory specified for share %s but samba not v2 or better"), qdisk); /*NOTREACHED*/ } if ((user_and_password = findpass(share, &domain)) == NULL) { if(domain) { memset(domain, '\0', strlen(domain)); amfree(domain); } set_pname(error_pn); amfree(error_pn); error(_("error [invalid samba host or password not found?]")); /*NOTREACHED*/ } lpass = strlen(user_and_password); if ((pwtext = strchr(user_and_password, '%')) == NULL) { memset(user_and_password, '\0', lpass); amfree(user_and_password); if(domain) { memset(domain, '\0', strlen(domain)); amfree(domain); } set_pname(error_pn); amfree(error_pn); error(_("password field not \'user%%pass\' for %s"), qdisk); /*NOTREACHED*/ } *pwtext++ = '\0'; pwtext_len = strlen(pwtext); if ((sharename = makesharename(share, 0)) == 0) { memset(user_and_password, '\0', lpass); amfree(user_and_password); if(domain) { memset(domain, '\0', strlen(domain)); amfree(domain); } set_pname(error_pn); amfree(error_pn); error(_("error [can't make share name of %s]"), share); /*NOTREACHED*/ } taropt = g_strdup("-T"); if(dle->exclude_file && dle->exclude_file->nb_element == 1) { strappend(taropt, "X"); } #if SAMBA_VERSION >= 2 strappend(taropt, "q"); #endif strappend(taropt, "c"); if (level != 0) { strappend(taropt, "g"); } else if (dle->record) { strappend(taropt, "a"); } if (subdir) { dbprintf(_("gnutar: backup of %s/%s\n"), sharename, subdir); } else { dbprintf(_("gnutar: backup of %s\n"), sharename); } program->backup_name = program->restore_name = SAMBA_CLIENT; cmd = g_strdup(program->backup_name); info_tapeheader(dle); start_index(dle->create_index, native_pipe[1], mesgf, indexf, indexcmd); if (pwtext_len > 0) { pw_fd_env = "PASSWD_FD"; } else { pw_fd_env = "dummy_PASSWD_FD"; } dumppid = pipespawn(cmd, STDIN_PIPE|PASSWD_PIPE, 0, &dumpin, &native_pipe[1], &mesgf, pw_fd_env, &passwdf, "smbclient", sharename, *user_and_password ? "-U" : skip_argument, *user_and_password ? user_and_password : skip_argument, "-E", domain ? "-W" : skip_argument, domain ? domain : skip_argument, #if SAMBA_VERSION >= 2 subdir ? "-D" : skip_argument, subdir ? subdir : skip_argument, #endif "-d0", taropt, "-", dle->exclude_file && dle->exclude_file->nb_element == 1 ? dle->exclude_file->first->name : skip_argument, NULL); if(domain) { memset(domain, '\0', strlen(domain)); amfree(domain); } if(pwtext_len > 0 && full_write(passwdf, pwtext, pwtext_len) < pwtext_len) { int save_errno = errno; aclose(passwdf); memset(user_and_password, '\0', lpass); amfree(user_and_password); set_pname(error_pn); amfree(error_pn); error(_("error [password write failed: %s]"), strerror(save_errno)); /*NOTREACHED*/ } memset(user_and_password, '\0', lpass); amfree(user_and_password); aclose(passwdf); amfree(sharename); amfree(share); amfree(subdir); amfree(taropt); tarpid = dumppid; } else #endif /*end of samba */ { int nb_exclude = 0; int nb_include = 0; GPtrArray *argv_ptr = g_ptr_array_new(); char *file_exclude = NULL; char *file_include = NULL; messagelist_t mlist = NULL; if (dle->exclude_file) nb_exclude+=dle->exclude_file->nb_element; if (dle->exclude_list) nb_exclude+=dle->exclude_list->nb_element; if (dle->include_file) nb_include+=dle->include_file->nb_element; if (dle->include_list) nb_include+=dle->include_list->nb_element; if (nb_exclude > 0) file_exclude = build_exclude(dle, &mlist); if (nb_include > 0) file_include = build_include(dle, dirname, &mlist); g_slist_free(mlist); // MUST also free the message cmd = g_strjoin(NULL, amlibexecdir, "/", "runtar", NULL); info_tapeheader(dle); start_index(dle->create_index, native_pipe[1], mesgf, indexf, indexcmd); g_ptr_array_add(argv_ptr, g_strdup("runtar")); if (g_options->config) g_ptr_array_add(argv_ptr, g_strdup(g_options->config)); else g_ptr_array_add(argv_ptr, g_strdup("NOCONFIG")); #ifdef GNUTAR g_ptr_array_add(argv_ptr, g_strdup(GNUTAR)); #else g_ptr_array_add(argv_ptr, g_strdup("tar")); #endif g_ptr_array_add(argv_ptr, g_strdup("--create")); g_ptr_array_add(argv_ptr, g_strdup("--file")); g_ptr_array_add(argv_ptr, g_strdup("-")); g_ptr_array_add(argv_ptr, g_strdup("--directory")); canonicalize_pathname(dirname, tmppath); g_ptr_array_add(argv_ptr, g_strdup(tmppath)); g_ptr_array_add(argv_ptr, g_strdup("--one-file-system")); if (gnutar_list_dir && incrname) { g_ptr_array_add(argv_ptr, g_strdup("--listed-incremental")); g_ptr_array_add(argv_ptr, g_strdup(incrname)); } else { g_ptr_array_add(argv_ptr, g_strdup("--incremental")); g_ptr_array_add(argv_ptr, g_strdup("--newer")); g_ptr_array_add(argv_ptr, g_strdup(dumptimestr)); } #ifdef ENABLE_GNUTAR_ATIME_PRESERVE /* --atime-preserve causes gnutar to call * utime() after reading files in order to * adjust their atime. However, utime() * updates the file's ctime, so incremental * dumps will think the file has changed. */ g_ptr_array_add(argv_ptr, g_strdup("--atime-preserve")); #endif g_ptr_array_add(argv_ptr, g_strdup("--sparse")); g_ptr_array_add(argv_ptr, g_strdup("--ignore-failed-read")); g_ptr_array_add(argv_ptr, g_strdup("--totals")); if(file_exclude) { g_ptr_array_add(argv_ptr, g_strdup("--exclude-from")); g_ptr_array_add(argv_ptr, g_strdup(file_exclude)); } if(file_include) { g_ptr_array_add(argv_ptr, g_strdup("--files-from")); g_ptr_array_add(argv_ptr, g_strdup(file_include)); } else { g_ptr_array_add(argv_ptr, g_strdup(".")); } g_ptr_array_add(argv_ptr, NULL); dumppid = pipespawnv(cmd, STDIN_PIPE, 0, &dumpin, &native_pipe[1], &mesgf, (char **)argv_ptr->pdata); tarpid = dumppid; amfree(file_exclude); amfree(file_include); g_ptr_array_free_full(argv_ptr); } dbprintf(_("gnutar: %s: pid %ld\n"), cmd, (long)dumppid); amfree(qdisk); amfree(dirname); amfree(cmd); amfree(indexcmd); amfree(error_pn); /* close the write ends of the pipes */ aclose(dumpin); aclose(native_pipe[1]); aclose(mesgf); if (dle->create_index) aclose(indexf); if (shm_control_name) { shm_ring = shm_ring_link(shm_control_name); shm_ring_producer_set_size(shm_ring, NETWORK_BLOCK_BYTES*16, NETWORK_BLOCK_BYTES*4); native_crc.in = native_pipe[0]; if (!have_filter) { native_crc.out = dumpout; native_crc.shm_ring = shm_ring; native_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread, (gpointer)&native_crc, TRUE, NULL); } else { native_crc.out = dumpout; native_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&native_crc, TRUE, NULL); client_crc.in = client_pipe[0]; client_crc.out = dataf; client_crc.shm_ring = shm_ring; client_crc.thread = g_thread_create(handle_crc_to_shm_ring_thread, (gpointer)&client_crc, TRUE, NULL); } } else { native_crc.in = native_pipe[0]; native_crc.out = dumpout; native_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&native_crc, TRUE, NULL); if (have_filter) { client_crc.in = client_pipe[0]; client_crc.out = dataf; client_crc.thread = g_thread_create(handle_crc_thread, (gpointer)&client_crc, TRUE, NULL); } } }
static char * filename_completion_function (const char *text, int state, input_complete_t flags) { static DIR *directory = NULL; static char *filename = NULL; static char *dirname = NULL; static char *users_dirname = NULL; static size_t filename_len; int isdir = 1, isexec = 0; static vfs_path_t *dirname_vpath = NULL; struct dirent *entry = NULL; SHOW_C_CTX ("filename_completion_function"); if (text && (flags & INPUT_COMPLETE_SHELL_ESC)) { char *u_text; char *result; char *e_result; u_text = strutils_shell_unescape (text); result = filename_completion_function (u_text, state, flags & (~INPUT_COMPLETE_SHELL_ESC)); g_free (u_text); e_result = strutils_shell_escape (result); g_free (result); return e_result; } /* If we're starting the match process, initialize us a bit. */ if (state == 0) { const char *temp; g_free (dirname); g_free (filename); g_free (users_dirname); vfs_path_free (dirname_vpath); if ((*text != '\0') && (temp = strrchr (text, PATH_SEP)) != NULL) { filename = g_strdup (++temp); dirname = g_strndup (text, temp - text); } else { dirname = g_strdup ("."); filename = g_strdup (text); } /* We aren't done yet. We also support the "~user" syntax. */ /* Save the version of the directory that the user typed. */ users_dirname = dirname; dirname = tilde_expand (dirname); canonicalize_pathname (dirname); dirname_vpath = vfs_path_from_str (dirname); /* Here we should do something with variable expansion and `command`. Maybe a dream - UNIMPLEMENTED yet. */ directory = mc_opendir (dirname_vpath); filename_len = strlen (filename); } /* Now that we have some state, we can read the directory. */ while (directory && (entry = mc_readdir (directory))) { if (!str_is_valid_string (entry->d_name)) continue; /* Special case for no filename. All entries except "." and ".." match. */ if (filename_len == 0) { if (DIR_IS_DOT (entry->d_name) || DIR_IS_DOTDOT (entry->d_name)) continue; } else { /* Otherwise, if these match up to the length of filename, then it may be a match. */ if ((entry->d_name[0] != filename[0]) || ((NLENGTH (entry)) < filename_len) || strncmp (filename, entry->d_name, filename_len)) continue; } isdir = 1; isexec = 0; { struct stat tempstat; vfs_path_t *tmp_vpath; tmp_vpath = vfs_path_build_filename (dirname, entry->d_name, (char *) NULL); /* Unix version */ if (mc_stat (tmp_vpath, &tempstat) == 0) { uid_t my_uid = getuid (); gid_t my_gid = getgid (); if (!S_ISDIR (tempstat.st_mode)) { isdir = 0; if ((!my_uid && (tempstat.st_mode & 0111)) || (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) || (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) || (tempstat.st_mode & 0001)) isexec = 1; } } else { /* stat failed, strange. not a dir in any case */ isdir = 0; } vfs_path_free (tmp_vpath); } if ((flags & INPUT_COMPLETE_COMMANDS) && (isexec || isdir)) break; if ((flags & INPUT_COMPLETE_CD) && isdir) break; if (flags & (INPUT_COMPLETE_FILENAMES)) break; } if (entry == NULL) { if (directory) { mc_closedir (directory); directory = NULL; } g_free (dirname); dirname = NULL; vfs_path_free (dirname_vpath); dirname_vpath = NULL; g_free (filename); filename = NULL; g_free (users_dirname); users_dirname = NULL; return NULL; } { GString *temp; temp = g_string_sized_new (16); if (users_dirname != NULL && (users_dirname[0] != '.' || users_dirname[1] != '\0')) { g_string_append (temp, users_dirname); /* We need a '/' at the end. */ if (temp->str[temp->len - 1] != PATH_SEP) g_string_append_c (temp, PATH_SEP); } g_string_append (temp, entry->d_name); if (isdir) g_string_append_c (temp, PATH_SEP); return g_string_free (temp, FALSE); } }
const char * mc_tmpdir (void) { static char buffer[64]; static const char *tmpdir; const char *sys_tmp; struct passwd *pwd; struct stat st; const char *error = NULL; /* Check if already correctly initialized */ if (tmpdir && lstat (tmpdir, &st) == 0 && S_ISDIR (st.st_mode) && st.st_uid == getuid () && (st.st_mode & 0777) == 0700) return tmpdir; sys_tmp = getenv ("TMPDIR"); if (!sys_tmp || sys_tmp[0] != '/') { sys_tmp = TMPDIR_DEFAULT; } pwd = getpwuid (getuid ()); if (pwd) g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp, pwd->pw_name); else g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp, (unsigned long) getuid ()); canonicalize_pathname (buffer); if (lstat (buffer, &st) == 0) { /* Sanity check for existing directory */ if (!S_ISDIR (st.st_mode)) error = _("%s is not a directory\n"); else if (st.st_uid != getuid ()) error = _("Directory %s is not owned by you\n"); else if (((st.st_mode & 0777) != 0700) && (chmod (buffer, 0700) != 0)) error = _("Cannot set correct permissions for directory %s\n"); } else { /* Need to create directory */ if (mkdir (buffer, S_IRWXU) != 0) { fprintf (stderr, _("Cannot create temporary directory %s: %s\n"), buffer, unix_error_string (errno)); error = ""; } } if (error != NULL) { int test_fd; char *test_fn, *fallback_prefix; int fallback_ok = 0; if (*error) fprintf (stderr, error, buffer); /* Test if sys_tmp is suitable for temporary files */ fallback_prefix = g_strdup_printf ("%s/mctest", sys_tmp); test_fd = mc_mkstemps (&test_fn, fallback_prefix, NULL); g_free (fallback_prefix); if (test_fd != -1) { close (test_fd); test_fd = open (test_fn, O_RDONLY); if (test_fd != -1) { close (test_fd); unlink (test_fn); fallback_ok = 1; } } if (fallback_ok) { fprintf (stderr, _("Temporary files will be created in %s\n"), sys_tmp); g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp); error = NULL; } else { fprintf (stderr, _("Temporary files will not be created\n")); g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/"); } fprintf (stderr, "%s\n", _("Press any key to continue...")); getc (stdin); } tmpdir = buffer; if (!error) g_setenv ("MC_TMPDIR", tmpdir, TRUE); return tmpdir; }
static char * filename_completion_function (char *text, int state) { static DIR *directory; static char *filename = NULL; static char *dirname = NULL; static char *users_dirname = NULL; static size_t filename_len; int isdir = 1, isexec = 0; struct dirent *entry = NULL; /* If we're starting the match process, initialize us a bit. */ if (!state){ const char *temp; g_free (dirname); g_free (filename); g_free (users_dirname); if ((*text) && (temp = strrchr (text, PATH_SEP))){ filename = g_strdup (++temp); dirname = g_strndup (text, temp - text); } else { dirname = g_strdup ("."); filename = g_strdup (text); } /* We aren't done yet. We also support the "~user" syntax. */ /* Save the version of the directory that the user typed. */ users_dirname = dirname; { dirname = tilde_expand (dirname); canonicalize_pathname (dirname); /* Here we should do something with variable expansion and `command`. Maybe a dream - UNIMPLEMENTED yet. */ } directory = mc_opendir (dirname); filename_len = strlen (filename); } /* Now that we have some state, we can read the directory. */ while (directory && (entry = mc_readdir (directory))){ /* Special case for no filename. All entries except "." and ".." match. */ if (!filename_len){ if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, "..")) continue; } else { /* Otherwise, if these match up to the length of filename, then it may be a match. */ if ((entry->d_name[0] != filename[0]) || ((NLENGTH (entry)) < filename_len) || strncmp (filename, entry->d_name, filename_len)) continue; } isdir = 1; isexec = 0; { char *tmp = g_malloc (3 + strlen (dirname) + NLENGTH (entry)); struct stat tempstat; strcpy (tmp, dirname); strcat (tmp, PATH_SEP_STR); strcat (tmp, entry->d_name); canonicalize_pathname (tmp); /* Unix version */ if (!mc_stat (tmp, &tempstat)){ uid_t my_uid = getuid (); gid_t my_gid = getgid (); if (!S_ISDIR (tempstat.st_mode)){ isdir = 0; if ((!my_uid && (tempstat.st_mode & 0111)) || (my_uid == tempstat.st_uid && (tempstat.st_mode & 0100)) || (my_gid == tempstat.st_gid && (tempstat.st_mode & 0010)) || (tempstat.st_mode & 0001)) isexec = 1; } } g_free (tmp); } switch (look_for_executables) { case 2: if (!isexec) continue; break; case 1: if (!isexec && !isdir) continue; break; } if (ignore_filenames && !isdir) continue; break; } if (!entry){ if (directory){ mc_closedir (directory); directory = NULL; } g_free (dirname); dirname = NULL; g_free (filename); filename = NULL; g_free (users_dirname); users_dirname = NULL; return NULL; } else { char *temp; if (users_dirname && (users_dirname[0] != '.' || users_dirname[1])){ int dirlen = strlen (users_dirname); temp = g_malloc (3 + dirlen + NLENGTH (entry)); strcpy (temp, users_dirname); /* We need a `/' at the end. */ if (users_dirname[dirlen - 1] != PATH_SEP){ temp[dirlen] = PATH_SEP; temp[dirlen + 1] = 0; } strcat (temp, entry->d_name); } else { temp = g_malloc (2 + NLENGTH (entry)); strcpy (temp, entry->d_name); } if (isdir) strcat (temp, PATH_SEP_STR); return temp; } }
/* * This is the function to call when the word to complete is in a position * where a command word can be found. It looks around $PATH, looking for * commands that match. It also scans aliases, function names, and the * table of shell built-ins. */ static char * command_completion_function (char *text, int state) { static const char *path_end; static int isabsolute; static int phase; static int text_len; static const char *const *words; static char *path; static char *cur_path; static char *cur_word; static int init_state; static const char *const bash_reserved[] = { "if", "then", "else", "elif", "fi", "case", "esac", "for", "select", "while", "until", "do", "done", "in", "function", 0 }; static const char *const bash_builtins[] = { "alias", "bg", "bind", "break", "builtin", "cd", "command", "continue", "declare", "dirs", "echo", "enable", "eval", "exec", "exit", "export", "fc", "fg", "getopts", "hash", "help", "history", "jobs", "kill", "let", "local", "logout", "popd", "pushd", "pwd", "read", "readonly", "return", "set", "shift", "source", "suspend", "test", "times", "trap", "type", "typeset", "ulimit", "umask", "unalias", "unset", "wait", 0 }; char *p, *found; if (!state) { /* Initialize us a little bit */ isabsolute = strchr (text, PATH_SEP) != 0; look_for_executables = isabsolute ? 1 : 2; if (!isabsolute) { words = bash_reserved; phase = 0; text_len = strlen (text); if (!path && (path = g_strdup (getenv ("PATH"))) != NULL) { p = path; path_end = strchr (p, 0); while ((p = strchr (p, PATH_ENV_SEP))) { *p++ = 0; } } } } if (isabsolute) { p = filename_completion_function (text, state); if (!p) look_for_executables = 0; return p; } found = NULL; switch (phase) { case 0: /* Reserved words */ while (*words) { if (!strncmp (*words, text, text_len)) return g_strdup (*(words++)); words++; } phase++; words = bash_builtins; case 1: /* Builtin commands */ while (*words) { if (!strncmp (*words, text, text_len)) return g_strdup (*(words++)); words++; } phase++; if (!path) break; cur_path = path; cur_word = NULL; case 2: /* And looking through the $PATH */ while (!found) { if (!cur_word) { char *expanded; if (cur_path >= path_end) break; expanded = tilde_expand (*cur_path ? cur_path : "."); cur_word = concat_dir_and_file (expanded, text); g_free (expanded); canonicalize_pathname (cur_word); cur_path = strchr (cur_path, 0) + 1; init_state = state; } found = filename_completion_function (cur_word, state - init_state); if (!found) { g_free (cur_word); cur_word = NULL; } } } if (!found) { look_for_executables = 0; g_free (path); path = NULL; return NULL; } if ((p = strrchr (found, PATH_SEP)) != NULL) { p++; p = g_strdup (p); g_free (found); return p; } return found; }
static struct vfs_s_entry * vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root, const char *a_path, int follow, int flags) { struct vfs_s_entry *ent = NULL; char * const path = g_strdup (a_path); struct vfs_s_entry *retval = NULL; if (root->super->root != root) vfs_die ("We have to use _real_ root. Always. Sorry."); canonicalize_pathname (path); if (!(flags & FL_DIR)) { char *dirname, *name, *save; struct vfs_s_inode *ino; split_dir_name (me, path, &dirname, &name, &save); ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR); if (save) *save = PATH_SEP; retval = vfs_s_find_entry_tree (me, ino, name, follow, flags); g_free (path); return retval; } for (ent = root->subdir; ent != NULL; ent = ent->next) if (!strcmp (ent->name, path)) break; if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino))) { #if 1 print_vfs_message (_("Directory cache expired for %s"), path); #endif vfs_s_free_entry (me, ent); ent = NULL; } if (!ent) { struct vfs_s_inode *ino; ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755)); ent = vfs_s_new_entry (me, path, ino); if ((MEDATA->dir_load) (me, ino, path) == -1) { vfs_s_free_entry (me, ent); g_free (path); return NULL; } vfs_s_insert_entry (me, root, ent); for (ent = root->subdir; ent != NULL; ent = ent->next) if (!strcmp (ent->name, path)) break; } if (!ent) vfs_die ("find_linear: success but directory is not there\n"); #if 0 if (!vfs_s_resolve_symlink (me, ent, follow)) { g_free (path); return NULL; } #endif g_free (path); return ent; }
static char * resolve_symlinks (const vfs_path_t * vpath) { char *p, *p2; char *buf, *buf2, *q, *r, c; struct stat mybuf; if (vpath->relative) return NULL; p = p2 = g_strdup (vfs_path_as_str (vpath)); r = buf = g_malloc (MC_MAXPATHLEN); buf2 = g_malloc (MC_MAXPATHLEN); *r++ = PATH_SEP; *r = 0; do { q = strchr (p + 1, PATH_SEP); if (!q) { q = strchr (p + 1, 0); if (q == p + 1) break; } c = *q; *q = 0; if (mc_lstat (vpath, &mybuf) < 0) { MC_PTR_FREE (buf); goto ret; } if (!S_ISLNK (mybuf.st_mode)) strcpy (r, p + 1); else { int len; len = mc_readlink (vpath, buf2, MC_MAXPATHLEN - 1); if (len < 0) { MC_PTR_FREE (buf); goto ret; } buf2[len] = 0; if (IS_PATH_SEP (*buf2)) strcpy (buf, buf2); else strcpy (r, buf2); } canonicalize_pathname (buf); r = strchr (buf, 0); if (*r == '\0' || !IS_PATH_SEP (r[-1])) /* FIXME: this condition is always true because r points to the EOL */ { *r++ = PATH_SEP; *r = '\0'; } *q = c; p = q; } while (c != '\0'); if (*buf == '\0') strcpy (buf, PATH_SEP_STR); else if (IS_PATH_SEP (r[-1]) && r != buf + 1) r[-1] = '\0'; ret: g_free (buf2); g_free (p2); return buf; }
static char * command_completion_function (const char *_text, int state, input_complete_t flags) { char *text; static const char *path_end; static gboolean isabsolute; static int phase; static size_t text_len; static const char *const *words; static char *path; static char *cur_path; static char *cur_word; static int init_state; static const char *const bash_reserved[] = { "if", "then", "else", "elif", "fi", "case", "esac", "for", "select", "while", "until", "do", "done", "in", "function", 0 }; static const char *const bash_builtins[] = { "alias", "bg", "bind", "break", "builtin", "cd", "command", "continue", "declare", "dirs", "echo", "enable", "eval", "exec", "exit", "export", "fc", "fg", "getopts", "hash", "help", "history", "jobs", "kill", "let", "local", "logout", "popd", "pushd", "pwd", "read", "readonly", "return", "set", "shift", "source", "suspend", "test", "times", "trap", "type", "typeset", "ulimit", "umask", "unalias", "unset", "wait", 0 }; char *p, *found; SHOW_C_CTX ("command_completion_function"); if (!(flags & INPUT_COMPLETE_COMMANDS)) return 0; text = strutils_shell_unescape (_text); flags &= ~INPUT_COMPLETE_SHELL_ESC; if (state == 0) { /* Initialize us a little bit */ isabsolute = strchr (text, PATH_SEP) != NULL; if (!isabsolute) { words = bash_reserved; phase = 0; text_len = strlen (text); if (path == NULL) { path = g_strdup (getenv ("PATH")); if (path != NULL) { p = path; path_end = strchr (p, '\0'); while ((p = strchr (p, PATH_ENV_SEP)) != NULL) { *p++ = '\0'; } } } } } if (isabsolute) { p = filename_completion_function (text, state, flags); if (p != NULL) { char *temp_p = p; p = strutils_shell_escape (p); g_free (temp_p); } g_free (text); return p; } found = NULL; switch (phase) { case 0: /* Reserved words */ while (*words) { if (strncmp (*words, text, text_len) == 0) { g_free (text); return g_strdup (*(words++)); } words++; } phase++; words = bash_builtins; case 1: /* Builtin commands */ while (*words) { if (strncmp (*words, text, text_len) == 0) { g_free (text); return g_strdup (*(words++)); } words++; } phase++; if (!path) break; cur_path = path; cur_word = NULL; case 2: /* And looking through the $PATH */ while (!found) { if (!cur_word) { char *expanded; if (cur_path >= path_end) break; expanded = tilde_expand (*cur_path ? cur_path : "."); cur_word = mc_build_filename (expanded, text, NULL); g_free (expanded); canonicalize_pathname (cur_word); cur_path = strchr (cur_path, 0) + 1; init_state = state; } found = filename_completion_function (cur_word, state - init_state, flags); if (!found) { g_free (cur_word); cur_word = NULL; } } } if (found == NULL) { g_free (path); path = NULL; } else { p = strrchr (found, PATH_SEP); if (p != NULL) { char *tmp = found; found = strutils_shell_escape (p + 1); g_free (tmp); } } g_free (text); return found; }
/** * local implementation of pathfind. * @param[in] path colon separated list of directories * @param[in] fname the name we are hunting for * @param[in] mode the required file mode * @returns an allocated string with the full path, or NULL */ static char * pathfind( char const * path, char const * fname, char const * mode ) { int p_index = 0; int mode_bits = 0; char * res_path = NULL; char zPath[ AG_PATH_MAX + 1 ]; if (strchr( mode, 'r' )) mode_bits |= R_OK; if (strchr( mode, 'w' )) mode_bits |= W_OK; if (strchr( mode, 'x' )) mode_bits |= X_OK; /* * FOR each non-null entry in the colon-separated path, DO ... */ for (;;) { DIR* dirP; char* colon_unit = extract_colon_unit( zPath, path, &p_index ); if (colon_unit == NULL) break; dirP = opendir( colon_unit ); /* * IF the directory is inaccessable, THEN next directory */ if (dirP == NULL) continue; for (;;) { struct dirent *entP = readdir( dirP ); if (entP == (struct dirent*)NULL) break; /* * IF the file name matches the one we are looking for, ... */ if (strcmp(entP->d_name, fname) == 0) { char * abs_name = make_absolute(fname, colon_unit); /* * Make sure we can access it in the way we want */ if (access(abs_name, mode_bits) >= 0) { /* * We can, so normalize the name and return it below */ res_path = canonicalize_pathname(abs_name); } free(abs_name); break; } } closedir( dirP ); if (res_path != NULL) break; } return res_path; }
int etags_set_definition_hash (const char *tagfile, const char *start_path, const char *match_func, etags_hash_t * def_hash) { /* *INDENT-OFF* */ enum { start, in_filename, in_define } state = start; /* *INDENT-ON* */ FILE *f; static char buf[BUF_LARGE]; char *chekedstr = NULL; int num = 0; /* returned value */ char *filename = NULL; if (!match_func || !tagfile) return 0; /* open file with positions */ f = fopen (tagfile, "r"); if (f == NULL) return 0; while (fgets (buf, sizeof (buf), f)) { switch (state) { case start: if (buf[0] == 0x0C) { state = in_filename; } break; case in_filename: { size_t pos; pos = strcspn (buf, ","); g_free (filename); filename = g_strndup (buf, pos); state = in_define; break; } case in_define: if (buf[0] == 0x0C) { state = in_filename; break; } /* check if the filename matches the define pos */ chekedstr = strstr (buf, match_func); if (chekedstr) { char *longname = NULL; char *shortname = NULL; long line = 0; parse_define (chekedstr, &longname, &shortname, &line); if (num < MAX_DEFINITIONS - 1) { def_hash[num].filename_len = strlen (filename); def_hash[num].fullpath = mc_build_filename (start_path, filename, (char *) NULL); canonicalize_pathname (def_hash[num].fullpath); def_hash[num].filename = g_strdup (filename); if (shortname) { def_hash[num].short_define = g_strdup (shortname); } else { def_hash[num].short_define = g_strdup (longname); } def_hash[num].line = line; num++; } } break; default: break; } } g_free (filename); fclose (f); return num; }
static char * load_setup_get_full_config_name (const char *subdir, const char *config_file_name) { /* TODO: IMHO, in future, this function shall be placed in mcconfig module. */ char *lc_basename, *ret; char *file_name; if (config_file_name == NULL) return NULL; /* check for .keymap suffix */ if (g_str_has_suffix (config_file_name, ".keymap")) file_name = g_strdup (config_file_name); else file_name = g_strconcat (config_file_name, ".keymap", (char *) NULL); canonicalize_pathname (file_name); if (g_path_is_absolute (file_name)) return file_name; lc_basename = g_path_get_basename (file_name); g_free (file_name); if (lc_basename == NULL) return NULL; if (subdir != NULL) ret = g_build_filename (mc_config_get_path (), subdir, lc_basename, NULL); else ret = g_build_filename (mc_config_get_path (), lc_basename, NULL); if (exist_file (ret)) { g_free (lc_basename); canonicalize_pathname (ret); return ret; } g_free (ret); if (subdir != NULL) ret = g_build_filename (mc_global.sysconfig_dir, subdir, lc_basename, NULL); else ret = g_build_filename (mc_global.sysconfig_dir, lc_basename, NULL); if (exist_file (ret)) { g_free (lc_basename); canonicalize_pathname (ret); return ret; } g_free (ret); if (subdir != NULL) ret = g_build_filename (mc_global.share_data_dir, subdir, lc_basename, NULL); else ret = g_build_filename (mc_global.share_data_dir, lc_basename, NULL); g_free (lc_basename); if (exist_file (ret)) { canonicalize_pathname (ret); return ret; } g_free (ret); return NULL; }
static char * resolve_symlinks (const char *path) { char *buf, *buf2, *q, *r, c; int len; struct stat mybuf; const char *p; if (*path != PATH_SEP) return NULL; r = buf = g_malloc (MC_MAXPATHLEN); buf2 = g_malloc (MC_MAXPATHLEN); *r++ = PATH_SEP; *r = 0; p = path; for (;;) { q = strchr (p + 1, PATH_SEP); if (!q) { q = strchr (p + 1, 0); if (q == p + 1) break; } c = *q; *q = 0; if (mc_lstat (path, &mybuf) < 0) { g_free (buf); g_free (buf2); *q = c; return NULL; } if (!S_ISLNK (mybuf.st_mode)) strcpy (r, p + 1); else { len = mc_readlink (path, buf2, MC_MAXPATHLEN - 1); if (len < 0) { g_free (buf); g_free (buf2); *q = c; return NULL; } buf2[len] = 0; if (*buf2 == PATH_SEP) strcpy (buf, buf2); else strcpy (r, buf2); } canonicalize_pathname (buf); r = strchr (buf, 0); if (!*r || *(r - 1) != PATH_SEP) { *r++ = PATH_SEP; *r = 0; } *q = c; p = q; if (!c) break; } if (!*buf) strcpy (buf, PATH_SEP_STR); else if (*(r - 1) == PATH_SEP && r != buf + 1) *(r - 1) = 0; g_free (buf2); return buf; }