Exemple #1
0
void
copy(void)
{
    ARCHD *arcn;
    int res;
    int fddest;
    char *dest_pt;
    int dlen;
    int drem;
    int fdsrc = -1;
    struct stat sb;
    ARCHD archd;
    char dirbuf[PAXPATHLEN+1];

    arcn = &archd;
    /*
     * set up the destination dir path and make sure it is a directory. We
     * make sure we have a trailing / on the destination
     */
    dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
    if (dlen >= sizeof(dirbuf) ||
            (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
        paxwarn(1, "directory name is too long %s", dirptr);
        return;
    }
    dest_pt = dirbuf + dlen;
    if (*(dest_pt-1) != '/') {
        *dest_pt++ = '/';
        *dest_pt = '\0';
        ++dlen;
    }
    drem = PAXPATHLEN - dlen;

    if (stat(dirptr, &sb) < 0) {
        syswarn(1, errno, "Cannot access destination directory %s",
                dirptr);
        return;
    }
    if (!S_ISDIR(sb.st_mode)) {
        paxwarn(1, "Destination is not a directory %s", dirptr);
        return;
    }

    /*
     * start up the hard link table; file traversal routines and the
     * modification time and access mode database
     */
    if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
        return;

    /*
     * When we are doing interactive rename, we store the mapping of names
     * so we can fix up hard links files later in the archive.
     */
    if (iflag && (name_start() < 0))
        return;

    /*
     * set up to cp file trees
     */
    cp_start();

    /*
     * while there are files to archive, process them
     */
    while (next_file(arcn) == 0) {
        fdsrc = -1;

        /*
         * check if this file meets user specified options
         */
        if (sel_chk(arcn) != 0)
            continue;

        /*
         * if there is already a file in the destination directory with
         * the same name and it is newer, skip the one stored on the
         * archive.
         * NOTE: this test is done BEFORE name modifications as
         * specified by pax. this can be confusing to the user who
         * might expect the test to be done on an existing file AFTER
         * the name mod. In honesty the pax spec is probably flawed in
         * this respect
         */
        if (uflag || Dflag) {
            /*
             * create the destination name
             */
            if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
                        drem + 1) > drem) {
                paxwarn(1, "Destination pathname too long %s",
                        arcn->name);
                continue;
            }

            /*
             * if existing file is same age or newer skip
             */
            res = lstat(dirbuf, &sb);
            *dest_pt = '\0';

            if (res == 0) {
                if (uflag && Dflag) {
                    if ((arcn->sb.st_mtime<=sb.st_mtime) &&
                            (arcn->sb.st_ctime<=sb.st_ctime))
                        continue;
                } else if (Dflag) {
                    if (arcn->sb.st_ctime <= sb.st_ctime)
                        continue;
                } else if (arcn->sb.st_mtime <= sb.st_mtime)
                    continue;
            }
        }

        /*
         * this file is considered selected. See if this is a hard link
         * to a previous file; modify the name as requested by the
         * user; set the final destination.
         */
        ftree_sel(arcn);
        if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0))
            break;
        if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) {
            /*
             * skip file, purge from link table
             */
            purg_lnk(arcn);
            continue;
        }

        /*
         * Non standard -Y and -Z flag. When the existing file is
         * same age or newer skip
         */
        if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
            if (Yflag && Zflag) {
                if ((arcn->sb.st_mtime <= sb.st_mtime) &&
                        (arcn->sb.st_ctime <= sb.st_ctime))
                    continue;
            } else if (Yflag) {
                if (arcn->sb.st_ctime <= sb.st_ctime)
                    continue;
            } else if (arcn->sb.st_mtime <= sb.st_mtime)
                continue;
        }

        if (vflag) {
            (void)safe_print(arcn->name, listf);
            vfpart = 1;
        }
        ++flcnt;

        /*
         * try to create a hard link to the src file if requested
         * but make sure we are not trying to overwrite ourselves.
         */
        if (lflag)
            res = cross_lnk(arcn);
        else
            res = chk_same(arcn);
        if (res <= 0) {
            if (vflag && vfpart) {
                (void)putc('\n', listf);
                vfpart = 0;
            }
            continue;
        }

        /*
         * have to create a new file
         */
        if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
            /*
             * create a link or special file
             */
            if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
                res = lnk_creat(arcn);
            else
                res = node_creat(arcn);
            if (res < 0)
                purg_lnk(arcn);
            if (vflag && vfpart) {
                (void)putc('\n', listf);
                vfpart = 0;
            }
            continue;
        }

        /*
         * have to copy a regular file to the destination directory.
         * first open source file and then create the destination file
         */
        if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) {
            syswarn(1, errno, "Unable to open %s to read",
                    arcn->org_name);
            purg_lnk(arcn);
            continue;
        }
        if ((fddest = file_creat(arcn)) < 0) {
            rdfile_close(arcn, &fdsrc);
            purg_lnk(arcn);
            continue;
        }

        /*
         * copy source file data to the destination file
         */
        cp_file(arcn, fdsrc, fddest);
        file_close(arcn, fddest);
        rdfile_close(arcn, &fdsrc);

        if (vflag && vfpart) {
            (void)putc('\n', listf);
            vfpart = 0;
        }
    }

    /*
     * restore directory modes and times as required; make sure all
     * patterns were selected block off signals to avoid chance for
     * multiple entry into the cleanup code.
     */
    (void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
    ar_close();
    proc_dir();
    ftree_chk();
}
Exemple #2
0
void
list(void)
{
    ARCHD *arcn;
    int res;
    ARCHD archd;
    time_t now;

    arcn = &archd;
    /*
     * figure out archive type; pass any format specific options to the
     * archive option processing routine; call the format init routine. We
     * also save current time for ls_list() so we do not make a system
     * call for each file we need to print. If verbose (vflag) start up
     * the name and group caches.
     */
    if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
            ((*frmt->st_rd)() < 0))
        return;

    if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0)))
        return;

    now = time(NULL);

    /*
     * step through the archive until the format says it is done
     */
    while (next_head(arcn) == 0) {
        if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
            /*
             * we need to read, to get the real filename
             */
            off_t cnt;
            if (!(*frmt->rd_data)(arcn, -1, &cnt));
            (void)rd_skip(cnt + arcn->pad);
            continue;
        }

        /*
         * check for pattern, and user specified options match.
         * When all patterns are matched we are done.
         */
        if ((res = pat_match(arcn)) < 0)
            break;

        if ((res == 0) && (sel_chk(arcn) == 0)) {
            /*
             * pattern resulted in a selected file
             */
            if (pat_sel(arcn) < 0)
                break;

            /*
             * modify the name as requested by the user if name
             * survives modification, do a listing of the file
             */
            if ((res = mod_name(arcn)) < 0)
                break;
            if (res == 0)
                ls_list(arcn, now, stdout);
        }

        /*
         * skip to next archive format header using values calculated
         * by the format header read routine
         */
        if (rd_skip(arcn->skip + arcn->pad) == 1)
            break;
    }

    /*
     * all done, let format have a chance to cleanup, and make sure that
     * the patterns supplied by the user were all matched
     */
    (void)(*frmt->end_rd)();
    (void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
    ar_close();
    pat_chk();
}
Exemple #3
0
static void
wr_archive(ARCHD *arcn, int is_app)
{
    int res;
    int hlk;
    int wr_one;
    off_t cnt;
    int (*wrf)();
    int fd = -1;
    time_t now;

    /*
     * if this format supports hard link storage, start up the database
     * that detects them.
     */
    if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
        return;

    /*
     * start up the file traversal code and format specific write
     */
    if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
        return;
    wrf = frmt->wr;

    /*
     * When we are doing interactive rename, we store the mapping of names
     * so we can fix up hard links files later in the archive.
     */
    if (iflag && (name_start() < 0))
        return;

    /*
     * if this is not append, and there are no files, we do not write a
     * trailer
     */
    wr_one = is_app;

    now = time(NULL);

    /*
     * while there are files to archive, process them one at at time
     */
    while (next_file(arcn) == 0) {
        /*
         * check if this file meets user specified options match.
         */
        if (sel_chk(arcn) != 0)
            continue;
        fd = -1;
        if (uflag) {
            /*
             * only archive if this file is newer than a file with
             * the same name that is already stored on the archive
             */
            if ((res = chk_ftime(arcn)) < 0)
                break;
            if (res > 0)
                continue;
        }

        /*
         * this file is considered selected now. see if this is a hard
         * link to a file already stored
         */
        ftree_sel(arcn);
        if (hlk && (chk_lnk(arcn) < 0))
            break;

        if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) ||
                (arcn->type == PAX_CTG)) {
            /*
             * we will have to read this file. by opening it now we
             * can avoid writing a header to the archive for a file
             * we were later unable to read (we also purge it from
             * the link table).
             */
            if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {
                syswarn(1,errno, "Unable to open %s to read",
                        arcn->org_name);
                purg_lnk(arcn);
                continue;
            }
        }

        /*
         * Now modify the name as requested by the user
         */
        if ((res = mod_name(arcn)) < 0) {
            /*
             * name modification says to skip this file, close the
             * file and purge link table entry
             */
            rdfile_close(arcn, &fd);
            purg_lnk(arcn);
            break;
        }

        if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
            /*
             * unable to obtain the crc we need, close the file,
             * purge link table entry
             */
            rdfile_close(arcn, &fd);
            purg_lnk(arcn);
            continue;
        }

        if (vflag) {
            if (vflag > 1)
                ls_list(arcn, now, listf);
            else {
                (void)safe_print(arcn->name, listf);
                vfpart = 1;
            }
        }
        ++flcnt;

        /*
         * looks safe to store the file, have the format specific
         * routine write routine store the file header on the archive
         */
        if ((res = (*wrf)(arcn)) < 0) {
            rdfile_close(arcn, &fd);
            break;
        }
        wr_one = 1;
        if (res > 0) {
            /*
             * format write says no file data needs to be stored
             * so we are done messing with this file
             */
            if (vflag && vfpart) {
                (void)putc('\n', listf);
                vfpart = 0;
            }
            rdfile_close(arcn, &fd);
            continue;
        }

        /*
         * Add file data to the archive, quit on write error. if we
         * cannot write the entire file contents to the archive we
         * must pad the archive to replace the missing file data
         * (otherwise during an extract the file header for the file
         * which FOLLOWS this one will not be where we expect it to
         * be).
         */
        res = (*frmt->wr_data)(arcn, fd, &cnt);
        rdfile_close(arcn, &fd);
        if (vflag && vfpart) {
            (void)putc('\n', listf);
            vfpart = 0;
        }
        if (res < 0)
            break;

        /*
         * pad as required, cnt is number of bytes not written
         */
        if (((cnt > 0) && (wr_skip(cnt) < 0)) ||
                ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0)))
            break;
    }

    /*
     * tell format to write trailer; pad to block boundary; reset directory
     * mode/access times, and check if all patterns supplied by the user
     * were matched. block off signals to avoid chance for multiple entry
     * into the cleanup code
     */
    if (wr_one) {
        (*frmt->end_wr)();
        wr_fin();
    }
    (void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
    ar_close();
    if (tflag)
        proc_dir();
    ftree_chk();
}
Exemple #4
0
void
extract(void)
{
    ARCHD *arcn;
    int res;
    off_t cnt;
    ARCHD archd;
    struct stat sb;
    int fd;
    time_t now;

    arcn = &archd;
    /*
     * figure out archive type; pass any format specific options to the
     * archive option processing routine; call the format init routine;
     * start up the directory modification time and access mode database
     */
    if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
            ((*frmt->st_rd)() < 0) || (dir_start() < 0))
        return;

    /*
     * When we are doing interactive rename, we store the mapping of names
     * so we can fix up hard links files later in the archive.
     */
    if (iflag && (name_start() < 0))
        return;

    now = time(NULL);

    /*
     * step through each entry on the archive until the format read routine
     * says it is done
     */
    while (next_head(arcn) == 0) {
        if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
            /*
             * we need to read, to get the real filename
             */
            if (!(*frmt->rd_data)(arcn, -1, &cnt));
            (void)rd_skip(cnt + arcn->pad);
            continue;
        }

        /*
         * check for pattern, and user specified options match. When
         * all the patterns are matched we are done
         */
        if ((res = pat_match(arcn)) < 0)
            break;

        if ((res > 0) || (sel_chk(arcn) != 0)) {
            /*
             * file is not selected. skip past any file data and
             * padding and go back for the next archive member
             */
            (void)rd_skip(arcn->skip + arcn->pad);
            continue;
        }

        /*
         * with -u or -D only extract when the archive member is newer
         * than the file with the same name in the file system (no
         * test of being the same type is required).
         * NOTE: this test is done BEFORE name modifications as
         * specified by pax. this operation can be confusing to the
         * user who might expect the test to be done on an existing
         * file AFTER the name mod. In honesty the pax spec is probably
         * flawed in this respect.
         */
        if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
            if (uflag && Dflag) {
                if ((arcn->sb.st_mtime <= sb.st_mtime) &&
                        (arcn->sb.st_ctime <= sb.st_ctime)) {
                    (void)rd_skip(arcn->skip + arcn->pad);
                    continue;
                }
            } else if (Dflag) {
                if (arcn->sb.st_ctime <= sb.st_ctime) {
                    (void)rd_skip(arcn->skip + arcn->pad);
                    continue;
                }
            } else if (arcn->sb.st_mtime <= sb.st_mtime) {
                (void)rd_skip(arcn->skip + arcn->pad);
                continue;
            }
        }

        /*
         * this archive member is now been selected. modify the name.
         */
        if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
            break;
        if (res > 0) {
            /*
             * a bad name mod, skip and purge name from link table
             */
            purg_lnk(arcn);
            (void)rd_skip(arcn->skip + arcn->pad);
            continue;
        }

        /*
         * Non standard -Y and -Z flag. When the existing file is
         * same age or newer skip
         */
        if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
            if (Yflag && Zflag) {
                if ((arcn->sb.st_mtime <= sb.st_mtime) &&
                        (arcn->sb.st_ctime <= sb.st_ctime)) {
                    (void)rd_skip(arcn->skip + arcn->pad);
                    continue;
                }
            } else if (Yflag) {
                if (arcn->sb.st_ctime <= sb.st_ctime) {
                    (void)rd_skip(arcn->skip + arcn->pad);
                    continue;
                }
            } else if (arcn->sb.st_mtime <= sb.st_mtime) {
                (void)rd_skip(arcn->skip + arcn->pad);
                continue;
            }
        }

        if (vflag) {
            if (vflag > 1)
                ls_list(arcn, now, listf);
            else {
                (void)safe_print(arcn->name, listf);
                vfpart = 1;
            }
        }

        /*
         * if required, chdir around.
         */
        if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
            if (chdir(arcn->pat->chdname) != 0)
                syswarn(1, errno, "Cannot chdir to %s",
                        arcn->pat->chdname);

        /*
         * all ok, extract this member based on type
         */
        if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
            /*
             * process archive members that are not regular files.
             * throw out padding and any data that might follow the
             * header (as determined by the format).
             */
            if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
                res = lnk_creat(arcn);
            else
                res = node_creat(arcn);

            (void)rd_skip(arcn->skip + arcn->pad);
            if (res < 0)
                purg_lnk(arcn);

            if (vflag && vfpart) {
                (void)putc('\n', listf);
                vfpart = 0;
            }
            continue;
        }
        /*
         * we have a file with data here. If we can not create it, skip
         * over the data and purge the name from hard link table
         */
        if ((fd = file_creat(arcn)) < 0) {
            (void)rd_skip(arcn->skip + arcn->pad);
            purg_lnk(arcn);
            continue;
        }
        /*
         * extract the file from the archive and skip over padding and
         * any unprocessed data
         */
        res = (*frmt->rd_data)(arcn, fd, &cnt);
        file_close(arcn, fd);
        if (vflag && vfpart) {
            (void)putc('\n', listf);
            vfpart = 0;
        }
        if (!res)
            (void)rd_skip(cnt + arcn->pad);

        /*
         * if required, chdir around.
         */
        if ((arcn->pat != NULL) && (arcn->pat->chdname != NULL))
            if (fchdir(cwdfd) != 0)
                syswarn(1, errno,
                        "Can't fchdir to starting directory");
    }

    /*
     * all done, restore directory modes and times as required; make sure
     * all patterns supplied by the user were matched; block off signals
     * to avoid chance for multiple entry into the cleanup code.
     */
    (void)(*frmt->end_rd)();
    (void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
    ar_close();
    proc_dir();
    pat_chk();
}
Exemple #5
0
int main(int argc, char **argv) {
	const struct mod *mod, *dep;
	const char *substr_package = NULL, *substr_name = NULL;
	int print_deps = 0, show_label = 0, integrity_check = 0;
	int opt;

	while (-1 != (opt = getopt(argc, argv, "qdclhp:n:"))) {
		switch (opt) {
		case 'd':
			print_deps = 1;
			break;
		case 'c':
			integrity_check = 1;
			break;
		case 'h':
			print_usage();
			return 0;
		case 'p':
			substr_package = optarg;
			break;
		case 'n':
			substr_name = optarg;
			break;
		case 'l':
			show_label = 1;
			break;
		case '?':
			break;
		default:
			return -EINVAL;
		}
	}

	mod_foreach(mod) {
		if ((substr_package && !strstr(mod_pkg_name(mod), substr_package)) ||
			(substr_name && !strstr(mod_name(mod), substr_name))) {
			continue;
		}
		mod_print(mod);
		printf("\n");
		if (show_label) {
			printf("\tlabel:%x:%x:%x:%x\n",
					(uint32_t)mod_label(mod)->text.vma,
					(uint32_t)mod_label(mod)->data.vma,
					(uint32_t)mod_label(mod)->bss.vma,
					(uint32_t)mod_label(mod)->rodata.vma);
		}

		if (integrity_check) {
			int check = mod_integrity_check(mod);

			printf("\tintegrity: ");

			if (check < 0) {
				printf("error: %s\n", strerror(-check));
			} else if (check == 0) {
				printf("OK\n");
			} else {
				printf("FAIL\n");
			}
		}

		if (print_deps) {
			printf("\n\t-> ");
			mod_foreach_requires(dep, mod) {
				mod_print(dep);
			}

			printf("\n\t<- ");
			mod_foreach_provides(dep, mod) {
				mod_print(dep);
			}

			printf("\n");
		}
Exemple #6
0
static void mod_print(const struct mod *mod) {
	int enabled = mod->priv->flags & 0x1; // XXX fix later
	printf(" %c  %s.%s ", enabled ? '*' : ' ', mod_pkg_name(mod), mod_name(mod));
}
Exemple #7
0
int
list(void)
{
	ARCHD *arcn;
	int res;
	time_t now;

	arcn = &archd;
	/*
	 * figure out archive type; pass any format specific options to the
	 * archive option processing routine; call the format init routine. We
	 * also save current time for ls_list() so we do not make a system
	 * call for each file we need to print. If verbose (vflag) start up
	 * the name and group caches.
	 */
	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
	    ((*frmt->st_rd)() < 0))
		return 1;

	now = time(NULL);

	/*
	 * step through the archive until the format says it is done
	 */
	while (next_head(arcn) == 0) {
		if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
			/*
			 * we need to read, to get the real filename
			 */
			off_t cnt;
			if (!(*frmt->rd_data)(arcn, -arcn->type, &cnt))
				(void)rd_skip(cnt + arcn->pad);
			continue;
		}

		/*
		 * check for pattern, and user specified options match.
		 * When all patterns are matched we are done.
		 */
		if ((res = pat_match(arcn)) < 0)
			break;

		if ((res == 0) && (sel_chk(arcn) == 0)) {
			/*
			 * pattern resulted in a selected file
			 */
			if (pat_sel(arcn) < 0)
				break;

			/*
			 * modify the name as requested by the user if name
			 * survives modification, do a listing of the file
			 */
			if ((res = mod_name(arcn, RENM)) < 0)
				break;
			if (res == 0) {
				if (arcn->name[0] == '/' && !check_Aflag()) {
					memmove(arcn->name, arcn->name + 1, 
					    strlen(arcn->name));
				}
				ls_list(arcn, now, stdout);
			}
			/*
			 * if there's an error writing to stdout then we must
			 * stop now -- we're probably writing to a pipe that
			 * has been closed by the reader.
			 */
			if (ferror(stdout)) {
				syswarn(1, errno, "Listing incomplete.");
				break;
			}
		}
		/*
		 * skip to next archive format header using values calculated
		 * by the format header read routine
		 */
		if (rd_skip(arcn->skip + arcn->pad) == 1)
			break;
	}

	/*
	 * all done, let format have a chance to cleanup, and make sure that
	 * the patterns supplied by the user were all matched
	 */
	(void)(*frmt->end_rd)();
	(void)sigprocmask(SIG_BLOCK, &s_mask, NULL);
	ar_close();
	pat_chk();

	return 0;
}