int main(int argc, char* argv[]) { char dirname[256]; UINT len; FILE *f = stdout; if (argc < 2) { fprintf(stderr, "Please specify directory.\n"); return 1; } strcpy(dirname, argv[1]); header.magic = INITRD_MAGIC; header.inodecount = count_of_inodes(dirname, 1) + 1; header.entries = 0; if (!header.inodecount) return 2; len = sizeof(initrd_header) + header.inodecount * sizeof(initrd_inode); expand_initrd(len); memset(inodes, 0, header.inodecount * sizeof(initrd_inode)); savedir(dirname, -1); *((initrd_header*)(filebuf)) = header; //f=fopen("initrd.img","w"); fwrite(filebuf, filelen, 1, f); //fclose(f); return 0; }
static int copy_dir (const char *src_path_in, const char *dst_path_in, int new_dst, const struct stat *src_sb, struct dir_list *ancestors, const struct cp_options *x, int *copy_into_self) { char *name_space; char *namep; struct cp_options non_command_line_options = *x; int ret = 0; name_space = savedir (src_path_in); if (name_space == NULL) { /* This diagnostic is a bit vague because savedir can fail in several different ways. */ error (0, errno, _("cannot access %s"), quote (src_path_in)); return -1; } /* For cp's -H option, dereference command line arguments, but do not dereference symlinks that are found via recursive traversal. */ if (x->dereference == DEREF_COMMAND_LINE_ARGUMENTS) non_command_line_options.xstat = lstat; namep = name_space; while (*namep != '\0') { int local_copy_into_self; char *src_path = path_concat (src_path_in, namep, NULL); char *dst_path = path_concat (dst_path_in, namep, NULL); if (dst_path == NULL || src_path == NULL) xalloc_die (); ret |= copy_internal (src_path, dst_path, new_dst, src_sb->st_dev, ancestors, &non_command_line_options, 0, &local_copy_into_self, NULL); *copy_into_self |= local_copy_into_self; free (dst_path); free (src_path); namep += strlen (namep) + 1; } free (name_space); return -ret; }
UINT savefile(char *filename, UCHAR d_type, UINT parent_inode) { if (d_type == DT_DIR) return savedir(filename, parent_inode); initrd_inode inode; UCHAR *data; FILE *f; createinode(filename, &inode, FS_FILE); fprintf(stderr, "\tOpen file %s\n", filename); header.entries++; data = expand_initrd(inode.size); f = fopen(filename, "r"); fread(data, inode.size, 1, f); fclose(f); inodes[inode.inode] = inode; return inode.inode; }
int c_flush(C_FILE * fptr) { int it; if (!(fptr->c_flag & WRITE)) { fprintf(stderr, "no write access"); return EOF; } fptr->c_seccnt += blksiz / seclth; /* caution: blockno() might evaluate its argument twice */ if (putblock(blockno(fptr->c_blk), fptr->c_base, -1) == EOF) return EOF; fptr->c_blk++; if (fptr->c_blk == (use16bitptrs ? 8 : 16)) { fptr->c_dirp->blkcnt = (char) 0x80; savedir(); /* create new extent */ if ((it = creext(fptr->c_ext)) == 0) { fprintf(stderr, "can't create new extent, current: %d\n", fptr->c_ext); return EOF; } fptr->c_dirp = dirbuf + it; fptr->c_ext = it; fptr->c_blk = 0; fptr->c_seccnt = 0; fptr->c_extno++; fptr->c_dirp->extno = fptr->c_extno; } fptr->c_buf = fptr->c_base; fptr->c_cnt = blksiz; if ((it = alloc()) == '\0') { fprintf(stderr, "disk full\n"); return EOF; } if (use16bitptrs) { fptr->c_dirp->pointers[2 * fptr->c_blk] = it & 0xff; fptr->c_dirp->pointers[2 * fptr->c_blk + 1] = (it >> 8) & 0xff; } else
/* Recursively scan the given directory DIR. DEVICE is the device number where DIR resides (for --one-file-system). If CMDLINE is true, the directory name was explicitly listed in the command line. Unless *PDIR is NULL, store there a pointer to the struct directory describing DIR. */ struct directory * scan_directory (char *dir, dev_t device, bool cmdline) { char *dirp = savedir (dir); /* for scanning directory */ namebuf_t nbuf; char *tmp; struct stat stat_data; struct directory *directory; char ch; if (! dirp) savedir_error (dir); tmp = xstrdup (dir); zap_slashes (tmp); if (deref_stat (dereference_option, tmp, &stat_data)) { dir_removed_diag (tmp, cmdline, stat_diag); free (tmp); free (dirp); return NULL; } directory = procdir (tmp, &stat_data, device, (cmdline ? PD_FORCE_INIT : 0), &ch); free (tmp); nbuf = namebuf_create (dir); if (dirp && directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ dumpdir_iter_t itr; makedumpdir (directory, dirp); for (entry = dumpdir_first (directory->dump, 1, &itr); entry; entry = dumpdir_next (itr)) { char *full_name = namebuf_name (nbuf, entry + 1); if (*entry == 'I') /* Ignored entry */ *entry = 'N'; else if (excluded_name (full_name)) *entry = 'N'; else { if (deref_stat (dereference_option, full_name, &stat_data)) { file_removed_diag (full_name, false, stat_diag); *entry = 'N'; continue; } if (S_ISDIR (stat_data.st_mode)) { int pd_flag = 0; if (!recursion_option) pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN; else if (directory->children == ALL_CHILDREN) pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; *entry = 'D'; procdir (full_name, &stat_data, device, pd_flag, entry); } else if (one_file_system_option && device != stat_data.st_dev) *entry = 'N'; else if (*entry == 'Y') /* New entry, skip further checks */; /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ else if (OLDER_STAT_TIME (stat_data, m) && (!after_date_option || OLDER_STAT_TIME (stat_data, c))) *entry = 'N'; else *entry = 'Y'; } } free (itr); } namebuf_free (nbuf); if (dirp) free (dirp); return directory; }
/* Examine the directories under directory_name and delete any files that were not there at the time of the back-up. */ static bool try_purge_directory (char const *directory_name) { char *current_dir; char *cur, *arc, *p; char *temp_stub = NULL; struct dumpdir *dump; if (!is_dumpdir (¤t_stat_info)) return false; current_dir = savedir (directory_name); if (!current_dir) /* The directory doesn't exist now. It'll be created. In any case, we don't have to delete any files out of it. */ return false; /* Verify if dump directory is sane */ if (!dumpdir_ok (current_stat_info.dumpdir)) return false; /* Process renames */ for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1) { if (*arc == 'X') { #define TEMP_DIR_TEMPLATE "tar.XXXXXX" size_t len = strlen (arc + 1); temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE); memcpy (temp_stub, arc + 1, len); temp_stub[len] = '/'; memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE, sizeof TEMP_DIR_TEMPLATE); if (!mkdtemp (temp_stub)) { ERROR ((0, errno, _("Cannot create temporary directory using template %s"), quote (temp_stub))); free (temp_stub); free (current_dir); return false; } } else if (*arc == 'R') { char *src, *dst; src = arc + 1; arc += strlen (arc) + 1; dst = arc + 1; /* Ensure that neither source nor destination are absolute file names (unless permitted by -P option), and that they do not contain dubious parts (e.g. ../). This is an extra safety precaution. Besides, it might be necessary to extract from archives created with tar versions prior to 1.19. */ if (*src) src = safer_name_suffix (src, false, absolute_names_option); if (*dst) dst = safer_name_suffix (dst, false, absolute_names_option); if (*src == 0) src = temp_stub; else if (*dst == 0) dst = temp_stub; if (!rename_directory (src, dst)) { free (temp_stub); free (current_dir); /* FIXME: Make sure purge_directory(dst) will return immediately */ return false; } } } free (temp_stub); /* Process deletes */ dump = dumpdir_create (current_stat_info.dumpdir); p = NULL; for (cur = current_dir; *cur; cur += strlen (cur) + 1) { const char *entry; struct stat st; if (p) free (p); p = new_name (directory_name, cur); if (deref_stat (false, p, &st)) { if (errno != ENOENT) /* FIXME: Maybe keep a list of renamed dirs and check it here? */ { stat_diag (p); WARN ((0, 0, _("%s: Not purging directory: unable to stat"), quotearg_colon (p))); } continue; } if (!(entry = dumpdir_locate (dump, cur)) || (*entry == 'D' && !S_ISDIR (st.st_mode)) || (*entry == 'Y' && S_ISDIR (st.st_mode))) { if (one_file_system_option && st.st_dev != root_device) { WARN ((0, 0, _("%s: directory is on a different device: not purging"), quotearg_colon (p))); continue; } if (! interactive_option || confirm ("delete", p)) { if (verbose_option) fprintf (stdlis, _("%s: Deleting %s\n"), program_name, quote (p)); if (! remove_any_file (p, RECURSIVE_REMOVE_OPTION)) { int e = errno; ERROR ((0, e, _("%s: Cannot remove"), quotearg_colon (p))); } } } } free (p); dumpdir_free (dump); free (current_dir); return true; }
static long count_entry (char *ent, int top, dev_t last_dev) { long size; if (((top && opt_dereference_arguments) ? stat (ent, &stat_buf) : (*xstat) (ent, &stat_buf)) < 0) { error (0, errno, "%s", path->text); exit_status = 1; return 0; } if (!opt_count_all && stat_buf.st_nlink > 1 && hash_insert (stat_buf.st_ino, stat_buf.st_dev)) return 0; /* Have counted this already. */ if (output_size == size_bytes) size = stat_buf.st_size; else size = ST_NBLOCKS (stat_buf); tot_size += size; if (S_ISDIR (stat_buf.st_mode)) { unsigned pathlen; dev_t dir_dev; char *name_space; char *namep; struct saved_cwd cwd; int through_symlink; struct stat e_buf; dir_dev = stat_buf.st_dev; if (opt_one_file_system && !top && last_dev != dir_dev) return 0; /* Don't enter a new file system. */ #ifndef S_ISDIR # define S_ISDIR(s) 0 #endif /* If we're dereferencing symlinks and we're about to chdir through a symlink, remember the current directory so we can return to it later. In other cases, chdir ("..") works fine. */ through_symlink = (xstat == stat && lstat (ent, &e_buf) == 0 && S_ISLNK (e_buf.st_mode)); if (through_symlink) if (save_cwd (&cwd)) exit (1); if (chdir (ent) < 0) { error (0, errno, _("cannot change to directory %s"), path->text); exit_status = 1; return 0; } errno = 0; name_space = savedir (".", stat_buf.st_size); if (name_space == NULL) { if (errno) { error (0, errno, "%s", path->text); if (through_symlink) { if (restore_cwd (&cwd, "..", path->text)) exit (1); free_cwd (&cwd); } else if (chdir ("..") < 0) error (1, errno, _("cannot change to `..' from directory %s"), path->text); exit_status = 1; return 0; } else error (1, 0, _("virtual memory exhausted")); } /* Remember the current path. */ str_concatc (path, "/"); pathlen = path->length; namep = name_space; while (*namep != 0) { str_concatc (path, namep); size += count_entry (namep, 0, dir_dev); str_trunc (path, pathlen); namep += strlen (namep) + 1; } free (name_space); if (through_symlink) { restore_cwd (&cwd, "..", path->text); free_cwd (&cwd); } else if (chdir ("..") < 0) error (1, errno, _("cannot change to `..' from directory %s"), path->text); str_trunc (path, pathlen - 1); /* Remove the "/" we added. */ if (!opt_summarize_only || top) { if (opt_human_readable) { char buf[LONGEST_HUMAN_READABLE + 1]; printf("%s\t%s\n", human_readable (size, buf, LONGEST_HUMAN_READABLE + 1), path->length > 0 ? path->text : "/"); } else { printf ("%ld\t%s\n", (output_size == size_bytes ? size : convert_blocks (size, output_size)), path->length > 0 ? path->text : "/"); } fflush (stdout); } return opt_separate_dirs ? 0 : size; } else if (opt_all || top) { /* FIXME: make this an option. */ int print_only_dir_size = 0; if (!print_only_dir_size) { if (opt_human_readable) { char buf[LONGEST_HUMAN_READABLE + 1]; printf("%s\t%s\n", human_readable (size, buf, LONGEST_HUMAN_READABLE + 1), path->length > 0 ? path->text : "/"); } else { printf ("%ld\t%s\n", output_size == size_bytes ? size : convert_blocks (size, output_size), path->text); } fflush (stdout); } } return size; }
void huntmain(int argc,char **argv) { /* read query from stdin, expect name of indexes in argv[1] */ static FILE *fa, *fb, *fc; char indexname[PATH_MAX], *qitem[100], *rprog = 0; char grepquery[200]; static char oldname[30] ; static int nhash = 0; static int maxhash = 0; int falseflg = 0, nitem, nfound, frtbl; static long *hpt = 0; unsigned *masterp; # if D1 fprintf(stderr, "in glue1 argc %d argv %o %o\n", argc, argv[0],argv[1]); # endif savedir(); while (argv[1][0] == '-') { # if D1 fprintf(stderr, "argv.1 is %s\n",argv[1]); # endif switch(argv[1][1]) { case 'a': /* all output, incl. false drops */ falseflg = 1; break; case 'r': argc--; argv++; rprog = argv[1]; break; case 'F': /* put out full text */ full = setfrom(argv[1][2]); break; case 'T': /* put out tags */ tags = setfrom(argv[1][2]); break; case 'i': /* input in argument string */ argc--; argv++; sinput = argv[1]; break; case 's': /*text output to string */ case 'o': argc--; argv++; soutput = argv[1]; if ((intptr_t) argv[2]<16000) { soutlen = (intptr_t) argv[2]; argc--; argv++; } break; case 't': /*tag output to string */ argc--; argv++; tagout = argv[1]; if ((intptr_t)argv[2]<16000) { taglen = (intptr_t)argv[2]; argc--; argv++; } break; case 'l': /* specify length of lists */ argc--; argv++; lmaster = atoi(argv[1]); # if D1 fprintf(stderr, "lmaster now %d\n",lmaster); # endif break; case 'C': argc--; argv++; colevel = atoi(argv[1]); break; } argc--; argv++; } n_strcpy (indexname, todir(argv[1]), sizeof(indexname)); # if D1 fprintf(stderr, "in huntmain indexname %s typeindex %d\n", indexname, typeindex); # endif if (typeindex == 0 || strcmp (oldname, indexname) !=0) { n_strcpy (oldname, indexname, sizeof(oldname)); unopen(fa); unopen(fb); unopen(fc); if (ckexist(indexname, ".ib")) { # if D1 fprintf(stderr, "found old index\n"); # endif fa = iopen(indexname, ".ia"); fb = iopen(indexname, ".ib"); fc = iopen(indexname, ".ic"); typeindex =1; # if D1 fprintf(stderr, "opened f's as %o %o %o\n",fa,fb,fc); # endif indexdate = gdate(fb); fread (&nhash, sizeof(nhash), 1, fa); fread (&iflong, sizeof(iflong), 1, fa); if (nhash > maxhash) { if (hpt) free (hpt); hpt=0; if (hfreq) free(hfreq); hfreq=0; maxhash=nhash; # if D1 fprintf(stderr, "Freed if needed maxhash %d\n",maxhash); # endif } if (hpt==0) hpt = zalloc(nhash, sizeof(*hpt)); # if D1 fprintf(stderr, "hpt now %o\n",hpt); # endif if (hpt == NULL) err("No space for hash list (%d)", nhash); fread( hpt, sizeof(*hpt), nhash, fa); if (hfreq==0) hfreq=zalloc(nhash, sizeof(*hfreq)); if (hfreq==NULL) err("No space for hash frequencies (%d)", nhash); frtbl = fread(hfreq, sizeof(*hfreq), nhash, fa); hfrflg = (frtbl == nhash); # if D1 fprintf(stderr,"Read pointer files\n"); # endif if (master.a == NULL) { if (iflong) master.b = zalloc(lmaster, sizeof(long)); else master.a = zalloc(lmaster, sizeof(int)); } if (master.a == NULL) err("no space for answer list", 0); } else if (makefgrep(indexname)) typeindex=2; else { err("No files %s\n", indexname); exit(1); } } if (iflong) masterp = (unsigned *) master.b; else masterp = master.a; # if D1 fprintf(stderr, "typeindex now %d\n",typeindex); # endif tagout[0]=0; if (typeindex==2) { grepcall(sinput, tagout, indexname); # if D1 fprintf(stderr, " back from grepcall\n"); # endif restodir(); return; } nitem = getq(qitem); # if D1 fprintf(stderr, "approaching doquery fb %o\n", fb); # endif nfound = doquery(hpt, nhash, fb, nitem, qitem, masterp); # ifdef D1 fprintf(stderr, "return from doquery with nfound %d\n", nfound); # endif if (falseflg == 0) nfound = baddrop(masterp, nfound, fc, nitem, qitem, rprog, full); # ifdef D1 fprintf(stderr, "after baddrop with nfound %d\n",nfound); fprintf(stderr, "tagout is /%s/, sout /%s/\n",tagout, soutput); # endif if (tags) result (masterp, nfound >tags ? tags : nfound, fc); # if D1 fprintf(stderr, "done with huntmain\n"); fprintf(stderr, "tagout is /%s/\n", tagout); fprintf(stderr, "string out is /%s/\n", soutput); # endif if (fgnamp>fgnames) { char **fgp; int k; # if D1 fprintf(stderr, "were %d bad files\n", fgnamp-fgnames); # endif grepquery[0]=0; for(k=0; k<nitem; k++) { n_strcat(grepquery, " ", sizeof(grepquery)); n_strcat(grepquery, qitem[k], sizeof(grepquery)); } for(fgp=fgnames; fgp<fgnamp; fgp++) { # if D1 fprintf(stderr, "Now on %s query /%s/\n", *fgp, grepquery); # endif makefgrep(*fgp); grepcall(grepquery, tagout, *fgp); # if D1 fprintf(stderr, "tagout now /%s/\n", tagout); # endif } } restodir(); }
/* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory, then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME recursively; otherwise, remove it only if it is empty. If FILE_NAME is a directory that cannot be removed (e.g., because it is nonempty) and if OPTION is WANT_DIRECTORY_REMOVE_OPTION, then return -1. Return 0 on error, with errno set; if FILE_NAME is obviously the working directory return zero with errno set to zero. */ int remove_any_file (const char *file_name, enum remove_option option) { /* Try unlink first if we cannot unlink directories, as this saves us a system call in the common case where we're removing a non-directory. */ bool try_unlink_first = cannot_unlink_dir (); if (try_unlink_first) { if (unlinkat (chdir_fd, file_name, 0) == 0) return 1; /* POSIX 1003.1-2001 requires EPERM when attempting to unlink a directory without appropriate privileges, but many Linux kernels return the more-sensible EISDIR. */ if (errno != EPERM && errno != EISDIR) return 0; } if (safer_rmdir (file_name) == 0) return 1; switch (errno) { case ENOTDIR: return !try_unlink_first && unlinkat (chdir_fd, file_name, 0) == 0; case 0: case EEXIST: #if defined ENOTEMPTY && ENOTEMPTY != EEXIST case ENOTEMPTY: #endif switch (option) { case ORDINARY_REMOVE_OPTION: break; case WANT_DIRECTORY_REMOVE_OPTION: return -1; case RECURSIVE_REMOVE_OPTION: { char *directory = savedir (file_name); char const *entry; size_t entrylen; if (! directory) return 0; for (entry = directory; (entrylen = strlen (entry)) != 0; entry += entrylen + 1) { char *file_name_buffer = new_name (file_name, entry); int r = remove_any_file (file_name_buffer, RECURSIVE_REMOVE_OPTION); int e = errno; free (file_name_buffer); if (! r) { free (directory); errno = e; return 0; } } free (directory); return safer_rmdir (file_name) == 0; } } break; } return 0; }
/* Recursively scan the given directory. */ static const char * scan_directory (char *dir, dev_t device) { char *dirp = savedir (dir); /* for scanning directory */ char *name_buffer; /* directory, `/', and directory member */ size_t name_buffer_size; /* allocated size of name_buffer, minus 2 */ size_t name_length; /* used length in name_buffer */ struct stat stat_data; struct directory *directory; if (! dirp) savedir_error (dir); name_buffer_size = strlen (dir) + NAME_FIELD_SIZE; name_buffer = xmalloc (name_buffer_size + 2); strcpy (name_buffer, dir); if (! ISSLASH (dir[strlen (dir) - 1])) strcat (name_buffer, "/"); name_length = strlen (name_buffer); if (deref_stat (dereference_option, name_buffer, &stat_data)) { stat_diag (name_buffer); /* FIXME: used to be children = CHANGED_CHILDREN; but changed to: */ free (name_buffer); free (dirp); return NULL; } directory = procdir (name_buffer, &stat_data, device, 0, NULL); if (dirp && directory->children != NO_CHILDREN) { char *entry; /* directory entry being scanned */ size_t entrylen; /* length of directory entry */ dumpdir_iter_t itr; makedumpdir (directory, dirp); for (entry = dumpdir_first (directory->dump, 1, &itr); entry; entry = dumpdir_next (itr)) { entrylen = strlen (entry); if (name_buffer_size <= entrylen - 1 + name_length) { do name_buffer_size += NAME_FIELD_SIZE; while (name_buffer_size <= entrylen - 1 + name_length); name_buffer = xrealloc (name_buffer, name_buffer_size + 2); } strcpy (name_buffer + name_length, entry + 1); if (*entry == 'I') /* Ignored entry */ *entry = 'N'; else if (excluded_name (name_buffer)) *entry = 'N'; else { if (deref_stat (dereference_option, name_buffer, &stat_data)) { stat_diag (name_buffer); *entry = 'N'; continue; } if (S_ISDIR (stat_data.st_mode)) { int pd_flag = (verbose_option ? PD_VERBOSE : 0); if (!recursion_option) pd_flag |= PD_FORCE_CHILDREN | NO_CHILDREN; else if (directory->children == ALL_CHILDREN) pd_flag |= PD_FORCE_CHILDREN | ALL_CHILDREN; *entry = 'D'; procdir (name_buffer, &stat_data, device, pd_flag, entry); } else if (one_file_system_option && device != stat_data.st_dev) *entry = 'N'; else if (*entry == 'Y') /* New entry, skip further checks */; /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */ else if (OLDER_STAT_TIME (stat_data, m) && (!after_date_option || OLDER_STAT_TIME (stat_data, c))) *entry = 'N'; else *entry = 'Y'; } } free (itr); } free (name_buffer); if (dirp) free (dirp); return directory->dump ? directory->dump->contents : NULL; }