/* alias and password should be set already in url */ static void create_the_bookmark(url_t *url) { listitem *li; /* we don't want to be asked again */ url_setalias(ftp->url, url->alias); if(strcmp(ftp->curdir, ftp->homedir) != 0) url_setdirectory(url, ftp->curdir); else url_setdirectory(url, 0); list_clear(gvBookmarks); { char *tmp = NULL; if (asprintf(&tmp, "%s/bookmarks", gvWorkingDirectory) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); return; } parse_rc(tmp, false); free(tmp); } li = list_search(gvBookmarks, (listsearchfunc)urlcmp, url); if(li) list_delitem(gvBookmarks, li); list_additem(gvBookmarks, url); bookmark_save(0); }
/* appends char * items in list LP matching MASK * EXCLUDE_FUNC (if not 0) is called for each path found * and that path is excluded if EXCLUDE_FUNC returns true * * returns 0 if successful, -1 if failure */ int lglob_glob(list *gl, const char *mask, bool ignore_multiples, lglobfunc exclude_func) { struct dirent *de; DIR *dp; char *directory; char tmp[PATH_MAX]; bool added = false, found = false; directory = base_dir_xptr(mask); if((dp = opendir(directory ? directory : ".")) == 0) { ftp_err("Unable to read directory %s\n", directory ? directory : "."); return -1; } if (!getcwd(tmp, PATH_MAX)) { if (ERANGE == errno) { ftp_err("cwd too long\n"); } else { ftp_err("getcwd(): %s\n", strerror(errno)); } return -1; } while((de = readdir(dp)) != 0) { char *path; asprintf(&path, "%s/%s", directory ? directory : ".", de->d_name); if(fnmatch(base_name_ptr(mask), de->d_name, 0) == 0) { if(!(exclude_func && exclude_func(path))) { char *p; bool ignore_item; p = path_absolute(path, tmp, gvLocalHomeDir); ignore_item = (ignore_multiples && (list_search(gl, (listsearchfunc)strcmp, p) != 0)); if(!ignore_item) { list_additem(gl, p); added = true; } } found = true; } free(path); } closedir(dp); if(!found) { ftp_err("%s: no matches found\n", mask); return -1; } return added ? 0 : -1; }
void listify_string(const char *str, list *lp) { char *e; char *s, *orgs; orgs = s = xstrdup(str); while((e = strqsep(&s, ':')) != 0) { if(list_search(lp, (listsearchfunc)strcmp, e) == 0) list_additem(lp, xstrdup(e)); } free(orgs); }
list *list_clone(list *lp, listclonefunc clonefunc) { list *cloned; listitem *li; if(!lp) return 0; cloned = list_new(lp->freefunc); for(li=lp->first; li; li=li->next) list_additem(cloned, clonefunc(li->data)); return cloned; }
int rdir_parse(rdirectory *rdir, FILE *fp, const char *path, bool is_mlsd) { char tmp[257]; rfile *f; int r; bool failed = false; free(rdir->path); rdir->path = 0; list_clear(rdir->files); rdir->timestamp = time(0); f = rfile_create(); ftp_trace("*** start parsing directory listing of '%s' ***\n", path); while(!feof(fp)) { if(fgets(tmp, 256, fp) == 0) break; strip_trailing_chars(tmp, "\r\n"); if(tmp[0] == 0) break; ftp_trace("%s\n", tmp); rfile_clear(f); r = rfile_parse(f, tmp, path, is_mlsd); if(r == -1) { ftp_err("parsing failed on '%s'\n", tmp); list_clear(rdir->files); failed = true; } else if(r == 0) list_additem(rdir->files, (void *)rfile_clone(f)); /* else r == 1, ie a 'total ###' line, which isn't an error */ } ftp_trace("*** end parsing directory listing ***\n"); if(failed) { if(list_numitem(rdir->files) == 0) { ftp_err("directory parsing failed completely\n"); return -1; } } rdir->path = xstrdup(path); return 0; }
rdirectory *ftp_read_directory(const char *path) { FILE *fp = 0; rdirectory *rdir; bool is_curdir = false; bool _failed = false; char *dir; bool is_mlsd = false; #ifdef HAVE_LIBSSH if(ftp->session) return ssh_read_directory(path); #endif dir = ftp_path_absolute(path); stripslash(dir); is_curdir = (strcmp(dir, ftp->curdir) == 0); if((fp = tmpfile()) == NULL) { /* can't create a tmpfile */ ftp_err("Unable to create temp file: %s\n", strerror(errno)); free(dir); return 0; } /* we do a "CWD" before the listing, because: we want a listing of * the directory contents, not the directory itself, and some * servers misunderstand this. If the target is a link to a * directory, we have to do this. */ if(!is_curdir) { ftp_cmd("CWD %s", dir); if(ftp->code != ctComplete) goto failed; } if(ftp->has_mlsd_command) { is_mlsd = true; #if 0 /* PureFTPd (1.0.11) doesn't recognize directory arguments * with spaces, not even quoted, it just chops the argument * string after the first space, duh... so we have to CWD to * the directory... */ char *asdf; asprintf(&asdf, "%s/", dir); /* Hack to get around issue in PureFTPd (up to version 0.98.2): * doing a 'MLSD link-to-dir' on PureFTPd closes the control * connection, however, 'MLSD link-to-dir/' works fine. */ _failed = (ftp_list("MLSD", asdf, fp) != 0); free(asdf); #else _failed = (ftp_list("MLSD", 0, fp) != 0); #endif if(_failed && ftp->code == ctError) ftp->has_mlsd_command = false; } if(!ftp->has_mlsd_command) { _failed = (ftp_list("LIST", 0, fp) != 0); is_mlsd = false; } if(!is_curdir) ftp_cmd("CWD %s", ftp->curdir); if(_failed) goto failed; rewind(fp); rdir = rdir_create(); if(rdir_parse(rdir, fp, dir, is_mlsd) != 0) { rdir_destroy(rdir); goto failed; } fclose(fp); ftp_trace("added directory '%s' to cache\n", dir); list_additem(ftp->cache, rdir); free(dir); return rdir; failed: /* forgive me father, for I have goto'ed */ if (fp) fclose(fp); free(dir); return 0; }
/* appends rglob items in list LP matching MASK * EXCLUDE_FUNC (if not 0) is called for each fileinfo item found * and that file is excluded if EXCLUDE_FUNC returns true * returns 0 if successful, -1 if failure (no files found) * * if ignore_multiples is true, a file isn't added to the list * if it already exists in the list * * any spaces or other strange characters in MASK should be backslash-quoted */ int rglob_glob(list *gl, const char *mask, bool cpifnomatch, bool ignore_multiples, rglobfunc exclude_func) { char *path; char *dep, *mp; rdirectory *rdir; listitem *lip; rfile *fi = 0, *nfi; char *d; int found = 0; path = tilde_expand_home(mask, ftp->homedir); dep = strrchr(path, '/'); if(!dep) dep = path; else dep++; mp = xstrdup(dep); if(mp) unquote(mp); /* note: mp might be NULL here, treat it like mp == "*" */ /* read the directory */ d = base_dir_xptr(path); if(!d) d = xstrdup(ftp->curdir); else unquote(d); rdir = ftp_get_directory(d); free(d); if(rdir) { lip = rdir->files->first; while(lip) { fi = (rfile *)lip->data; lip = lip->next; /* check if the mask includes this file */ if(mp == 0 || fnmatch(mp, base_name_ptr(fi->path), 0) != FNM_NOMATCH) { bool ignore_item; found++; /* call the exclude function, if any, and skip file if the function returns true */ if(exclude_func && exclude_func(fi)) ignore_item = true; else ignore_item = (ignore_multiples && (list_search(gl, (listsearchfunc)rfile_search_path, fi->path) != 0)); if(!ignore_item) { nfi = rfile_clone(fi); list_additem(gl, (void *)nfi); } else ftp_trace("ignoring file '%s'\n", fi->path); } } } if(found == 0) { char *p; bool ignore_item; if(!cpifnomatch || mp == 0 || *mp == 0) { free(mp); return -1; } p = ftp_path_absolute(path); unquote(p); /* disallow multiples of the same file */ ignore_item = (ignore_multiples && (list_search(gl, (listsearchfunc)rfile_search_path, p)) != 0); if(!ignore_item) { nfi = rfile_create(); rfile_fake(nfi, p); list_additem(gl, (void *)nfi); } free(p); } free(mp); free(path); return 0; }
rdirectory *ssh_read_directory(const char *path) { char *p = ftp_path_absolute(path); stripslash(p); sftp_dir dir = sftp_opendir(ftp->sftp_session, p); if (!dir) { free(p); return 0; } ftp_trace("*** start parsing directory listing ***\n"); rdirectory* rdir = rdir_create(); sftp_attributes attrib = NULL; while ((attrib = sftp_readdir(ftp->sftp_session, dir)) != NULL) { ftp_trace("%s\n", attrib->longname); rfile* rf = rfile_create(); rf->perm = perm2string(attrib->permissions); rf->nhl = 0; // atoi(e); if (attrib->owner) rf->owner = xstrdup(attrib->owner); if (attrib->group) rf->group = xstrdup(attrib->group); if (asprintf(&rf->path, "%s/%s", p, attrib->name) == -1) { ftp_err(_("Failed to allocate memory.\n")); sftp_closedir(dir); free(p); rdir_destroy(rdir); rfile_destroy(rf); } rf->mtime = attrib->mtime; rf->date = time_to_string(rf->mtime); rf->size = attrib->size; rfile_parse_colors(rf); rf->link = NULL; if (rislink(rf) && ftp->ssh_version > 2) rf->link = sftp_readlink(ftp->sftp_session, rf->path); list_additem(rdir->files, (void *)rf); sftp_attributes_free(attrib); } ftp_trace("*** end parsing directory listing ***\n"); if (!sftp_dir_eof(dir)) { ftp_err(_("Couldn't list directory: %s\n"), ssh_get_error(ftp->session)); sftp_closedir(dir); free(p); rdir_destroy(rdir); return NULL; } sftp_closedir(dir); rdir->path = p; ftp_trace("added directory '%s' to cache\n", p); list_additem(ftp->cache, rdir); return rdir; }
int compare(const char *filepath) { char *subpath = pathtrim(filepath); debug_msg("Comparing File: %s", filepath); file_count++; // ignore if no read permission if (check_privilege(filepath)) { verbose_msg("Ignore file: %s due to privilege limitation: %s", subpath, strerror(errno)); return -1; } struct stat buffer; int status; status = lstat(filepath, &buffer); if (status != 0) { verbose_msg("Fetch file status failed: $s: %s, Error code: %d", subpath, strerror(errno), errno); return -1; } // find the linked list with the same file size and the same file type // st_mode & S_IFMT extract the file type code from a mode value. list *ls_search = list_new(buffer.st_size, (unsigned int)buffer.st_mode & S_IFMT); debug_msg("Size: %d, type: %u, status=%d", (int)ls_search->filesize, ls_search->filetype, status); // store the file info into the node list_node *newfile = node_new(filepath, buffer.st_size); // reference man page: http://man7.org/linux/man-pages/man3/tsearch.3.html // key points to the item to be searched for. rootp points to a variable which points to the root of the tree. list **lsp = (list **)tsearch((void *)ls_search, &tree_root, list_compare); // returns a pointer to the newly added item. list_node *finded_same; //0 true 1 false if (lsp == NULL) { debug_msg("Append child failed"); exit(1); } else { // Find the same file list *rls = *lsp; debug_msg("Listinfo Size: %d, type: %d", rls->filesize, rls->filetype); if (rls != ls_search) { // list exists debug_msg("A list already exists! Search the item."); // wheather the same file is in the list finded_same = is_samefile_inlist(rls, newfile); // add the item to the existing list if (finded_same != NULL) { debug_msg("Same file found!"); node_free(newfile); char *tmp_subpath = pathtrim(finded_same->filepath); printf("%s\t%s\n", tmp_subpath, subpath); num_du_files++; free(tmp_subpath); free(subpath); } else { list_additem(rls, newfile); } list_free(ls_search); } else { // list not exist list_additem(rls, newfile); debug_msg("Created a new list!"); } } memLimitCheck(); return 0; }
rdirectory *ssh_read_directory(const char *path) { rdirectory *rdir; int i; SFTP_DIRENT **dir; char *p = ftp_path_absolute(path); stripslash(p); if(ssh_readdir(p, &dir) != 0) { free(p); return 0; } rdir = rdir_create(); ftp_trace("*** start parsing directory listing ***\n"); for(i = 0; dir[i]; i++) { rfile *rf; char *e, *cf = dir[i]->longname; ftp_trace("%s\n", dir[i]->longname); rf = rfile_create(); rf->perm = perm2string(dir[i]->a.perm); e = strqsep(&cf, ' '); /* skip permissions */ e = strqsep(&cf, ' '); /* nhl? */ /* if(ftp->ssh_version > 2) {*/ rf->nhl = atoi(e); /* } else*/ /* rf->nhl = 0;*/ #if 1 e = strqsep(&cf, ' '); rf->owner = xstrdup(e); e = strqsep(&cf, ' '); rf->group = xstrdup(e); #else asprintf(&rf->owner, "%d", dir[i]->a.uid); asprintf(&rf->group, "%d", dir[i]->a.gid); #endif asprintf(&rf->path, "%s/%s", p, dir[i]->filename); rf->mtime = dir[i]->a.mtime; if(rf->mtime == 0) { char *m, *d, *y; while(e && month_number(e) == -1) e = strqsep(&cf, ' '); if(e) { m = e; d = strqsep(&cf, ' '); y = strqsep(&cf, ' '); ftp_trace("parsing time: m:%s d:%s y:%s\n", m, d, y); rfile_parse_time(rf, m, d, y); } } rf->date = time_to_string(rf->mtime); rf->size = dir[i]->a.size; rfile_parse_colors(rf); rf->link = 0; if(rislink(rf) && ftp->ssh_version > 2) rf->link = ssh_readlink(rf->path); list_additem(rdir->files, (void *)rf); } ftp_trace("*** end parsing directory listing ***\n"); ssh_free_dirents(dir); rdir->path = p; ftp_trace("added directory '%s' to cache\n", p); list_additem(ftp->cache, rdir); return rdir; }
void load_ltaglist(bool showerr, bool always_autoload, const char *alt_filename) { FILE *fp; char *f, *e = 0; unsigned n = 0; int c; char tmp[4096]; if(gvLoadTaglist == 0 && !always_autoload) return; if(alt_filename == 0) if (asprintf(&e, "%s/taglist.local", gvWorkingDirectory) == -1) { fprintf(stderr, _("Failed to allocate memory.\n")); return; } f = tilde_expand_home(alt_filename ? alt_filename : e, gvLocalHomeDir); free(e); fp = fopen(f, "r"); if(!fp) { if(showerr) { if(alt_filename) perror(alt_filename); else fprintf(stderr, _("No saved local taglist\n")); } free(f); return; } if(gvLoadTaglist == 2 && !always_autoload) { c = ask(ASKYES|ASKNO, ASKYES, _("Found saved local taglist, load it now?")); if(c == ASKNO) { fclose(fp); return; } } /* else gvLoadTaglist == 1 == yes */ if(fgets(tmp, 4096, fp) != 0) { strip_trailing_chars(tmp, "\n\r"); if(strcasecmp(tmp, "[yafc taglist]") != 0) { fprintf(stderr, "Not a Yafc taglist file: %s\n", f); fclose(fp); return; } } while(true) { if(fgets(tmp, 4096, fp) == 0) break; strip_trailing_chars(tmp, "\r\n"); if(tmp[0] == 0) continue; list_additem(gvLocalTagList, xstrdup(tmp)); n++; } if(n) fprintf(stderr, "Loaded %u files from saved local taglist %s\n", n, f); fclose(fp); if(alt_filename == 0) unlink(f); free(f); }