Esempio n. 1
0
int
rd_sync(void)
{
	int errcnt = 0;
	int res;

	/*
	 * if the user says bail out on first fault, we are out of here...
	 */
	if (maxflt == 0)
		return(-1);
	if (act == APPND) {
		paxwarn(1, "Unable to append when there are archive read errors.");
		return(-1);
	}

	/*
	 * poke at device and try to get past media error
	 */
	if (ar_rdsync() < 0) {
		if (ar_next() < 0)
			return(-1);
		else
			rdcnt = 0;
	}

	for (;;) {
		if ((res = ar_read(buf, blksz)) > 0) {
			/*
			 * All right! got some data, fill that buffer
			 */
			bufpt = buf;
			bufend = buf + res;
			rdcnt += res;
			return(0);
		}

		/*
		 * Oh well, yet another failed read...
		 * if error limit reached, ditch. o.w. poke device to move past
		 * bad media and try again. if media is badly damaged, we ask
		 * the poor (and upset user at this point) for the next archive
		 * volume. remember the goal on reads is to get the most we
		 * can extract out of the archive.
		 */
		if ((maxflt > 0) && (++errcnt > maxflt))
			paxwarn(0,"Archive read error limit (%d) reached",maxflt);
		else if (ar_rdsync() == 0)
			continue;
		if (ar_next() < 0)
			break;
		rdcnt = 0;
		errcnt = 0;
	}
	return(-1);
}
Esempio n. 2
0
int
rd_start()
#endif
{
	/*
	 * leave space for the header pushback (see get_arc()). If we are
	 * going to append and user specified a write block size, check it
	 * right away
	 */
	buf = &(bufmem[BLKMULT]);
	if ((act == APPND) && wrblksz) {
		if (wrblksz > MAXBLK) {
			warn(1,"Write block size %d too large, maximium is: %d",
				wrblksz, MAXBLK);
			return(-1);
		}
		if (wrblksz % BLKMULT) {
			warn(1, "Write block size %d is not a %d byte multiple",
		    	wrblksz, BLKMULT);
			return(-1);
		}
	}

	/*
	 * open the archive
	 */
	if ((ar_open(arcname) < 0) && (ar_next() < 0))
		return(-1);
	bufend = buf + rdblksz;
	bufpt = bufend;
	rdcnt = 0;
	return(0);
}
Esempio n. 3
0
int
buf_fill(void)
{
	int cnt;
	static int fini = 0;

	if (fini)
		return(0);

	for (;;) {
		/*
		 * try to fill the buffer. on error the next archive volume is
		 * opened and we try again.
		 */
		if ((cnt = ar_read(buf, blksz)) > 0) {
			bufpt = buf;
			bufend = buf + cnt;
			rdcnt += cnt;
			return(cnt);
		}

		/*
		 * errors require resync, EOF goes to next archive
		 */
		if (cnt < 0)
			break;
		if (ar_next() < 0) {
			fini = 1;
			return(0);
		}
		rdcnt = 0;
	}
	exit_val = 1;
	return(-1);
}
Esempio n. 4
0
/* scan an archive of Mach-Os */
static int scanmacho_archive(const char *filename, int fd, size_t len)
{
	archive_handle *ar;
	archive_member *m;
	char *ar_buffer;
	fatobj *fobj;
	fatobj *walk;

	ar = ar_open_fd(filename, fd);
	if (ar == NULL)
		return 1;

	ar_buffer = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
	while ((m = ar_next(ar)) != NULL) {
		fobj = readmacho_buffer(m->name, ar_buffer + lseek(fd, 0, SEEK_CUR), m->size);
		if (fobj) {
			walk = fobj;
			do {
				scanmacho_fatobj(walk);
			} while (walk->next != NULL && (walk = walk->next));
			fobj->data = NULL;
			unreadmacho(fobj);
		}
	}
	munmap(ar_buffer, len);

	return 0;
}
Esempio n. 5
0
int
wr_start()
#endif
{
	buf = &(bufmem[BLKMULT]);
	/*
	 * Check to make sure the write block size meets pax specs. If the user
	 * does not specify a blocksize, we use the format default blocksize.
	 * We must be picky on writes, so we do not allow the user to create an
	 * archive that might be hard to read elsewhere. If all ok, we then
	 * open the first archive volume
	 */
	if (!wrblksz)
		wrblksz = frmt->bsz;
	if (wrblksz > MAXBLK) {
		paxwarn(1, "Write block size of %d too large, maximium is: %d",
			wrblksz, MAXBLK);
		return(-1);
	}
	if (wrblksz % BLKMULT) {
		paxwarn(1, "Write block size of %d is not a %d byte multiple",
		    wrblksz, BLKMULT);
		return(-1);
	}
	if (wrblksz > MAXBLK_POSIX) {
		paxwarn(0, "Write block size of %d larger than POSIX max %d, archive may not be portable",
			wrblksz, MAXBLK_POSIX);
		return(-1);
	}

	/*
	 * we only allow wrblksz to be used with all archive operations 
	 */
	blksz = rdblksz = wrblksz;
	if ((ar_open(arcname) < 0) && (ar_next() < 0))
		return(-1);
	wrcnt = 0;
	bufend = buf + wrblksz;
	bufpt = buf;
	return(0);
}
Esempio n. 6
0
unsigned long AddModule(unsigned long mod_start, unsigned long mod_end, unsigned long end)
{
    char *p = (char *)mod_start;

    if (p[0] == 0x7f && p[1] == 'E' && p[2] == 'L' && p[3] == 'F')
    {
        /* 
         * The loaded file is an ELF object. It may be put directly into our list of modules.
         * Unfortunately GRUB doesn't give us names of loaded modules
         */
        struct ELFNode *mo = module_prepare(NULL);

        mo->Name = "Kickstart ELF";
        mo->eh = (void*)mod_start;

        D(kprintf("[BOOT] * ELF module %s @ %p\n", mo->Name, mo->eh));

	if (mod_end > end)
	    end = mod_end;
    }
    else if (p[0] == 'P' && p[1] == 'K' && p[2] == 'G' && p[3] == 0x01)
    {
        /* 
         * The loaded file is an PKG\0 archive. Scan it to find all modules which are 
         * stored here.
         */
        void *file = p + 8;

        D(kprintf("[BOOT] * package @ %p:\n", mod_start));

        while (file < (void*)mod_end)
        {
            int len = LONG2BE(*(int *)file);
            char *s = __bs_remove_path(file+4);
            struct ELFNode *mo = module_prepare(s);

            file += 5+len;
            len = LONG2BE(*(int *)file);
            file += 4;

            mo->Name = s;
            mo->eh = file;
            D(kprintf("[BOOT]   * PKG module %s @ %p\n", mo->Name, mo->eh));

            file += len;
        }

	if (mod_end > end)
	    end = mod_end;
    }
    else if (memcmp(p,"!<arch>\n",8) == 0) {
        const struct ar_header *file;
        char *name;
        const struct ar_header *longnames = NULL;

        /* ar(1) archive */
        D(kprintf("[BOOT] * archive @ %p:\n", mod_start));

        /* Look for the GNU extended name section */
        for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
        {
            name = ar_name(file, NULL);
            if (strcmp(name, "//") == 0)
            {
                longnames = file;
                break;
            }
        }
        D(kprintf("[BOOT] *   longnames @ %p\n", longnames));

        for (file = (void *)(p + 8); (void *)file < (void*)mod_end; file = ar_next(file))
        {
            const char *data = ar_data(file);
            char *s = ar_name(file, longnames);

            if (memcmp(data,"\177ELF",4) == 0) {
                struct ELFNode *mo = module_prepare(s);

                mo->Name = s;
                mo->eh = (void *)data;
                D(kprintf("[BOOT] *   ar module %s @ %p\n", mo->Name, mo->eh));
            } else {
                D(kprintf("[BOOT] *   Ignored @ %p (%s)\n", file, s));
            }
        }

	if (mod_end > end)
	    end = mod_end;

    }
    else
       	kprintf("[BOOT] Unknown module 0x%p\n", p);

    return end;
}
Esempio n. 7
0
int
buf_flush(int bufcnt)
{
	int cnt;
	int push = 0;
	int totcnt = 0;

	/*
	 * if we have reached the user specified byte count for each archive
	 * volume, prompt for the next volume. (The non-standard -R flag).
	 * NOTE: If the wrlimit is smaller than wrcnt, we will always write
	 * at least one record. We always round limit UP to next blocksize.
	 */
	if ((wrlimit > 0) && (wrcnt > wrlimit)) {
		paxwarn(0, "User specified archive volume byte limit reached.");
		if (ar_next() < 0) {
			wrcnt = 0;
			exit_val = 1;
			return(-1);
		}
		wrcnt = 0;

		/*
		 * The new archive volume might have changed the size of the
		 * write blocksize. if so we figure out if we need to write
		 * (one or more times), or if there is now free space left in
		 * the buffer (it is no longer full). bufcnt has the number of
		 * bytes in the buffer, (the blocksize, at the point we were
		 * CALLED). Push has the amount of "extra" data in the buffer
		 * if the block size has shrunk from a volume change.
		 */
		bufend = buf + blksz;
		if (blksz > bufcnt)
			return(0);
		if (blksz < bufcnt)
			push = bufcnt - blksz;
	}

	/*
	 * We have enough data to write at least one archive block
	 */
	for (;;) {
		/*
		 * write a block and check if it all went out ok
		 */
		cnt = ar_write(buf, blksz);
		if (cnt == blksz) {
			/*
			 * the write went ok
			 */
			wrcnt += cnt;
			totcnt += cnt;
			if (push > 0) {
				/* we have extra data to push to the front.
				 * check for more than 1 block of push, and if
				 * so we loop back to write again
				 */
				memcpy(buf, bufend, push);
				bufpt = buf + push;
				if (push >= blksz) {
					push -= blksz;
					continue;
				}
			} else
				bufpt = buf;
			return(totcnt);
		} else if (cnt > 0) {
			/*
			 * Oh drat we got a partial write!
			 * if format does not care about alignment let it go,
			 * we warned the user in ar_write().... but this means
			 * the last record on this volume violates pax spec....
			 */
			totcnt += cnt;
			wrcnt += cnt;
			bufpt = buf + cnt;
			cnt = bufcnt - cnt;
			memcpy(buf, bufpt, cnt);
			bufpt = buf + cnt;
			if (!frmt->blkalgn || ((cnt % frmt->blkalgn) == 0))
				return(totcnt);
			break;
		}

		/*
		 * All done, go to next archive
		 */
		wrcnt = 0;
		if (ar_next() < 0)
			break;

		/*
		 * The new archive volume might also have changed the block
		 * size. if so, figure out if we have too much or too little
		 * data for using the new block size
		 */
		bufend = buf + blksz;
		if (blksz > bufcnt)
			return(0);
		if (blksz < bufcnt)
			push = bufcnt - blksz;
	}

	/*
	 * write failed, stop pax. we must not create a bad archive!
	 */
	exit_val = 1;
	return(-1);
}