Exemple #1
0
struct toepcb *
alloc_toepcb(struct vi_info *vi, int txqid, int rxqid, int flags)
{
	struct port_info *pi = vi->pi;
	struct adapter *sc = pi->adapter;
	struct toepcb *toep;
	int tx_credits, txsd_total, len;

	/*
	 * The firmware counts tx work request credits in units of 16 bytes
	 * each.  Reserve room for an ABORT_REQ so the driver never has to worry
	 * about tx credits if it wants to abort a connection.
	 */
	tx_credits = sc->params.ofldq_wr_cred;
	tx_credits -= howmany(sizeof(struct cpl_abort_req), 16);

	/*
	 * Shortest possible tx work request is a fw_ofld_tx_data_wr + 1 byte
	 * immediate payload, and firmware counts tx work request credits in
	 * units of 16 byte.  Calculate the maximum work requests possible.
	 */
	txsd_total = tx_credits /
	    howmany(sizeof(struct fw_ofld_tx_data_wr) + 1, 16);

	if (txqid < 0)
		txqid = (arc4random() % vi->nofldtxq) + vi->first_ofld_txq;
	KASSERT(txqid >= vi->first_ofld_txq &&
	    txqid < vi->first_ofld_txq + vi->nofldtxq,
	    ("%s: txqid %d for vi %p (first %d, n %d)", __func__, txqid, vi,
		vi->first_ofld_txq, vi->nofldtxq));

	if (rxqid < 0)
		rxqid = (arc4random() % vi->nofldrxq) + vi->first_ofld_rxq;
	KASSERT(rxqid >= vi->first_ofld_rxq &&
	    rxqid < vi->first_ofld_rxq + vi->nofldrxq,
	    ("%s: rxqid %d for vi %p (first %d, n %d)", __func__, rxqid, vi,
		vi->first_ofld_rxq, vi->nofldrxq));

	len = offsetof(struct toepcb, txsd) +
	    txsd_total * sizeof(struct ofld_tx_sdesc);

	toep = malloc(len, M_CXGBE, M_ZERO | flags);
	if (toep == NULL)
		return (NULL);

	refcount_init(&toep->refcount, 1);
	toep->td = sc->tom_softc;
	toep->vi = vi;
	toep->tc_idx = -1;
	toep->tx_total = tx_credits;
	toep->tx_credits = tx_credits;
	toep->ofld_txq = &sc->sge.ofld_txq[txqid];
	toep->ofld_rxq = &sc->sge.ofld_rxq[rxqid];
	toep->ctrlq = &sc->sge.ctrlq[pi->port_id];
	mbufq_init(&toep->ulp_pduq, INT_MAX);
	mbufq_init(&toep->ulp_pdu_reclaimq, INT_MAX);
	toep->txsd_total = txsd_total;
	toep->txsd_avail = txsd_total;
	toep->txsd_pidx = 0;
	toep->txsd_cidx = 0;
	aiotx_init_toep(toep);
	ddp_init_toep(toep);

	return (toep);
}
Exemple #2
0
static int bEscape8BitChars = 0; /* escape characters > 127 on reception: 0 - no, 1 - yes */
static int bEscapeTab = 1; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */
static int bParserEscapeCCCStyle = 0; /* escape control characters in c style: 0 - no, 1 - yes */
short janitorInterval = 10; /* interval (in minutes) at which the janitor runs */
int glblReportNewSenders = 0;
int glblReportGoneAwaySenders = 0;
int glblSenderStatsTimeout = 12 * 60 * 60; /* 12 hr timeout for senders */
int glblSenderKeepTrack = 0;  /* keep track of known senders? */
int glblUnloadModules = 1;

pid_t glbl_ourpid;
#ifndef HAVE_ATOMIC_BUILTINS
static DEF_ATOMIC_HELPER_MUT(mutTerminateInputs);
#endif
#ifdef USE_UNLIMITED_SELECT
static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof (fd_mask); /* size of select() bitmask in bytes */
#endif
static uchar *SourceIPofLocalClient = NULL;	/* [ar] Source IP for local client to be used on multihomed host */

tzinfo_t *tzinfos = NULL;
static int ntzinfos;

/* tables for interfacing with the v6 config system */
static struct cnfparamdescr cnfparamdescr[] = {
	{ "workdirectory", eCmdHdlrString, 0 },
	{ "dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0 },
	{ "localhostname", eCmdHdlrGetWord, 0 },
	{ "preservefqdn", eCmdHdlrBinary, 0 },
	{ "debug.onshutdown", eCmdHdlrBinary, 0 },
	{ "debug.logfile", eCmdHdlrString, 0 },
	{ "debug.gnutls", eCmdHdlrPositiveInt, 0 },
Exemple #3
0
void
printlong(DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20], szbuf[5];

	now = time(NULL);

	if (!f_leafonly)
		printtotal(dp);		/* "total: %u\n" */
	
	for (p = dp->list; p; p = p->fts_link) {
		if (IS_NOPRINT(p))
			continue;
		sp = p->fts_statp;
		if (f_inode)
			(void)printf("%*"PRIu64" ", dp->s_inode, sp->st_ino);
		if (f_size) {
			if (f_humanize) {
				if ((humanize_number(szbuf, sizeof(szbuf),
				    sp->st_blocks * S_BLKSIZE,
				    "", HN_AUTOSCALE,
				    (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
					err(1, "humanize_number");
				(void)printf("%*s ", dp->s_block, szbuf);
			} else {
				(void)printf(f_commas ? "%'*llu " : "%*llu ",
				    dp->s_block,
				    (unsigned long long)howmany(sp->st_blocks,
				    blocksize));
			}
		}
		(void)strmode(sp->st_mode, buf);
		np = p->fts_pointer;
		(void)printf("%s %*lu ", buf, dp->s_nlink,
		    (unsigned long)sp->st_nlink);
		if (!f_grouponly)
			(void)printf("%-*s  ", dp->s_user, np->user);
		(void)printf("%-*s  ", dp->s_group, np->group);
		if (f_flags)
			(void)printf("%-*s ", dp->s_flags, np->flags);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			(void)printf("%*lld, %*lld ",
			    dp->s_major, (long long)major(sp->st_rdev),
			    dp->s_minor, (long long)minor(sp->st_rdev));
		else
			if (f_humanize) {
				if ((humanize_number(szbuf, sizeof(szbuf),
				    sp->st_size, "", HN_AUTOSCALE,
				    (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1)
					err(1, "humanize_number");
				(void)printf("%*s ", dp->s_size, szbuf);
			} else {
				(void)printf(f_commas ? "%'*llu " : "%*llu ", 
				    dp->s_size, (unsigned long long)
				    sp->st_size);
			}
		if (f_accesstime)
			printtime(sp->st_atime);
		else if (f_statustime)
			printtime(sp->st_ctime);
		else
			printtime(sp->st_mtime);
		if (f_octal || f_octal_escape)
			(void)safe_printpath(p);
		else if (f_nonprint)
			(void)printescapedpath(p);
		else
			(void)printpath(p);

		if (f_type || (f_typedir && S_ISDIR(sp->st_mode)))
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		(void)putchar('\n');
	}
}
Exemple #4
0
void
printlong(const DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20];
#ifdef COLORLS
	int color_printed = 0;
#endif

	if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
	    (f_longform || f_size)) {
		(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
	}

	for (p = dp->list; p; p = p->fts_link) {
		if (IS_NOPRINT(p))
			continue;
		sp = p->fts_statp;
		if (f_inode)
			(void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
		if (f_size)
			(void)printf("%*jd ",
			    dp->s_block, howmany(sp->st_blocks, blocksize));
		strmode(sp->st_mode, buf);
		aclmode(buf, p);
		np = p->fts_pointer;
		(void)printf("%s %*u %-*s  %-*s  ", buf, dp->s_nlink,
		    sp->st_nlink, dp->s_user, np->user, dp->s_group,
		    np->group);
		if (f_flags)
			(void)printf("%-*s ", dp->s_flags, np->flags);
		if (f_label)
			(void)printf("%-*s ", dp->s_label, np->label);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			printdev(dp->s_size, sp->st_rdev);
		else
			printsize(dp->s_size, sp->st_size);
		if (f_accesstime)
			printtime(sp->st_atime);
		else if (f_birthtime)
			printtime(sp->st_birthtime);
		else if (f_statustime)
			printtime(sp->st_ctime);
		else
			printtime(sp->st_mtime);
#ifdef COLORLS
		if (f_color)
			color_printed = colortype(sp->st_mode);
#endif
		(void)printname(p->fts_name);
#ifdef COLORLS
		if (f_color && color_printed)
			endcolor(0);
#endif
		if (f_type)
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		(void)putchar('\n');
	}
}
Exemple #5
0
/*
 * wrxmem does the real work of write requests for xmemfs.
 */
static int
wrxmem(struct xmount *xm, struct xmemnode *xp, struct uio *uio,
	struct cred *cr, struct caller_context *ct)
{
	uint_t		blockoffset;	/* offset in the block */
	uint_t		blkwr;		/* offset in blocks into xmem file */
	uint_t		blkcnt;
	caddr_t		base;
	ssize_t		bytes;		/* bytes to uiomove */
	struct vnode	*vp;
	int		error = 0;
	size_t		bsize = xm->xm_bsize;
	rlim64_t	limit = uio->uio_llimit;
	long		oresid = uio->uio_resid;
	timestruc_t 	now;
	offset_t	offset;

	/*
	 * xp->xn_size is incremented before the uiomove
	 * is done on a write.  If the move fails (bad user
	 * address) reset xp->xn_size.
	 * The better way would be to increment xp->xn_size
	 * only if the uiomove succeeds.
	 */
	long		xn_size_changed = 0;
	offset_t	old_xn_size;

	vp = XNTOV(xp);
	ASSERT(vp->v_type == VREG);

	XMEMPRINTF(1, ("wrxmem: vp %p resid %lx off %llx\n",
	    (void *)vp, uio->uio_resid, uio->uio_loffset));

	ASSERT(RW_WRITE_HELD(&xp->xn_contents));
	ASSERT(RW_WRITE_HELD(&xp->xn_rwlock));

	if (MANDLOCK(vp, xp->xn_mode)) {
		rw_exit(&xp->xn_contents);
		/*
		 * xmem_getattr ends up being called by chklock
		 */
		error = chklock(vp, FWRITE,
			uio->uio_loffset, uio->uio_resid, uio->uio_fmode, ct);

		rw_enter(&xp->xn_contents, RW_WRITER);
		if (error != 0) {
			XMEMPRINTF(8, ("wrxmem: vp %p error %x\n",
			    (void *)vp, error));
			return (error);
		}
	}

	if ((offset = uio->uio_loffset) < 0)
		return (EINVAL);

	if (offset >= limit) {
		proc_t *p = ttoproc(curthread);

		mutex_enter(&p->p_lock);
		(void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE], p->p_rctls,
		    p, RCA_UNSAFE_SIGINFO);
		mutex_exit(&p->p_lock);
		return (EFBIG);
	}

	if (uio->uio_resid == 0) {
		XMEMPRINTF(8, ("wrxmem: vp %p resid %lx\n",
			(void *)vp, uio->uio_resid));
		return (0);
	}

	/*
	 * Get the highest blocknumber and allocate page array if needed.
	 * Note that if xm_bsize != PAGESIZE, each ppa[] is pointer to
	 * a page array rather than just a page.
	 */
	blkcnt = howmany((offset + uio->uio_resid), bsize);
	blkwr = offset >> xm->xm_bshift;	/* write begins here */

	XMEMPRINTF(1, ("wrxmem: vp %p blkcnt %x blkwr %x xn_ppasz %lx\n",
	    (void *)vp, blkcnt, blkwr, xp->xn_ppasz));

	/* file size increase */
	if (xp->xn_ppasz < blkcnt) {

		page_t		***ppa;
		int		ppasz;
		uint_t		blksinfile = howmany(xp->xn_size, bsize);

		/*
		 * check if sufficient blocks available for the given offset.
		 */
		if (blkcnt - blksinfile > xm->xm_max - xm->xm_mem)
			return (ENOSPC);

		/*
		 * to prevent reallocating every time the file grows by a
		 * single block, double the size of the array.
		 */
		if (blkcnt < xp->xn_ppasz * 2)
			ppasz = xp->xn_ppasz * 2;
		else
			ppasz = blkcnt;


		ppa = kmem_zalloc(ppasz * sizeof (page_t **), KM_SLEEP);

		ASSERT(ppa);

		if (xp->xn_ppasz) {
			bcopy(xp->xn_ppa, ppa, blksinfile * sizeof (*ppa));
			kmem_free(xp->xn_ppa, xp->xn_ppasz * sizeof (*ppa));
		}
		xp->xn_ppa = ppa;
		xp->xn_ppasz = ppasz;

		/*
		 * fill in the 'hole' if write offset beyond file size. This
		 * helps in creating large files quickly; an application can
		 * lseek to a large offset and perform a single write
		 * operation to create the large file.
		 */

		if (blksinfile < blkwr) {

			old_xn_size = xp->xn_size;
			xp->xn_size = (offset_t)blkwr * bsize;

			XMEMPRINTF(4, ("wrxmem: fill vp %p blks %x to %x\n",
			    (void *)vp, blksinfile, blkcnt - 1));
			error = xmem_fillpages(xp, vp,
				(offset_t)blksinfile * bsize,
				(offset_t)(blkcnt - blksinfile) * bsize, 1);
			if (error) {
				/* truncate file back to original size */
				(void) xmemnode_trunc(xm, xp, old_xn_size);
				return (error);
			}
			/*
			 * if error on blkwr, this allows truncation of the
			 * filled hole.
			 */
			xp->xn_size = old_xn_size;
		}
	}

	do {
		offset_t	pagestart, pageend;
		page_t		**ppp;

		blockoffset = (uint_t)offset & (bsize - 1);
		/*
		 * A maximum of xm->xm_bsize bytes of data is transferred
		 * each pass through this loop
		 */
		bytes = MIN(bsize - blockoffset, uio->uio_resid);

		ASSERT(bytes);

		if (offset + bytes >= limit) {
			if (offset >= limit) {
				error = EFBIG;
				goto out;
			}
			bytes = limit - offset;
		}


		if (!xp->xn_ppa[blkwr]) {
			/* zero fill new pages - simplify partial updates */
			error = xmem_fillpages(xp, vp, offset, bytes, 1);
			if (error)
				return (error);
		}

		/* grow the file to the new length */
		if (offset + bytes > xp->xn_size) {
			xn_size_changed = 1;
			old_xn_size = xp->xn_size;
			xp->xn_size = offset + bytes;
		}

#ifdef LOCKNEST
		xmem_getpage();
#endif

		/* xn_ppa[] is a page_t * if ppb == 1 */
		if (xm->xm_ppb == 1)
			ppp = (page_t **)&xp->xn_ppa[blkwr];
		else
			ppp = &xp->xn_ppa[blkwr][btop(blockoffset)];

		pagestart = offset & ~(offset_t)(PAGESIZE - 1);
		/*
		 * subtract 1 in case (offset + bytes) is mod PAGESIZE
		 * so that pageend is the actual index of last page.
		 */
		pageend = (offset + bytes - 1) & ~(offset_t)(PAGESIZE - 1);

		base = segxmem_getmap(xm->xm_map, vp,
			pagestart, pageend - pagestart + PAGESIZE,
			ppp, S_WRITE);

		rw_exit(&xp->xn_contents);

		error = uiomove(base + (offset - pagestart), bytes,
							UIO_WRITE, uio);
		segxmem_release(xm->xm_map, base,
				pageend - pagestart + PAGESIZE);

		/*
		 * Re-acquire contents lock.
		 */
		rw_enter(&xp->xn_contents, RW_WRITER);
		/*
		 * If the uiomove failed, fix up xn_size.
		 */
		if (error) {
			if (xn_size_changed) {
				/*
				 * The uiomove failed, and we
				 * allocated blocks,so get rid
				 * of them.
				 */
				(void) xmemnode_trunc(xm, xp, old_xn_size);
			}
		} else {
			if ((xp->xn_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) &&
			    (xp->xn_mode & (S_ISUID | S_ISGID)) &&
			    secpolicy_vnode_setid_retain(cr,
			    (xp->xn_mode & S_ISUID) != 0 && xp->xn_uid == 0)
				!= 0) {

				/*
				 * Clear Set-UID & Set-GID bits on
				 * successful write if not privileged
				 * and at least one of the execute bits
				 * is set.  If we always clear Set-GID,
				 * mandatory file and record locking is
				 * unuseable.
				 */
				xp->xn_mode &= ~(S_ISUID | S_ISGID);
			}
			gethrestime(&now);
			xp->xn_mtime = now;
			xp->xn_ctime = now;
		}
		offset = uio->uio_loffset;	/* uiomove sets uio_loffset */
		blkwr++;
	} while (error == 0 && uio->uio_resid > 0 && bytes != 0);

out:
	/*
	 * If we've already done a partial-write, terminate
	 * the write but return no error.
	 */
	if (oresid != uio->uio_resid)
		error = 0;
	return (error);
}
Exemple #6
0
/* ARGSUSED */
int
dk_dump(struct dk_softc *dksc, dev_t dev,
    daddr_t blkno, void *vav, size_t size)
{
	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
	char *va = vav;
	struct disklabel *lp;
	struct partition *p;
	int part, towrt, nsects, sectoff, maxblkcnt, nblk;
	int maxxfer, rv = 0;

	/*
	 * ensure that we consider this device to be safe for dumping,
	 * and that the device is configured.
	 */
	if (!DKFF_READYFORDUMP(dksc->sc_flags)) {
		DPRINTF(DKDB_DUMP, ("%s: bad dump flags 0x%x\n", __func__,
		    dksc->sc_flags));
		return ENXIO;
	}

	/* ensure that we are not already dumping */
	if (dk_dumping)
		return EFAULT;
	dk_dumping = 1;

	if (dkd->d_dumpblocks == NULL) {
		DPRINTF(DKDB_DUMP, ("%s: no dumpblocks\n", __func__));
		return ENXIO;
	}

	/* device specific max transfer size */
	maxxfer = MAXPHYS;
	if (dkd->d_iosize != NULL)
		(*dkd->d_iosize)(dksc->sc_dev, &maxxfer);

	/* Convert to disk sectors.  Request must be a multiple of size. */
	part = DISKPART(dev);
	lp = dksc->sc_dkdev.dk_label;
	if ((size % lp->d_secsize) != 0) {
		DPRINTF(DKDB_DUMP, ("%s: odd size %zu\n", __func__, size));
		return EFAULT;
	}
	towrt = size / lp->d_secsize;
	blkno = dbtob(blkno) / lp->d_secsize;   /* blkno in secsize units */

	p = &lp->d_partitions[part];
	if (p->p_fstype != FS_SWAP) {
		DPRINTF(DKDB_DUMP, ("%s: bad fstype %d\n", __func__,
		    p->p_fstype));
		return ENXIO;
	}
	nsects = p->p_size;
	sectoff = p->p_offset;

	/* Check transfer bounds against partition size. */
	if ((blkno < 0) || ((blkno + towrt) > nsects)) {
		DPRINTF(DKDB_DUMP, ("%s: out of bounds blkno=%jd, towrt=%d, "
		    "nsects=%d\n", __func__, (intmax_t)blkno, towrt, nsects));
		return EINVAL;
	}

	/* Offset block number to start of partition. */
	blkno += sectoff;

	/* Start dumping and return when done. */
	maxblkcnt = howmany(maxxfer, lp->d_secsize);
	while (towrt > 0) {
		nblk = min(maxblkcnt, towrt);

		if ((rv = (*dkd->d_dumpblocks)(dksc->sc_dev, va, blkno, nblk))
		    != 0) {
			DPRINTF(DKDB_DUMP, ("%s: dumpblocks %d\n", __func__,
			    rv));
			return rv;
		}

		towrt -= nblk;
		blkno += nblk;
		va += nblk * lp->d_secsize;
	}

	dk_dumping = 0;

	return 0;
}
Exemple #7
0
void
pass1(void)
{
    struct inostat *info;
    struct inodesc idesc;
    struct bufarea *cgbp;
    struct cg *cgp;
    ino_t inumber, inosused, mininos;
    ufs2_daddr_t i, cgd;
    u_int8_t *cp;
    int c, rebuildcg;

    badblk = dupblk = lastino = 0;

    /*
     * Set file system reserved blocks in used block map.
     */
    for (c = 0; c < sblock.fs_ncg; c++) {
        cgd = cgdmin(&sblock, c);
        if (c == 0) {
            i = cgbase(&sblock, c);
        } else
            i = cgsblock(&sblock, c);
        for (; i < cgd; i++)
            setbmap(i);
    }
    i = sblock.fs_csaddr;
    cgd = i + howmany(sblock.fs_cssize, sblock.fs_fsize);
    for (; i < cgd; i++)
        setbmap(i);

    /*
     * Find all allocated blocks.
     */
    memset(&idesc, 0, sizeof(struct inodesc));
    idesc.id_func = pass1check;
    n_files = n_blks = 0;
    for (c = 0; c < sblock.fs_ncg; c++) {
        inumber = c * sblock.fs_ipg;
        setinodebuf(inumber);
        cgbp = cgget(c);
        cgp = cgbp->b_un.b_cg;
        rebuildcg = 0;
        if (!check_cgmagic(c, cgbp))
            rebuildcg = 1;
        if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
            inosused = cgp->cg_initediblk;
            if (inosused > sblock.fs_ipg) {
                pfatal(
                    "Too many initialized inodes (%ju > %d) in cylinder group %d\nReset to %d\n",
                    (uintmax_t)inosused,
                    sblock.fs_ipg, c, sblock.fs_ipg);
                inosused = sblock.fs_ipg;
            }
        } else {
            inosused = sblock.fs_ipg;
        }
        if (got_siginfo) {
            printf("%s: phase 1: cyl group %d of %d (%d%%)\n",
                   cdevname, c, sblock.fs_ncg,
                   c * 100 / sblock.fs_ncg);
            got_siginfo = 0;
        }
        if (got_sigalarm) {
            setproctitle("%s p1 %d%%", cdevname,
                         c * 100 / sblock.fs_ncg);
            got_sigalarm = 0;
        }
        /*
         * If we are using soft updates, then we can trust the
         * cylinder group inode allocation maps to tell us which
         * inodes are allocated. We will scan the used inode map
         * to find the inodes that are really in use, and then
         * read only those inodes in from disk.
         */
        if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
            cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
            for ( ; inosused > 0; inosused -= CHAR_BIT, cp--) {
                if (*cp == 0)
                    continue;
                for (i = 1 << (CHAR_BIT - 1); i > 0; i >>= 1) {
                    if (*cp & i)
                        break;
                    inosused--;
                }
                break;
            }
            if (inosused < 0)
                inosused = 0;
        }
        /*
         * Allocate inoinfo structures for the allocated inodes.
         */
        inostathead[c].il_numalloced = inosused;
        if (inosused == 0) {
            inostathead[c].il_stat = NULL;
            continue;
        }
        info = Calloc((unsigned)inosused, sizeof(struct inostat));
        if (info == NULL)
            errx(EEXIT, "cannot alloc %u bytes for inoinfo",
                 (unsigned)(sizeof(struct inostat) * inosused));
        inostathead[c].il_stat = info;
        /*
         * Scan the allocated inodes.
         */
        for (i = 0; i < inosused; i++, inumber++) {
            if (inumber < ROOTINO) {
                (void)getnextinode(inumber, rebuildcg);
                continue;
            }
            /*
             * NULL return indicates probable end of allocated
             * inodes during cylinder group rebuild attempt.
             * We always keep trying until we get to the minimum
             * valid number for this cylinder group.
             */
            if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
                    i > cgp->cg_initediblk)
                break;
        }
        /*
         * This optimization speeds up future runs of fsck
         * by trimming down the number of inodes in cylinder
         * groups that formerly had many inodes but now have
         * fewer in use.
         */
        mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
        if (inoopt && !preen && !rebuildcg &&
                sblock.fs_magic == FS_UFS2_MAGIC &&
                cgp->cg_initediblk > 2 * INOPB(&sblock) &&
                mininos < cgp->cg_initediblk) {
            i = cgp->cg_initediblk;
            if (mininos < 2 * INOPB(&sblock))
                cgp->cg_initediblk = 2 * INOPB(&sblock);
            else
                cgp->cg_initediblk = mininos;
            pwarn("CYLINDER GROUP %d: RESET FROM %ju TO %d %s\n",
                  c, i, cgp->cg_initediblk, "VALID INODES");
            dirty(cgbp);
        }
        if (inosused < sblock.fs_ipg)
            continue;
        lastino += 1;
        if (lastino < (c * sblock.fs_ipg))
            inosused = 0;
        else
            inosused = lastino - (c * sblock.fs_ipg);
        if (rebuildcg && inosused > cgp->cg_initediblk &&
                sblock.fs_magic == FS_UFS2_MAGIC) {
            cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
            pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
                  cgp->cg_initediblk);
        }
        /*
         * If we were not able to determine in advance which inodes
         * were in use, then reduce the size of the inoinfo structure
         * to the size necessary to describe the inodes that we
         * really found.
         */
        if (inumber == lastino)
            continue;
        inostathead[c].il_numalloced = inosused;
        if (inosused == 0) {
            free(inostathead[c].il_stat);
            inostathead[c].il_stat = NULL;
            continue;
        }
        info = Calloc((unsigned)inosused, sizeof(struct inostat));
        if (info == NULL)
            errx(EEXIT, "cannot alloc %u bytes for inoinfo",
                 (unsigned)(sizeof(struct inostat) * inosused));
        memmove(info, inostathead[c].il_stat, inosused * sizeof(*info));
        free(inostathead[c].il_stat);
        inostathead[c].il_stat = info;
    }
Exemple #8
0
/*
 * Reload all incore data for a filesystem (used after running fsck on
 * the root filesystem and finding things to fix). The filesystem must
 * be mounted read-only.
 *
 * Things to do to update the mount:
 *	1) invalidate all cached meta-data.
 *	2) re-read superblock from disk.
 *	3) re-read summary information from disk.
 *	4) invalidate all inactive vnodes.
 *	5) invalidate all cached file data.
 *	6) re-read inode data for all active vnodes.
 */
int
ffs_reload(struct mount *mountp, struct ucred *cred, struct proc *p)
{
	struct vnode *devvp;
	caddr_t space;
	struct fs *fs, *newfs;
	struct partinfo dpart;
	int i, blks, size, error;
	int32_t *lp;
	struct buf *bp = NULL;
	struct ffs_reload_args fra;

	if ((mountp->mnt_flag & MNT_RDONLY) == 0)
		return (EINVAL);
	/*
	 * Step 1: invalidate all cached meta-data.
	 */
	devvp = VFSTOUFS(mountp)->um_devvp;
	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
	error = vinvalbuf(devvp, 0, cred, p, 0, 0);
	VOP_UNLOCK(devvp, 0, p);
	if (error)
		panic("ffs_reload: dirty1");

	/*
	 * Step 2: re-read superblock from disk.
	 */
	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, NOCRED, p) != 0)
		size = DEV_BSIZE;
	else
		size = dpart.disklab->d_secsize;

	error = bread(devvp, (daddr_t)(SBOFF / size), SBSIZE, NOCRED, &bp);
	if (error) {
		brelse(bp);
		return (error);
	}

	newfs = (struct fs *)bp->b_data;
	if (ffs_validate(newfs) == 0) {
		brelse(bp);
		return (EINVAL);
	}
	fs = VFSTOUFS(mountp)->um_fs;
	/*
	 * Copy pointer fields back into superblock before copying in	XXX
	 * new superblock. These should really be in the ufsmount.	XXX
	 * Note that important parameters (eg fs_ncg) are unchanged.
	 */
	newfs->fs_csp = fs->fs_csp;
	newfs->fs_maxcluster = fs->fs_maxcluster;
	newfs->fs_ronly = fs->fs_ronly;
	bcopy(newfs, fs, (u_int)fs->fs_sbsize);
	if (fs->fs_sbsize < SBSIZE)
		bp->b_flags |= B_INVAL;
	brelse(bp);
	mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
	ffs1_compat_read(fs, VFSTOUFS(mountp), SBOFF);
	ffs_oldfscompat(fs);
	(void)ffs_statfs(mountp, &mountp->mnt_stat, p);
	/*
	 * Step 3: re-read summary information from disk.
	 */
	blks = howmany(fs->fs_cssize, fs->fs_fsize);
	space = (caddr_t)fs->fs_csp;
	for (i = 0; i < blks; i += fs->fs_frag) {
		size = fs->fs_bsize;
		if (i + fs->fs_frag > blks)
			size = (blks - i) * fs->fs_fsize;
		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
			      NOCRED, &bp);
		if (error) {
			brelse(bp);
			return (error);
		}
		bcopy(bp->b_data, space, (u_int)size);
		space += size;
		brelse(bp);
	}
	if ((fs->fs_flags & FS_DOSOFTDEP))
		(void) softdep_mount(devvp, mountp, fs, cred);
	/*
	 * We no longer know anything about clusters per cylinder group.
	 */
	if (fs->fs_contigsumsize > 0) {
		lp = fs->fs_maxcluster;
		for (i = 0; i < fs->fs_ncg; i++)
			*lp++ = fs->fs_contigsumsize;
	}

	fra.p = p;
	fra.cred = cred;
	fra.fs = fs;
	fra.devvp = devvp;

	error = vfs_mount_foreach_vnode(mountp, ffs_reload_vnode, &fra);

	return (error);
}
Exemple #9
0
/*
 * Common code for mount and mountroot
 */
int
ffs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p)
{
	struct ufsmount *ump;
	struct buf *bp;
	struct fs *fs;
	dev_t dev;
	struct partinfo dpart;
	caddr_t space;
	ufs2_daddr_t sbloc;
	int error, i, blks, size, ronly;
	int32_t *lp;
	size_t strsize;
	struct ucred *cred;
	u_int64_t maxfilesize;					/* XXX */

	dev = devvp->v_rdev;
	cred = p ? p->p_ucred : NOCRED;
	/*
	 * Disallow multiple mounts of the same device.
	 * Disallow mounting of a device that is currently in use
	 * (except for root, which might share swap device for miniroot).
	 * Flush out any old buffers remaining from a previous use.
	 */
	if ((error = vfs_mountedon(devvp)) != 0)
		return (error);
	if (vcount(devvp) > 1 && devvp != rootvp)
		return (EBUSY);
	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
	error = vinvalbuf(devvp, V_SAVE, cred, p, 0, 0);
	VOP_UNLOCK(devvp, 0, p);
	if (error)
		return (error);

	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
	error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
	if (error)
		return (error);
	if (VOP_IOCTL(devvp, DIOCGPART, (caddr_t)&dpart, FREAD, cred, p) != 0)
		size = DEV_BSIZE;
	else
		size = dpart.disklab->d_secsize;

	bp = NULL;
	ump = NULL;

	/*
	 * Try reading the super-block in each of its possible locations.
	 */
	for (i = 0; sbtry[i] != -1; i++) {
		if (bp != NULL) {
			bp->b_flags |= B_NOCACHE;
			brelse(bp);
			bp = NULL;
		}

		error = bread(devvp, sbtry[i] / size, SBSIZE, cred, &bp);
		if (error)
			goto out;

		fs = (struct fs *) bp->b_data;
		sbloc = sbtry[i];

#if 0
		if (fs->fs_magic == FS_UFS2_MAGIC) {
			printf("ffs_mountfs(): Sorry, no UFS2 support (yet)\n");
			error = EFTYPE;
			goto out;
		}
#endif

		/*
		 * Do not look for an FFS1 file system at SBLOCK_UFS2. Doing so
		 * will find the wrong super-block for file systems with 64k
		 * block size.
		 */
		if (fs->fs_magic == FS_UFS1_MAGIC && sbloc == SBLOCK_UFS2)
			continue;

		if (ffs_validate(fs))
			break; /* Super block validated */
	}

	if (sbtry[i] == -1) {
		error = EINVAL;
		goto out;
	}

	fs->fs_fmod = 0;
	fs->fs_flags &= ~FS_UNCLEAN;
	if (fs->fs_clean == 0) {
		fs->fs_flags |= FS_UNCLEAN;
#if 0
		/*
		 * It is safe mount unclean file system
		 * if it was previously mounted with softdep
		 * but we may loss space and must
		 * sometimes run fsck manually.
		 */
		if (fs->fs_flags & FS_DOSOFTDEP)
			printf(
"WARNING: %s was not properly unmounted\n",
			    fs->fs_fsmnt);
		else
#endif
		if (ronly || (mp->mnt_flag & MNT_FORCE)) {
			printf(
"WARNING: %s was not properly unmounted\n",
			    fs->fs_fsmnt);
		} else {
			printf(
"WARNING: R/W mount of %s denied.  Filesystem is not clean - run fsck\n",
			    fs->fs_fsmnt);
			error = EROFS;
			goto out;
		}
	}

	if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) {
#ifndef SMALL_KERNEL
		printf("ffs_mountfs(): obsolete rotational table format, "
		    "please use fsck_ffs(8) -c 1\n");
#endif
		error = EFTYPE;
		goto out;
	}

	ump = malloc(sizeof *ump, M_UFSMNT, M_WAITOK);
	bzero(ump, sizeof *ump);
	ump->um_fs = malloc((u_long)fs->fs_sbsize, M_UFSMNT,
	    M_WAITOK);

	if (fs->fs_magic == FS_UFS1_MAGIC)
		ump->um_fstype = UM_UFS1;
#ifdef FFS2
	else
		ump->um_fstype = UM_UFS2;
#endif

	bcopy(bp->b_data, ump->um_fs, (u_int)fs->fs_sbsize);
	if (fs->fs_sbsize < SBSIZE)
		bp->b_flags |= B_INVAL;
	brelse(bp);
	bp = NULL;
	fs = ump->um_fs;

	ffs1_compat_read(fs, ump, sbloc);

	fs->fs_ronly = ronly;
	size = fs->fs_cssize;
	blks = howmany(size, fs->fs_fsize);
	if (fs->fs_contigsumsize > 0)
		size += fs->fs_ncg * sizeof(int32_t);
	space = malloc((u_long)size, M_UFSMNT, M_WAITOK);
	fs->fs_csp = (struct csum *)space;
	for (i = 0; i < blks; i += fs->fs_frag) {
		size = fs->fs_bsize;
		if (i + fs->fs_frag > blks)
			size = (blks - i) * fs->fs_fsize;
		error = bread(devvp, fsbtodb(fs, fs->fs_csaddr + i), size,
			      cred, &bp);
		if (error) {
			free(fs->fs_csp, M_UFSMNT);
			goto out;
		}
		bcopy(bp->b_data, space, (u_int)size);
		space += size;
		brelse(bp);
		bp = NULL;
	}
	if (fs->fs_contigsumsize > 0) {
		fs->fs_maxcluster = lp = (int32_t *)space;
		for (i = 0; i < fs->fs_ncg; i++)
			*lp++ = fs->fs_contigsumsize;
	}
	mp->mnt_data = (qaddr_t)ump;
	mp->mnt_stat.f_fsid.val[0] = (long)dev;
	/* Use on-disk fsid if it exists, else fake it */
	if (fs->fs_id[0] != 0 && fs->fs_id[1] != 0)
		mp->mnt_stat.f_fsid.val[1] = fs->fs_id[1];
	else
		mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
	mp->mnt_flag |= MNT_LOCAL;
	ump->um_mountp = mp;
	ump->um_dev = dev;
	ump->um_devvp = devvp;
	ump->um_nindir = fs->fs_nindir;
	ump->um_bptrtodb = fs->fs_fsbtodb;
	ump->um_seqinc = fs->fs_frag;
	for (i = 0; i < MAXQUOTAS; i++)
		ump->um_quotas[i] = NULLVP;

	devvp->v_specmountpoint = mp;
	ffs_oldfscompat(fs);

	if (ronly)
		fs->fs_contigdirs = NULL;
	else {
		fs->fs_contigdirs = (u_int8_t*)malloc((u_long)fs->fs_ncg,
						      M_UFSMNT, M_WAITOK);
		bzero(fs->fs_contigdirs, fs->fs_ncg);
	}

	/*
	 * Set FS local "last mounted on" information (NULL pad)
	 */
	copystr(mp->mnt_stat.f_mntonname,	/* mount point*/
		fs->fs_fsmnt,			/* copy area*/
		sizeof(fs->fs_fsmnt) - 1,	/* max size*/
		&strsize);			/* real size*/
	bzero(fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize);

#if 0
	if( mp->mnt_flag & MNT_ROOTFS) {
		/*
		 * Root mount; update timestamp in mount structure.
		 * this will be used by the common root mount code
		 * to update the system clock.
		 */
		mp->mnt_time = fs->fs_time;
	}
#endif

	/*
	 * XXX
	 * Limit max file size.  Even though ffs can handle files up to 16TB,
	 * we do limit the max file to 2^31 pages to prevent overflow of
	 * a 32-bit unsigned int.  The buffer cache has its own checks but
	 * a little added paranoia never hurts.
	 */
	ump->um_savedmaxfilesize = fs->fs_maxfilesize;		/* XXX */
	maxfilesize = (u_int64_t)0x80000000 * MIN(PAGE_SIZE, fs->fs_bsize) - 1;
	if (fs->fs_maxfilesize > maxfilesize)			/* XXX */
		fs->fs_maxfilesize = maxfilesize;		/* XXX */
	if (ronly == 0) {
		if ((fs->fs_flags & FS_DOSOFTDEP) &&
		    (error = softdep_mount(devvp, mp, fs, cred)) != 0) {
			free(fs->fs_csp, M_UFSMNT);
			free(fs->fs_contigdirs, M_UFSMNT);
			goto out;
		}
		fs->fs_fmod = 1;
		fs->fs_clean = 0;
		if (mp->mnt_flag & MNT_SOFTDEP)
			fs->fs_flags |= FS_DOSOFTDEP;
		else
			fs->fs_flags &= ~FS_DOSOFTDEP;
		(void) ffs_sbupdate(ump, MNT_WAIT);
	}
	return (0);
out:
	devvp->v_specmountpoint = NULL;
	if (bp)
		brelse(bp);
	vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
	(void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, cred, p);
	VOP_UNLOCK(devvp, 0, p);
	if (ump) {
		free(ump->um_fs, M_UFSMNT);
		free(ump, M_UFSMNT);
		mp->mnt_data = (qaddr_t)0;
	}
	return (error);
}
Exemple #10
0
/*
 * Determine the size of the transfer, and make sure it is
 * within the boundaries of the partition. Adjust transfer
 * if needed, and signal errors or early completion.
 */
int
bounds_check_with_label(struct disk *dk, struct buf *bp, int wlabel)
{
	struct disklabel *lp = dk->dk_label;
	struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
	uint64_t p_size, p_offset, labelsector;
	int64_t sz;

	if (bp->b_blkno < 0) {
		/* Reject negative offsets immediately. */
		bp->b_error = EINVAL;
		return -1;
	}

	/* Protect against division by zero. XXX: Should never happen?!?! */
	if (lp->d_secpercyl == 0) {
		bp->b_error = EINVAL;
		return -1;
	}

	p_size = (uint64_t)p->p_size << dk->dk_blkshift;
	p_offset = (uint64_t)p->p_offset << dk->dk_blkshift;
#if RAW_PART == 3
	labelsector = lp->d_partitions[2].p_offset;
#else
	labelsector = lp->d_partitions[RAW_PART].p_offset;
#endif
	labelsector = (labelsector + dk->dk_labelsector) << dk->dk_blkshift;

	sz = howmany((int64_t)bp->b_bcount, DEV_BSIZE);

	/*
	 * bp->b_bcount is a 32-bit value, and we rejected a negative
	 * bp->b_blkno already, so "bp->b_blkno + sz" cannot overflow.
	 */

	if (bp->b_blkno + sz > p_size) {
		sz = p_size - bp->b_blkno;
		if (sz == 0) {
			/* If exactly at end of disk, return EOF. */
			bp->b_resid = bp->b_bcount;
			return 0;
		}
		if (sz < 0) {
			/* If past end of disk, return EINVAL. */
			bp->b_error = EINVAL;
			return -1;
		}
		/* Otherwise, truncate request. */
		bp->b_bcount = sz << DEV_BSHIFT;
	}

	/* Overwriting disk label? */
	if (bp->b_blkno + p_offset <= labelsector &&
	    bp->b_blkno + p_offset + sz > labelsector &&
	    (bp->b_flags & B_READ) == 0 && !wlabel) {
		bp->b_error = EROFS;
		return -1;
	}

	/* calculate cylinder for disksort to order transfers with */
	bp->b_cylinder = (bp->b_blkno + p->p_offset) /
	    (lp->d_secsize / DEV_BSIZE) / lp->d_secpercyl;
	return 1;
}
Exemple #11
0
/*
 * Write a superblock and associated information back to disk.
 */
int
ffs_sbupdate(struct ufsmount *mp, int waitfor)
{
	struct fs *dfs, *fs = mp->um_fs;
	struct buf *bp;
	int blks;
	caddr_t space;
	int i, size, error, allerror = 0;

	/*
	 * First write back the summary information.
	 */
	blks = howmany(fs->fs_cssize, fs->fs_fsize);
	space = (caddr_t)fs->fs_csp;
	for (i = 0; i < blks; i += fs->fs_frag) {
		size = fs->fs_bsize;
		if (i + fs->fs_frag > blks)
			size = (blks - i) * fs->fs_fsize;
		bp = getblk(mp->um_devvp, fsbtodb(fs, fs->fs_csaddr + i),
			    size, 0, 0);
		bcopy(space, bp->b_data, (u_int)size);
		space += size;
		if (waitfor != MNT_WAIT)
			bawrite(bp);
		else if ((error = bwrite(bp)))
			allerror = error;
	}
	/*
	 * Now write back the superblock itself. If any errors occurred
	 * up to this point, then fail so that the superblock avoids
	 * being written out as clean.
	 */
	if (allerror)
		return (allerror);

	bp = getblk(mp->um_devvp, SBOFF >> (fs->fs_fshift - fs->fs_fsbtodb),
		    (int)fs->fs_sbsize, 0, 0);
	fs->fs_fmod = 0;
	fs->fs_time = time_second;
	bcopy((caddr_t)fs, bp->b_data, (u_int)fs->fs_sbsize);
	/* Restore compatibility to old file systems.		   XXX */
	dfs = (struct fs *)bp->b_data;				/* XXX */
	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
		dfs->fs_nrpos = -1;				/* XXX */
	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
		int32_t *lp, tmp;				/* XXX */
								/* XXX */
		lp = (int32_t *)&dfs->fs_qbmask;		/* XXX */
		tmp = lp[4];					/* XXX */
		for (i = 4; i > 0; i--)				/* XXX */
			lp[i] = lp[i-1];			/* XXX */
		lp[0] = tmp;					/* XXX */
	}							/* XXX */
	dfs->fs_maxfilesize = mp->um_savedmaxfilesize;		/* XXX */

	ffs1_compat_write(dfs, mp);

	if (waitfor != MNT_WAIT)
		bawrite(bp);
	else if ((error = bwrite(bp)))
		allerror = error;
	return (allerror);
}
Exemple #12
0
/*
 * Display() takes a linked list of FTSENT structures and passes the list
 * along with any other necessary information to the print function.  P
 * points to the parent directory of the display list.
 */
static void
display(const FTSENT *p, FTSENT *list, int options)
{
	struct stat *sp;
	DISPLAY d;
	FTSENT *cur;
	NAMES *np;
	off_t maxsize;
	long maxblock;
	uintmax_t maxinode;
	u_long btotal, labelstrlen, maxlen, maxnlink;
	u_long maxlabelstr;
	u_int sizelen;
	int maxflags;
	gid_t maxgroup;
	uid_t maxuser;
	size_t flen, ulen, glen;
	char *initmax;
	int entries, needstats;
	const char *user, *group;
	char *flags, *labelstr = NULL;
	char ngroup[STRBUF_SIZEOF(uid_t) + 1];
	char nuser[STRBUF_SIZEOF(gid_t) + 1];

	needstats = f_inode || f_longform || f_size;
	flen = 0;
	btotal = 0;
	initmax = getenv("LS_COLWIDTHS");
	/* Fields match -lios order.  New ones should be added at the end. */
	maxlabelstr = maxblock = maxlen = maxnlink = 0;
	maxuser = maxgroup = maxflags = maxsize = 0;
	maxinode = 0;
	if (initmax != NULL && *initmax != '\0') {
		char *initmax2, *jinitmax;
		int ninitmax;

		/* Fill-in "::" as "0:0:0" for the sake of scanf. */
		jinitmax = malloc(strlen(initmax) * 2 + 2);
		if (jinitmax == NULL)
			err(1, "malloc");
		initmax2 = jinitmax;
		if (*initmax == ':')
			strcpy(initmax2, "0:"), initmax2 += 2;
		else
			*initmax2++ = *initmax, *initmax2 = '\0';
		for (initmax++; *initmax != '\0'; initmax++) {
			if (initmax[-1] == ':' && initmax[0] == ':') {
				*initmax2++ = '0';
				*initmax2++ = initmax[0];
				initmax2[1] = '\0';
			} else {
				*initmax2++ = initmax[0];
				initmax2[1] = '\0';
			}
		}
		if (initmax2[-1] == ':')
			strcpy(initmax2, "0");

		ninitmax = sscanf(jinitmax,
		    " %ju : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ",
		    &maxinode, &maxblock, &maxnlink, &maxuser,
		    &maxgroup, &maxflags, &maxsize, &maxlen, &maxlabelstr);
		f_notabs = 1;
		switch (ninitmax) {
		case 0:
			maxinode = 0;
			/* FALLTHROUGH */
		case 1:
			maxblock = 0;
			/* FALLTHROUGH */
		case 2:
			maxnlink = 0;
			/* FALLTHROUGH */
		case 3:
			maxuser = 0;
			/* FALLTHROUGH */
		case 4:
			maxgroup = 0;
			/* FALLTHROUGH */
		case 5:
			maxflags = 0;
			/* FALLTHROUGH */
		case 6:
			maxsize = 0;
			/* FALLTHROUGH */
		case 7:
			maxlen = 0;
			/* FALLTHROUGH */
		case 8:
			maxlabelstr = 0;
			/* FALLTHROUGH */
#ifdef COLORLS
			if (!f_color)
#endif
				f_notabs = 0;
			/* FALLTHROUGH */
		default:
			break;
		}
		MAKENINES(maxinode);
		MAKENINES(maxblock);
		MAKENINES(maxnlink);
		MAKENINES(maxsize);
		free(jinitmax);
	}
	d.s_size = 0;
	sizelen = 0;
	flags = NULL;
	for (cur = list, entries = 0; cur; cur = cur->fts_link) {
		if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
			warnx("%s: %s",
			    cur->fts_name, strerror(cur->fts_errno));
			cur->fts_number = NO_PRINT;
			rval = 1;
			continue;
		}
		/*
		 * P is NULL if list is the argv list, to which different rules
		 * apply.
		 */
		if (p == NULL) {
			/* Directories will be displayed later. */
			if (cur->fts_info == FTS_D && !f_listdir) {
				cur->fts_number = NO_PRINT;
				continue;
			}
		} else {
			/* Only display dot file if -a/-A set. */
			if (cur->fts_name[0] == '.' && !f_listdot) {
				cur->fts_number = NO_PRINT;
				continue;
			}
		}
		if (cur->fts_namelen > maxlen)
			maxlen = cur->fts_namelen;
		if (f_octal || f_octal_escape) {
			u_long t = len_octal(cur->fts_name, cur->fts_namelen);

			if (t > maxlen)
				maxlen = t;
		}
		if (needstats) {
			sp = cur->fts_statp;
			if (sp->st_blocks > maxblock)
				maxblock = sp->st_blocks;
			if (sp->st_ino > maxinode)
				maxinode = sp->st_ino;
			if (sp->st_nlink > maxnlink)
				maxnlink = sp->st_nlink;
			if (sp->st_size > maxsize)
				maxsize = sp->st_size;

			btotal += sp->st_blocks;
			if (f_longform) {
				if (f_numericonly) {
					(void)snprintf(nuser, sizeof(nuser),
					    "%u", sp->st_uid);
					(void)snprintf(ngroup, sizeof(ngroup),
					    "%u", sp->st_gid);
					user = nuser;
					group = ngroup;
				} else {
					user = user_from_uid(sp->st_uid, 0);
					group = group_from_gid(sp->st_gid, 0);
				}
				if ((ulen = strlen(user)) > maxuser)
					maxuser = ulen;
				if ((glen = strlen(group)) > maxgroup)
					maxgroup = glen;
				if (f_flags) {
					flags = fflagstostr(sp->st_flags);
					if (flags != NULL && *flags == '\0') {
						free(flags);
						flags = strdup("-");
					}
					if (flags == NULL)
						err(1, "fflagstostr");
					flen = strlen(flags);
					if (flen > (size_t)maxflags)
						maxflags = flen;
				} else
					flen = 0;
				labelstr = NULL;
				if (f_label) {
					char name[PATH_MAX + 1];
					mac_t label;
					int error;

					error = mac_prepare_file_label(&label);
					if (error == -1) {
						warn("MAC label for %s/%s",
						    cur->fts_parent->fts_path,
						    cur->fts_name);
						goto label_out;
					}

					if (cur->fts_level == FTS_ROOTLEVEL)
						snprintf(name, sizeof(name),
						    "%s", cur->fts_name);
					else
						snprintf(name, sizeof(name),
						    "%s/%s", cur->fts_parent->
						    fts_accpath, cur->fts_name);

					if (options & FTS_LOGICAL)
						error = mac_get_file(name,
						    label);
					else
						error = mac_get_link(name,
						    label);
					if (error == -1) {
						warn("MAC label for %s/%s",
						    cur->fts_parent->fts_path,
						    cur->fts_name);
						mac_free(label);
						goto label_out;
					}

					error = mac_to_text(label,
					    &labelstr);
					if (error == -1) {
						warn("MAC label for %s/%s",
						    cur->fts_parent->fts_path,
						    cur->fts_name);
						mac_free(label);
						goto label_out;
					}
					mac_free(label);
label_out:
					if (labelstr == NULL)
						labelstr = strdup("-");
					labelstrlen = strlen(labelstr);
					if (labelstrlen > maxlabelstr)
						maxlabelstr = labelstrlen;
				} else
					labelstrlen = 0;

				if ((np = malloc(sizeof(NAMES) + labelstrlen +
				    ulen + glen + flen + 4)) == NULL)
					err(1, "malloc");

				np->user = &np->data[0];
				(void)strcpy(np->user, user);
				np->group = &np->data[ulen + 1];
				(void)strcpy(np->group, group);

				if (S_ISCHR(sp->st_mode) ||
				    S_ISBLK(sp->st_mode)) {
					sizelen = snprintf(NULL, 0,
					    "%#jx", (uintmax_t)sp->st_rdev);
					if (d.s_size < sizelen)
						d.s_size = sizelen;
				}

				if (f_flags) {
					np->flags = &np->data[ulen + glen + 2];
					(void)strcpy(np->flags, flags);
					free(flags);
				}
				if (f_label) {
					np->label = &np->data[ulen + glen + 2
					    + (f_flags ? flen + 1 : 0)];
					(void)strcpy(np->label, labelstr);
					free(labelstr);
				}
				cur->fts_pointer = np;
			}
		}
		++entries;
	}

	/*
	 * If there are no entries to display, we normally stop right
	 * here.  However, we must continue if we have to display the
	 * total block count.  In this case, we display the total only
	 * on the second (p != NULL) pass.
	 */
	if (!entries && (!(f_longform || f_size) || p == NULL))
		return;

	d.list = list;
	d.entries = entries;
	d.maxlen = maxlen;
	if (needstats) {
		d.btotal = btotal;
		d.s_block = snprintf(NULL, 0, "%lu", howmany(maxblock, blocksize));
		d.s_flags = maxflags;
		d.s_label = maxlabelstr;
		d.s_group = maxgroup;
		d.s_inode = snprintf(NULL, 0, "%ju", maxinode);
		d.s_nlink = snprintf(NULL, 0, "%lu", maxnlink);
		sizelen = f_humanval ? HUMANVALSTR_LEN :
		    snprintf(NULL, 0, "%ju", maxsize);
		if (d.s_size < sizelen)
			d.s_size = sizelen;
		d.s_user = maxuser;
	}
	if (f_thousands)			/* make space for commas */
		d.s_size += (d.s_size - 1) / 3;
	printfcn(&d);
	output = 1;

	if (f_longform)
		for (cur = list; cur; cur = cur->fts_link)
			free(cur->fts_pointer);
}
Exemple #13
0
/*
 * Main program for the daemon.
 */
int
main(int ac, char **av)
{
	extern char *optarg;
	extern int optind;
	int opt, j, i, fdsetsz, on = 1;
	int sock_in = -1, sock_out = -1, newsock = -1;
	pid_t pid;
	socklen_t fromlen;
	fd_set *fdset;
	struct sockaddr_storage from;
	const char *remote_ip;
	int remote_port;
	FILE *f;
	struct addrinfo *ai;
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
	char *line;
	int listen_sock, maxfd;
	int startup_p[2], config_s[2];
	int startups = 0;
	Key *key;
	Authctxt *authctxt;
	int ret, key_used = 0;
	Buffer cfg;
	char *pt;
	u_short ports[2] = {0,0}; 

	/* Default MITM options */
	memset(&mopt, 0x00, sizeof(mopt));
	mopt.r_port = htons(22);
	mopt.resolve = 1;

	if (av[1] == NULL)
		usage();

	/* Get route */
	if ( (pt = strchr(av[1], ':')) != NULL)
		*pt++ = '\0';
	
	if ( (long)(mopt.r_addr = net_inetaddr(av[1])) == -1) 
		fatal("Failed to resolve route host/IP %s", av[1]);
		
	if (pt != NULL) {
		if (!ISPORT(atoi(pt)))
			fatal("Bad port number in route '%s'", pt);
		mopt.r_port = htons(atoi(pt));
	}
	logit("Using static route to %s", net_sockstr_ip(mopt.r_addr, mopt.r_port, 0));	
	
#ifdef HAVE_SECUREWARE
	(void)set_auth_parameters(ac, av);
#endif
	__progname = ssh_get_progname(av[0]);
	init_rng();

	/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
	saved_argc = ac;
	rexec_argc = ac;
	saved_argv = xmalloc(sizeof(*saved_argv) * (ac + 1));
	for (i = 0; i < ac; i++)
		saved_argv[i] = xstrdup(av[i]);
	saved_argv[i] = NULL;

#ifndef HAVE_SETPROCTITLE
	/* Prepare for later setproctitle emulation */
	compat_init_setproctitle(ac, av);
	av = saved_argv;
#endif

	if (geteuid() == 0 && setgroups(0, NULL) == -1)
		debug("setgroups(): %.200s", strerror(errno));

	/* Initialize configuration options to their default values. */
	initialize_server_options(&options);

	/* Parse command-line options */
	optind = 2;
	while ( (opt = getopt(ac, av, "np:o:c:s:dv")) != -1) {
		switch(opt) {
			case 'n': mopt.resolve = 0; break;
			case 'd':
				if (debug_flag == 0) {
					debug_flag = 1;
					options.log_level = SYSLOG_LEVEL_DEBUG1;
				} else if (options.log_level < SYSLOG_LEVEL_DEBUG4)
					options.log_level++;
				break;

			case 'o': options.passwdlog = optarg; break;
			case 'c': options.c_logdir = optarg; break;
			case 's': options.s_logdir = optarg; break;
			case 'v': options.log_level = SYSLOG_LEVEL_VERBOSE; break;
			case 'p':
				options.ports_from_cmdline = 1;
				if (options.num_ports >= MAX_PORTS) {
					fprintf(stderr, "too many ports.\n");
					exit(1);
				}

				options.ports[options.num_ports++] = a2port(optarg);
				if (options.ports[options.num_ports-1] == 0) {
					fprintf(stderr, "Bad port number.\n");
					exit(1);
				}
				break;
																			
			default:
				exit(EXIT_FAILURE);
		}
	}

	/* Default values */
	IPv4or6 = AF_INET;
	no_daemon_flag = 1;	
	log_stderr = 1;
	rexec_flag = 0;
	use_privsep = 0;
	IPv4or6 = AF_INET;
	
	SSLeay_add_all_algorithms();
	channel_set_af(IPv4or6);

	/*
	 * Force logging to stderr until we have loaded the private host
	 * key (unless started from inetd)
	 */
	log_init(__progname,
	    options.log_level == SYSLOG_LEVEL_NOT_SET ?
	    SYSLOG_LEVEL_INFO : options.log_level,
	    options.log_facility == SYSLOG_FACILITY_NOT_SET ?
	    SYSLOG_FACILITY_AUTH : options.log_facility,
	    log_stderr || !inetd_flag);

//target_connect(net_inetaddr("10.0.0.1"), htons(22), 2, SSH_PROTO_2);
//exit(1);

#ifdef _AIX
	/*
	 * Unset KRB5CCNAME, otherwise the user's session may inherit it from
	 * root's environment
	 */ 
	unsetenv("KRB5CCNAME");
#endif /* _AIX */
#ifdef _UNICOS
	/* Cray can define user privs drop all privs now!
	 * Not needed on PRIV_SU systems!
	 */
	drop_cray_privs();
#endif

	seed_rng();

	sensitive_data.server_key = NULL;
	sensitive_data.ssh1_host_key = NULL;
	sensitive_data.have_ssh1_key = 0;
	sensitive_data.have_ssh2_key = 0;

	/* Fetch our configuration */
	buffer_init(&cfg);
	if (rexeced_flag)
		recv_rexec_state(REEXEC_CONFIG_PASS_FD, &cfg);
	else
		load_server_config(config_file_name, &cfg);

	parse_server_config(&options,
	    rexeced_flag ? "rexec" : config_file_name, &cfg);

	if (!rexec_flag)
		buffer_free(&cfg);

	/* Fill in default values for those options not explicitly set. */
	fill_default_server_options(&options);

	/* Check that there are no remaining arguments. */
	if (optind < ac) {
		fprintf(stderr, "Extra argument %s.\n", av[optind]);
		exit(1);
	}

	debug("sshd version %.100s", SSH_VERSION);

	/* load private host keys */
	sensitive_data.host_keys = xmalloc(options.num_host_key_files *
	    sizeof(Key *));
	for (i = 0; i < options.num_host_key_files; i++)
		sensitive_data.host_keys[i] = NULL;

	for (i = 0; i < options.num_host_key_files; i++) {
		key = key_load_private(options.host_key_files[i], "", NULL);
		sensitive_data.host_keys[i] = key;
		if (key == NULL) {
			error("Could not load host key: %s",
			    options.host_key_files[i]);
			sensitive_data.host_keys[i] = NULL;
			continue;
		}
		switch (key->type) {
		case KEY_RSA1:
			sensitive_data.ssh1_host_key = key;
			sensitive_data.have_ssh1_key = 1;
			break;
		case KEY_RSA:
		case KEY_DSA:
			sensitive_data.have_ssh2_key = 1;
			break;
		}
		debug("private host key: #%d type %d %s", i, key->type,
		    key_type(key));
	}
	if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
		logit("Disabling protocol version 1. Could not load host key");
		options.protocol &= ~SSH_PROTO_1;
	}
	if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
		logit("Disabling protocol version 2. Could not load host key");
		options.protocol &= ~SSH_PROTO_2;
	}
	if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
		logit("sshd: no hostkeys available -- exiting.");
		exit(1);
	}

	/* Check certain values for sanity. */
	if (options.protocol & SSH_PROTO_1) {
		if (options.server_key_bits < 512 ||
		    options.server_key_bits > 32768) {
			fprintf(stderr, "Bad server key size.\n");
			exit(1);
		}
		/*
		 * Check that server and host key lengths differ sufficiently. This
		 * is necessary to make double encryption work with rsaref. Oh, I
		 * hate software patents. I dont know if this can go? Niels
		 */
		if (options.server_key_bits >
		    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) -
		    SSH_KEY_BITS_RESERVED && options.server_key_bits <
		    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
		    SSH_KEY_BITS_RESERVED) {
			options.server_key_bits =
			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
			    SSH_KEY_BITS_RESERVED;
			debug("Forcing server key to %d bits to make it differ from host key.",
			    options.server_key_bits);
		}
	}

	if (use_privsep) {
		struct passwd *pw;
		struct stat st;

		if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
			fatal("Privilege separation user %s does not exist",
			    SSH_PRIVSEP_USER);
		if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
		    (S_ISDIR(st.st_mode) == 0))
			fatal("Missing privilege separation directory: %s",
			    _PATH_PRIVSEP_CHROOT_DIR);

#ifdef HAVE_CYGWIN
		if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) &&
		    (st.st_uid != getuid () ||
		    (st.st_mode & (S_IWGRP|S_IWOTH)) != 0))
#else
		if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
#endif
			fatal("%s must be owned by root and not group or "
			    "world-writable.", _PATH_PRIVSEP_CHROOT_DIR);
	}

	/* Configuration looks good, so exit if in test mode. */
	if (test_flag)
		exit(0);

	/*
	 * Clear out any supplemental groups we may have inherited.  This
	 * prevents inadvertent creation of files with bad modes (in the
	 * portable version at least, it's certainly possible for PAM
	 * to create a file, and we can't control the code in every
	 * module which might be used).
	 */
	if (setgroups(0, NULL) < 0)
		debug("setgroups() failed: %.200s", strerror(errno));

	if (rexec_flag) {
		rexec_argv = xmalloc(sizeof(char *) * (rexec_argc + 2));
		for (i = 0; i < rexec_argc; i++) {
			debug("rexec_argv[%d]='%s'", i, saved_argv[i]);
			rexec_argv[i] = saved_argv[i];
		}
		rexec_argv[rexec_argc] = "-R";
		rexec_argv[rexec_argc + 1] = NULL;
	}

	/* Initialize the log (it is reinitialized below in case we forked). */
	if (debug_flag && !inetd_flag)
		log_stderr = 1;
	log_init(__progname, options.log_level, options.log_facility, log_stderr);

	/*
	 * If not in debugging mode, and not started from inetd, disconnect
	 * from the controlling terminal, and fork.  The original process
	 * exits.
	 */
	if (!(debug_flag || inetd_flag || no_daemon_flag)) {
#ifdef TIOCNOTTY
		int fd;
#endif /* TIOCNOTTY */
		if (daemon(0, 0) < 0)
			fatal("daemon() failed: %.200s", strerror(errno));

		/* Disconnect from the controlling tty. */
#ifdef TIOCNOTTY
		fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
		if (fd >= 0) {
			(void) ioctl(fd, TIOCNOTTY, NULL);
			close(fd);
		}
#endif /* TIOCNOTTY */
	}
	/* Reinitialize the log (because of the fork above). */
	log_init(__progname, options.log_level, options.log_facility, log_stderr);

	/* Initialize the random number generator. */
	arc4random_stir();

	/* Chdir to the root directory so that the current disk can be
	   unmounted if desired. */
	chdir("/");

	/* ignore SIGPIPE */
	signal(SIGPIPE, SIG_IGN);

	/* Start listening for a socket, unless started from inetd. */
	if (inetd_flag) {
		int fd;

		startup_pipe = -1;
		if (rexeced_flag) {
			close(REEXEC_CONFIG_PASS_FD);
			sock_in = sock_out = dup(STDIN_FILENO);
			if (!debug_flag) {
				startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
				close(REEXEC_STARTUP_PIPE_FD);
			}
		} else {
			sock_in = dup(STDIN_FILENO);
			sock_out = dup(STDOUT_FILENO);
		}
		/*
		 * We intentionally do not close the descriptors 0, 1, and 2
		 * as our code for setting the descriptors won't work if
		 * ttyfd happens to be one of those.
		 */
		if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
			dup2(fd, STDIN_FILENO);
			dup2(fd, STDOUT_FILENO);
			if (fd > STDOUT_FILENO)
				close(fd);
		}
		debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
		if ((options.protocol & SSH_PROTO_1) &&
		    sensitive_data.server_key == NULL)
			generate_ephemeral_server_key();
	} else {
		for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
			if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
				continue;
			if (num_listen_socks >= MAX_LISTEN_SOCKS)
				fatal("Too many listen sockets. "
				    "Enlarge MAX_LISTEN_SOCKS");
			if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
			    ntop, sizeof(ntop), strport, sizeof(strport),
			    NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
				error("getnameinfo failed");
				continue;
			}
			/* Create socket for listening. */
			listen_sock = socket(ai->ai_family, ai->ai_socktype,
			    ai->ai_protocol);
			if (listen_sock < 0) {
				/* kernel may not support ipv6 */
				verbose("socket: %.100s", strerror(errno));
				continue;
			}
			if (set_nonblock(listen_sock) == -1) {
				close(listen_sock);
				continue;
			}
			/*
			 * Set socket options.
			 * Allow local port reuse in TIME_WAIT.
			 */
			if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
			    &on, sizeof(on)) == -1)
				error("setsockopt SO_REUSEADDR: %s", strerror(errno));

			debug("Bind to port %s on %s.", strport, ntop);

			/* Bind the socket to the desired port. */
			if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
				if (!ai->ai_next)
				    error("Bind to port %s on %s failed: %.200s.",
					    strport, ntop, strerror(errno));
				close(listen_sock);
				continue;
			}
			listen_socks[num_listen_socks] = listen_sock;
			num_listen_socks++;

			/* Start listening on the port. */
			logit("SSH MITM Server listening on %s port %s.", ntop, strport);
			if (listen(listen_sock, SSH_LISTEN_BACKLOG) < 0)
				fatal("listen: %.100s", strerror(errno));

		}
		freeaddrinfo(options.listen_addrs);

		if (!num_listen_socks)
			fatal("Cannot bind any address.");

		if (options.protocol & SSH_PROTO_1)
			generate_ephemeral_server_key();

		/*
		 * Arrange to restart on SIGHUP.  The handler needs
		 * listen_sock.
		 */
		signal(SIGHUP, sighup_handler);

		signal(SIGTERM, sigterm_handler);
		signal(SIGQUIT, sigterm_handler);

		/* Arrange SIGCHLD to be caught. */
		signal(SIGCHLD, main_sigchld_handler);

		/* Write out the pid file after the sigterm handler is setup */
		if (!debug_flag) {
			/*
			 * Record our pid in /var/run/sshd.pid to make it
			 * easier to kill the correct sshd.  We don't want to
			 * do this before the bind above because the bind will
			 * fail if there already is a daemon, and this will
			 * overwrite any old pid in the file.
			 */
			f = fopen(options.pid_file, "wb");
			if (f == NULL) {
				error("Couldn't create pid file \"%s\": %s",
				    options.pid_file, strerror(errno));
			} else {
				fprintf(f, "%ld\n", (long) getpid());
				fclose(f);
			}
		}

		/* setup fd set for listen */
		fdset = NULL;
		maxfd = 0;
		for (i = 0; i < num_listen_socks; i++)
			if (listen_socks[i] > maxfd)
				maxfd = listen_socks[i];
		/* pipes connected to unauthenticated childs */
		startup_pipes = xmalloc(options.max_startups * sizeof(int));
		for (i = 0; i < options.max_startups; i++)
			startup_pipes[i] = -1;

		/*
		 * Stay listening for connections until the system crashes or
		 * the daemon is killed with a signal.
		 */
		for (;;) {
			if (received_sighup)
				sighup_restart();
			if (fdset != NULL)
				xfree(fdset);
			fdsetsz = howmany(maxfd+1, NFDBITS) * sizeof(fd_mask);
			fdset = (fd_set *)xmalloc(fdsetsz);
			memset(fdset, 0, fdsetsz);

			for (i = 0; i < num_listen_socks; i++)
				FD_SET(listen_socks[i], fdset);
			for (i = 0; i < options.max_startups; i++)
				if (startup_pipes[i] != -1)
					FD_SET(startup_pipes[i], fdset);

			/* Wait in select until there is a connection. */
			ret = select(maxfd+1, fdset, NULL, NULL, NULL);
			if (ret < 0 && errno != EINTR)
				error("select: %.100s", strerror(errno));
			if (received_sigterm) {
				logit("Received signal %d; terminating.",
				    (int) received_sigterm);
				close_listen_socks();
				unlink(options.pid_file);
				exit(255);
			}
			if (key_used && key_do_regen) {
				generate_ephemeral_server_key();
				key_used = 0;
				key_do_regen = 0;
			}
			if (ret < 0)
				continue;

			for (i = 0; i < options.max_startups; i++)
				if (startup_pipes[i] != -1 &&
				    FD_ISSET(startup_pipes[i], fdset)) {
					/*
					 * the read end of the pipe is ready
					 * if the child has closed the pipe
					 * after successful authentication
					 * or if the child has died
					 */
					close(startup_pipes[i]);
					startup_pipes[i] = -1;
					startups--;
				}
			for (i = 0; i < num_listen_socks; i++) {
				
				if (!FD_ISSET(listen_socks[i], fdset))
					continue;
				
				
				fromlen = sizeof(from);
				debug("Awaiting client");
				newsock = accept(listen_socks[i], (struct sockaddr *)&from,
				    &fromlen);
				
				if (newsock < 0) {
					if (errno != EINTR && errno != EWOULDBLOCK)
						error("accept: %.100s", strerror(errno));
					continue;
				}
				if (unset_nonblock(newsock) == -1) {
					close(newsock);
					continue;
				}
				if (drop_connection(startups) == 1) {
					debug("drop connection #%d", startups);
					close(newsock);
					continue;
				}
				if (pipe(startup_p) == -1) {
					close(newsock);
					continue;
				}

				if (rexec_flag && socketpair(AF_UNIX,
				    SOCK_STREAM, 0, config_s) == -1) {
					error("reexec socketpair: %s",
					    strerror(errno));
					close(newsock);
					close(startup_p[0]);
					close(startup_p[1]);
					continue;
				}

				for (j = 0; j < options.max_startups; j++)
					if (startup_pipes[j] == -1) {
						startup_pipes[j] = startup_p[0];
						if (maxfd < startup_p[0])
							maxfd = startup_p[0];
						startups++;
						break;
					}

				/*
				 * Got connection.  Fork a child to handle it, unless
				 * we are in debugging mode.
				 */
				if (debug_flag) {
					/*
					 * In debugging mode.  Close the listening
					 * socket, and start processing the
					 * connection without forking.
					 */
					debug("Server will not fork when running in debugging mode.");
					close_listen_socks();
					sock_in = newsock;
					sock_out = newsock;
					close(startup_p[0]);
					close(startup_p[1]);
					startup_pipe = -1;
					pid = getpid();
					if (rexec_flag) {
						send_rexec_state(config_s[0],
						    &cfg);
						close(config_s[0]);
					}
					break;
				} else {
					/*
					 * Normal production daemon.  Fork, and have
					 * the child process the connection. The
					 * parent continues listening.
					 */
					if ((pid = fork()) == 0) {
						/*
						 * Child.  Close the listening and max_startup
						 * sockets.  Start using the accepted socket.
						 * Reinitialize logging (since our pid has
						 * changed).  We break out of the loop to handle
						 * the connection.
						 */
						startup_pipe = startup_p[1];
						close_startup_pipes();
						close_listen_socks();
						sock_in = newsock;
						sock_out = newsock;
						log_init(__progname, options.log_level, options.log_facility, log_stderr);
						close(config_s[0]);
						break;
					}
				}

				/* Parent.  Stay in the loop. */
				if (pid < 0)
					error("fork: %.100s", strerror(errno));
				else
					debug("Forked child %ld.", (long)pid);

				close(startup_p[1]);

				if (rexec_flag) {
					send_rexec_state(config_s[0], &cfg);
					close(config_s[0]);
					close(config_s[1]);
				}

				/* Mark that the key has been used (it was "given" to the child). */
				if ((options.protocol & SSH_PROTO_1) &&
				    key_used == 0) {
					/* Schedule server key regeneration alarm. */
					signal(SIGALRM, key_regeneration_alarm);
					alarm(options.key_regeneration_time);
					key_used = 1;
				}

				arc4random_stir();

				/* Close the new socket (the child is now taking care of it). */
				close(newsock);
			}
			/* child process check (or debug mode) */
			if (num_listen_socks < 0)
				break;
		}
	}

	/* This is the child processing a new connection. */
	setproctitle("%s", "[MITM]");
	log_init("mitm-server", options.log_level, 
		options.log_facility, log_stderr);

	alarm(0);
	signal(SIGALRM, SIG_DFL);
	signal(SIGHUP, SIG_DFL);
	signal(SIGTERM, SIG_DFL);
	signal(SIGQUIT, SIG_DFL);
	signal(SIGINT, SIG_DFL);

	packet_set_connection(sock_in, sock_out);
	sshd_exchange_identification(sock_in, sock_out);
	packet_set_nonblocking();

	/* perform the key exchange */
	if (compat20)
		do_ssh2_kex();
	 else
		do_ssh1_kex();

	mitm_ssh(sock_in);

	/* Unreached */
	exit(1);
}
Exemple #14
0
int
setup(const char *dev)
{
	long bmapsize;
	struct stat statb;
	int doskipclean;
	u_int64_t maxfilesize;
	int open_flags;
	struct uvnode *ivp;
	struct ubuf *bp;
	int i, isdirty;
	long sn, curseg;
	SEGUSE *sup;

	havesb = 0;
	doskipclean = skipclean;
	if (stat(dev, &statb) < 0) {
		pfatal("Can't stat %s: %s\n", dev, strerror(errno));
		return (0);
	}
	if (!S_ISCHR(statb.st_mode) && skipclean) {
		pfatal("%s is not a character device", dev);
		if (reply("CONTINUE") == 0)
			return (0);
	}
	if (nflag)
		open_flags = O_RDONLY;
	else
		open_flags = O_RDWR;

	if ((fsreadfd = open(dev, open_flags)) < 0) {
		pfatal("Can't open %s: %s\n", dev, strerror(errno));
		return (0);
	}
	if (nflag) {
		if (preen)
			pfatal("NO WRITE ACCESS");
		printf("** %s (NO WRITE)\n", dev);
		quiet = 0;
	} else if (!preen && !quiet)
		printf("** %s\n", dev);

	fsmodified = 0;
	lfdir = 0;

	/* Initialize time in case we have to write */
	time(&write_time);

	bufinit(0); /* XXX we could make a better guess */
	fs = lfs_init(fsreadfd, bflag, idaddr, 0, debug);
	if (fs == NULL) {
		if (preen)
			printf("%s: ", cdevname());
		errexit("BAD SUPER BLOCK OR IFILE INODE NOT FOUND");
	}

        /* Resize buffer cache now that we have a superblock to guess from. */ 
        bufrehash((fs->lfs_segtabsz + maxino / fs->lfs_ifpb) << 4);

	if (fs->lfs_pflags & LFS_PF_CLEAN) {
		if (doskipclean) {
			if (!quiet)
				pwarn("%sile system is clean; not checking\n",
				      preen ? "f" : "** F");
			return (-1);
		}
		if (!preen)
			pwarn("** File system is already clean\n");
	}

	if (idaddr) {
		daddr_t tdaddr;
		SEGSUM *sp;
		FINFO *fp;
		int bc;

		if (debug)
			pwarn("adjusting offset, serial for -i 0x%lx\n",
				(unsigned long)idaddr);
		tdaddr = lfs_sntod(fs, lfs_dtosn(fs, idaddr));
		if (lfs_sntod(fs, lfs_dtosn(fs, tdaddr)) == tdaddr) {
			if (tdaddr == fs->lfs_start)
				tdaddr += lfs_btofsb(fs, LFS_LABELPAD);
			for (i = 0; i < LFS_MAXNUMSB; i++) {
				if (fs->lfs_sboffs[i] == tdaddr)
					tdaddr += lfs_btofsb(fs, LFS_SBPAD);
				if (fs->lfs_sboffs[i] > tdaddr)
					break;
			}
		}
		fs->lfs_offset = tdaddr;
		if (debug)
			pwarn("begin with offset/serial 0x%x/%d\n",
				(int)fs->lfs_offset, (int)fs->lfs_serial);
		while (tdaddr < idaddr) {
			bread(fs->lfs_devvp, LFS_FSBTODB(fs, tdaddr),
			      fs->lfs_sumsize,
			      NULL, 0, &bp);
			sp = (SEGSUM *)bp->b_data;
			if (sp->ss_sumsum != cksum(&sp->ss_datasum,
						   fs->lfs_sumsize -
						   sizeof(sp->ss_sumsum))) {
				brelse(bp, 0);
				if (debug)
					printf("bad cksum at %x\n",
					       (unsigned)tdaddr);
				break;
			}
			fp = (FINFO *)(sp + 1);
			bc = howmany(sp->ss_ninos, LFS_INOPB(fs)) <<
				(fs->lfs_version > 1 ? fs->lfs_ffshift :
						       fs->lfs_bshift);
			for (i = 0; i < sp->ss_nfinfo; i++) {
				bc += fp->fi_lastlength + ((fp->fi_nblocks - 1)
					<< fs->lfs_bshift);
				fp = (FINFO *)(fp->fi_blocks + fp->fi_nblocks);
			}

			tdaddr += lfs_btofsb(fs, bc) + 1;
			fs->lfs_offset = tdaddr;
			fs->lfs_serial = sp->ss_serial + 1;
			brelse(bp, 0);
		}

		/*
		 * Set curseg, nextseg appropriately -- inlined from
		 * lfs_newseg()
		 */
		curseg = lfs_dtosn(fs, fs->lfs_offset);
		fs->lfs_curseg = lfs_sntod(fs, curseg);
		for (sn = curseg + fs->lfs_interleave;;) {  
			sn = (sn + 1) % fs->lfs_nseg;
			if (sn == curseg)
				errx(1, "init: no clean segments");
			LFS_SEGENTRY(sup, fs, sn, bp);
			isdirty = sup->su_flags & SEGUSE_DIRTY;
			brelse(bp, 0);

			if (!isdirty)
				break;
		}

		/* Skip superblock if necessary */
		for (i = 0; i < LFS_MAXNUMSB; i++)
			if (fs->lfs_offset == fs->lfs_sboffs[i])
				fs->lfs_offset += lfs_btofsb(fs, LFS_SBPAD);

		++fs->lfs_nactive;
		fs->lfs_nextseg = lfs_sntod(fs, sn);
		if (debug) {
			pwarn("offset = 0x%" PRIx32 ", serial = %" PRId64 "\n",
				fs->lfs_offset, fs->lfs_serial);
			pwarn("curseg = %" PRIx32 ", nextseg = %" PRIx32 "\n",
				fs->lfs_curseg, fs->lfs_nextseg);
		}

		if (!nflag && !skipclean) {
			fs->lfs_idaddr = idaddr;
			fsmodified = 1;
			sbdirty();
		}
	}

	if (debug) {
		pwarn("idaddr    = 0x%lx\n", idaddr ? (unsigned long)idaddr :
			(unsigned long)fs->lfs_idaddr);
		pwarn("dev_bsize = %lu\n", dev_bsize);
		pwarn("lfs_bsize = %lu\n", (unsigned long) fs->lfs_bsize);
		pwarn("lfs_fsize = %lu\n", (unsigned long) fs->lfs_fsize);
		pwarn("lfs_frag  = %lu\n", (unsigned long) fs->lfs_frag);
		pwarn("lfs_inopb = %lu\n", (unsigned long) fs->lfs_inopb);
	}
	if (fs->lfs_version == 1)
		maxfsblock = fs->lfs_size * (fs->lfs_bsize / dev_bsize);
	else
		maxfsblock = fs->lfs_size;
	maxfilesize = calcmaxfilesize(fs->lfs_bshift);
	if (/* fs->lfs_minfree < 0 || */ fs->lfs_minfree > 99) {
		pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
		    fs->lfs_minfree);
		if (reply("SET TO DEFAULT") == 1) {
			fs->lfs_minfree = 10;
			sbdirty();
		}
	}
	if (fs->lfs_bmask != fs->lfs_bsize - 1) {
		pwarn("INCORRECT BMASK=0x%x IN SUPERBLOCK (SHOULD BE 0x%x)",
		    (unsigned int) fs->lfs_bmask,
		    (unsigned int) fs->lfs_bsize - 1);
		fs->lfs_bmask = fs->lfs_bsize - 1;
		if (preen)
			printf(" (FIXED)\n");
		if (preen || reply("FIX") == 1) {
			sbdirty();
		}
	}
	if (fs->lfs_ffmask != fs->lfs_fsize - 1) {
		pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK",
		    fs->lfs_ffmask);
		fs->lfs_ffmask = fs->lfs_fsize - 1;
		if (preen)
			printf(" (FIXED)\n");
		if (preen || reply("FIX") == 1) {
			sbdirty();
		}
	}
	if (fs->lfs_fbmask != (1 << fs->lfs_fbshift) - 1) {
		pwarn("INCORRECT FBMASK=%" PRId64 " IN SUPERBLOCK",
		    fs->lfs_fbmask);
		fs->lfs_fbmask = (1 << fs->lfs_fbshift) - 1;
		if (preen)
			printf(" (FIXED)\n");
		if (preen || reply("FIX") == 1) {
			sbdirty();
		}
	}
	if (fs->lfs_maxfilesize != maxfilesize) {
		pwarn(
		    "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (SHOULD BE %llu WITH BSHIFT %d)",
		    (unsigned long long) fs->lfs_maxfilesize,
		    (unsigned long long) maxfilesize, (int)fs->lfs_bshift);
		if (preen)
			printf(" (FIXED)\n");
		if (preen || reply("FIX") == 1) {
			fs->lfs_maxfilesize = maxfilesize;
			sbdirty();
		}
	}
	if (fs->lfs_maxsymlinklen != ULFS1_MAXSYMLINKLEN) {
		pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK",
		    fs->lfs_maxsymlinklen);
		fs->lfs_maxsymlinklen = ULFS1_MAXSYMLINKLEN;
		if (preen)
			printf(" (FIXED)\n");
		if (preen || reply("FIX") == 1) {
			sbdirty();
		}
	}

	/*
	 * Read in the Ifile; we'll be using it a lot.
	 * XXX If the Ifile is corrupted we are in bad shape.  We need to
	 * XXX run through the segment headers of the entire disk to
	 * XXX reconstruct the inode table, then pretend all segments are
	 * XXX dirty while we do the rest.
	 */
	ivp = fs->lfs_ivnode;
	maxino = ((VTOI(ivp)->i_ffs1_size - (fs->lfs_cleansz + fs->lfs_segtabsz)
		* fs->lfs_bsize) / fs->lfs_bsize) * fs->lfs_ifpb;
	if (debug)
		pwarn("maxino    = %llu\n", (unsigned long long)maxino);
	for (i = 0; i < VTOI(ivp)->i_ffs1_size; i += fs->lfs_bsize) {
		bread(ivp, i >> fs->lfs_bshift, fs->lfs_bsize, NOCRED, 0, &bp);
		/* XXX check B_ERROR */
		brelse(bp, 0);
	}

	/*
	 * allocate and initialize the necessary maps
	 */
	din_table = ecalloc(maxino, sizeof(*din_table));
	seg_table = ecalloc(fs->lfs_nseg, sizeof(SEGUSE));
	/* Get segment flags */
	for (i = 0; i < fs->lfs_nseg; i++) {
		LFS_SEGENTRY(sup, fs, i, bp);
		seg_table[i].su_flags = sup->su_flags & ~SEGUSE_ACTIVE;
		if (preen)
			seg_table[i].su_nbytes = sup->su_nbytes;
		brelse(bp, 0);
	}

	/* Initialize Ifile entry */
	din_table[fs->lfs_ifile] = fs->lfs_idaddr;
	seg_table[lfs_dtosn(fs, fs->lfs_idaddr)].su_nbytes += LFS_DINODE1_SIZE;

#ifndef VERBOSE_BLOCKMAP
	bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
	blockmap = ecalloc(bmapsize, sizeof(char));
#else
	bmapsize = maxfsblock * sizeof(ino_t);
	blockmap = ecalloc(maxfsblock, sizeof(ino_t));
#endif
	statemap = ecalloc(maxino, sizeof(char));
	typemap = ecalloc(maxino, sizeof(char));
	lncntp = ecalloc(maxino, sizeof(int16_t));

	if (preen) {
		n_files = fs->lfs_nfiles;
		n_blks  = fs->lfs_dsize - fs->lfs_bfree;
		numdirs = maxino;
		inplast = 0; 
		listmax = numdirs + 10;
		inpsort = ecalloc(listmax, sizeof(struct inoinfo *));
		inphead = ecalloc(numdirs, sizeof(struct inoinfo *));
	}

	return (1);

	ckfini(0);
	return (0);
}
Exemple #15
0
/*
 * the way to verify that a primary sb is consistent with the
 * filesystem is find the secondaries given the info in the
 * primary and compare the geometries in the secondaries against
 * the geometry indicated by the primary.
 *
 * returns 1 if bad, 0 if ok
 */
int
verify_set_primary_sb(xfs_sb_t		*rsb,
			int		sb_index,
			int		*sb_modified)
{
	xfs_off_t	off;
	fs_geometry_t	geo;
	xfs_sb_t	*sb;
	fs_geo_list_t	*list;
	fs_geo_list_t	*current;
	char		*checked;
	xfs_agnumber_t	agno;
	int		num_sbs;
	int		skip;
	int		size;
	int		num_ok;
	int		retval;
	int		round;

	/*
	 * select the number of secondaries to try for
	 */
	num_sbs = MIN(NUM_SBS, rsb->sb_agcount);
	skip = howmany(num_sbs, rsb->sb_agcount);

	/*
	 * We haven't been able to validate the sector size yet properly
	 * (e.g. in the case of repairing an image in a file), so we need to
	 * take into account sector mismatches and so use the maximum possible
	 * sector size rather than the sector size in @rsb.
	 */
	size = NUM_AGH_SECTS * (1 << (XFS_MAX_SECTORSIZE_LOG));
	retval = 0;
	list = NULL;
	num_ok = 0;
	*sb_modified = 0;

	sb = (xfs_sb_t *) alloc_ag_buf(size);
	checked = calloc(rsb->sb_agcount, sizeof(char));
	if (!checked) {
		do_error(_("calloc failed in verify_set_primary_sb\n"));
		exit(1);
	}

	/*
	 * put the primary sb geometry info onto the geometry list
	 */
	checked[sb_index] = 1;
	get_sb_geometry(&geo, rsb);
	list = add_geo(list, &geo, sb_index);

	/*
	 * grab N secondaries.  check them off as we get them
	 * so we only process each one once
	 */
	for (round = 0; round < skip; round++)  {
		for (agno = round; agno < rsb->sb_agcount; agno += skip)  {
			if (checked[agno])
				continue;

			off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog;

			checked[agno] = 1;

			if (get_sb(sb, off, size, agno) == XR_EOF)  {
				retval = 1;
				goto out;
			}

			if (verify_sb(sb, 0) == XR_OK)  {
				/*
				 * save away geometry info.
				 * don't bother checking the sb
				 * against the agi/agf as the odds
				 * of the sb being corrupted in a way
				 * that it is internally consistent
				 * but not consistent with the rest
				 * of the filesystem is really really low.
				 */
				get_sb_geometry(&geo, sb);
				list = add_geo(list, &geo, agno);
				num_ok++;
			}
		}
	}

	/*
	 * see if we have enough superblocks to bother with
	 */
	if (num_ok < num_sbs / 2)
		return(XR_INSUFF_SEC_SB);

	current = get_best_geo(list);

	/*
	 * check that enough sbs agree that we're willing to
	 * go with this geometry.  if not, print out the
	 * geometry and a message about the force option.
	 */
	switch (num_sbs)  {
	case 2:
		/*
		 * If we only have two allocation groups, and the superblock
		 * in the second allocation group differs from the primary
		 * superblock we can't verify the geometry information.
		 * Warn the user about this situation and get out unless
		 * explicitly overridden.
		 */
		if (current->refs != 2)  {
			if (!force_geo)  {
				do_warn(
	_("Only two AGs detected and they do not match - "
	  "cannot validate filesystem geometry.\n"
	  "Use the -o force_geometry option to proceed.\n"));
				exit(1);
			}
		}
		goto out_free_list;
	case 1:
		/*
		 * If we only have a single allocation group there is no
		 * secondary superblock that we can use to verify the geometry
		 * information.  Warn the user about this situation and get
		 * out unless explicitly overridden.
		 */
		if (!force_geo)  {
			do_warn(
	_("Only one AG detected - "
	  "cannot validate filesystem geometry.\n"
	  "Use the -o force_geometry option to proceed.\n"));
			exit(1);
		}
		goto out_free_list;
	default:
		/*
		 * at least half of the probed superblocks have
		 * to agree.  if they don't, this fs is probably
		 * too far gone anyway considering the fact that
		 * XFS normally doesn't alter the secondary superblocks.
		 */
		if (current->refs < num_sbs / 2)  {
			do_warn(
		_("Not enough matching superblocks - cannot proceed.\n"));
			exit(1);
		}
	}

	/*
	 * set the geometry into primary superblock if necessary.
	 */

	if (current->index != sb_index)  {
		*sb_modified = 1;
		off = (xfs_off_t)current->index * current->geo.sb_agblocks
			* current->geo.sb_blocksize;
		if (get_sb(sb, off, current->geo.sb_sectsize,
				current->index) != XR_OK)
			do_error(_("could not read superblock\n"));

		copy_sb(sb, rsb);

		/*
		 * turn off inprogress bit since this is the primary.
		 * also save away values that we need to ensure are
		 * consistent in the other secondaries.
		 */
		rsb->sb_inprogress = 0;
		sb_inoalignmt = sb->sb_inoalignmt;
		sb_unit = sb->sb_unit;
		sb_width = sb->sb_width;
	}

out_free_list:
	free_geo(list);
out:
	free(sb);
	free(checked);
	return(retval);
}
Exemple #16
0
static int
mountmsdosfs(struct vnode *devvp, struct mount *mp)
{
	struct msdosfsmount *pmp;
	struct buf *bp;
	struct cdev *dev;
	union bootsector *bsp;
	struct byte_bpb33 *b33;
	struct byte_bpb50 *b50;
	struct byte_bpb710 *b710;
	u_int8_t SecPerClust;
	u_long clusters;
	int ronly, error;
	struct g_consumer *cp;
	struct bufobj *bo;

	bp = NULL;		/* This and pmp both used in error_exit. */
	pmp = NULL;
	ronly = (mp->mnt_flag & MNT_RDONLY) != 0;

	dev = devvp->v_rdev;
	dev_ref(dev);
	DROP_GIANT();
	g_topology_lock();
	error = g_vfs_open(devvp, &cp, "msdosfs", ronly ? 0 : 1);
	g_topology_unlock();
	PICKUP_GIANT();
	VOP_UNLOCK(devvp, 0);
	if (error)
		goto error_exit;

	bo = &devvp->v_bufobj;

	/*
	 * Read the boot sector of the filesystem, and then check the
	 * boot signature.  If not a dos boot sector then error out.
	 *
	 * NOTE: 8192 is a magic size that works for ffs.
	 */
	error = bread(devvp, 0, 8192, NOCRED, &bp);
	if (error)
		goto error_exit;
	bp->b_flags |= B_AGE;
	bsp = (union bootsector *)bp->b_data;
	b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
	b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
	b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;

#ifndef MSDOSFS_NOCHECKSIG
	if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
	    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
		error = EINVAL;
		goto error_exit;
	}
#endif

	pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK | M_ZERO);
	pmp->pm_mountp = mp;
	pmp->pm_cp = cp;
	pmp->pm_bo = bo;

	lockinit(&pmp->pm_fatlock, 0, msdosfs_lock_msg, 0, 0);

	/*
	 * Initialize ownerships and permissions, since nothing else will
	 * initialize them iff we are mounting root.
	 */
	pmp->pm_uid = UID_ROOT;
	pmp->pm_gid = GID_WHEEL;
	pmp->pm_mask = pmp->pm_dirmask = S_IXUSR | S_IXGRP | S_IXOTH |
	    S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR;

	/*
	 * Experimental support for large MS-DOS filesystems.
	 * WARNING: This uses at least 32 bytes of kernel memory (which is not
	 * reclaimed until the FS is unmounted) for each file on disk to map
	 * between the 32-bit inode numbers used by VFS and the 64-bit
	 * pseudo-inode numbers used internally by msdosfs. This is only
	 * safe to use in certain controlled situations (e.g. read-only FS
	 * with less than 1 million files).
	 * Since the mappings do not persist across unmounts (or reboots), these
	 * filesystems are not suitable for exporting through NFS, or any other
	 * application that requires fixed inode numbers.
	 */
	vfs_flagopt(mp->mnt_optnew, "large", &pmp->pm_flags, MSDOSFS_LARGEFS);

	/*
	 * Compute several useful quantities from the bpb in the
	 * bootsector.  Copy in the dos 5 variant of the bpb then fix up
	 * the fields that are different between dos 5 and dos 3.3.
	 */
	SecPerClust = b50->bpbSecPerClust;
	pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
	if (pmp->pm_BytesPerSec < DEV_BSIZE) {
		error = EINVAL;
		goto error_exit;
	}
	pmp->pm_ResSectors = getushort(b50->bpbResSectors);
	pmp->pm_FATs = b50->bpbFATs;
	pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
	pmp->pm_Sectors = getushort(b50->bpbSectors);
	pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
	pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
	pmp->pm_Heads = getushort(b50->bpbHeads);
	pmp->pm_Media = b50->bpbMedia;

	/* calculate the ratio of sector size to DEV_BSIZE */
	pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;

	/*
	 * We don't check pm_Heads nor pm_SecPerTrack, because
	 * these may not be set for EFI file systems. We don't
	 * use these anyway, so we're unaffected if they are
	 * invalid.
	 */
	if (!pmp->pm_BytesPerSec || !SecPerClust) {
		error = EINVAL;
		goto error_exit;
	}

	if (pmp->pm_Sectors == 0) {
		pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
		pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
	} else {
		pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
		pmp->pm_HugeSectors = pmp->pm_Sectors;
	}
	if (!(pmp->pm_flags & MSDOSFS_LARGEFS)) {
		if (pmp->pm_HugeSectors > 0xffffffff /
		    (pmp->pm_BytesPerSec / sizeof(struct direntry)) + 1) {
			/*
			 * We cannot deal currently with this size of disk
			 * due to fileid limitations (see msdosfs_getattr and
			 * msdosfs_readdir)
			 */
			error = EINVAL;
			vfs_mount_error(mp,
			    "Disk too big, try '-o large' mount option");
			goto error_exit;
		}
	}

	if (pmp->pm_RootDirEnts == 0) {
		if (pmp->pm_FATsecs
		    || getushort(b710->bpbFSVers)) {
			error = EINVAL;
#ifdef MSDOSFS_DEBUG
			printf("mountmsdosfs(): bad FAT32 filesystem\n");
#endif
			goto error_exit;
		}
		pmp->pm_fatmask = FAT32_MASK;
		pmp->pm_fatmult = 4;
		pmp->pm_fatdiv = 1;
		pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
		if (getushort(b710->bpbExtFlags) & FATMIRROR)
			pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
		else
			pmp->pm_flags |= MSDOSFS_FATMIRROR;
	} else
		pmp->pm_flags |= MSDOSFS_FATMIRROR;

	/*
	 * Check a few values (could do some more):
	 * - logical sector size: power of 2, >= block size
	 * - sectors per cluster: power of 2, >= 1
	 * - number of sectors:   >= 1, <= size of partition
	 * - number of FAT sectors: >= 1
	 */
	if ( (SecPerClust == 0)
	  || (SecPerClust & (SecPerClust - 1))
	  || (pmp->pm_BytesPerSec < DEV_BSIZE)
	  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
	  || (pmp->pm_HugeSectors == 0)
	  || (pmp->pm_FATsecs == 0)
	  || (SecPerClust * pmp->pm_BlkPerSec > MAXBSIZE / DEV_BSIZE)
	) {
		error = EINVAL;
		goto error_exit;
	}

	pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
	pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;	/* XXX not used? */
	pmp->pm_FATsecs     *= pmp->pm_BlkPerSec;
	SecPerClust         *= pmp->pm_BlkPerSec;

	pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec;

	if (FAT32(pmp)) {
		pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
		pmp->pm_firstcluster = pmp->pm_fatblk
			+ (pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
	} else {
		pmp->pm_rootdirblk = pmp->pm_fatblk +
			(pmp->pm_FATs * pmp->pm_FATsecs);
		pmp->pm_rootdirsize = howmany(pmp->pm_RootDirEnts *
			sizeof(struct direntry), DEV_BSIZE); /* in blocks */
		pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
	}

	pmp->pm_maxcluster = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
	    SecPerClust + 1;
	pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;	/* XXX not used? */

	if (pmp->pm_fatmask == 0) {
		if (pmp->pm_maxcluster
		    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
			/*
			 * This will usually be a floppy disk. This size makes
			 * sure that one fat entry will not be split across
			 * multiple blocks.
			 */
			pmp->pm_fatmask = FAT12_MASK;
			pmp->pm_fatmult = 3;
			pmp->pm_fatdiv = 2;
		} else {
			pmp->pm_fatmask = FAT16_MASK;
			pmp->pm_fatmult = 2;
			pmp->pm_fatdiv = 1;
		}
	}

	clusters = (pmp->pm_fatsize / pmp->pm_fatmult) * pmp->pm_fatdiv;
	if (pmp->pm_maxcluster >= clusters) {
#ifdef MSDOSFS_DEBUG
		printf("Warning: number of clusters (%ld) exceeds FAT "
		    "capacity (%ld)\n", pmp->pm_maxcluster + 1, clusters);
#endif
		pmp->pm_maxcluster = clusters - 1;
	}

	if (FAT12(pmp))
		pmp->pm_fatblocksize = 3 * 512;
	else
		pmp->pm_fatblocksize = PAGE_SIZE;
	pmp->pm_fatblocksize = roundup(pmp->pm_fatblocksize,
	    pmp->pm_BytesPerSec);
	pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE;
	pmp->pm_bnshift = ffs(DEV_BSIZE) - 1;

	/*
	 * Compute mask and shift value for isolating cluster relative byte
	 * offsets and cluster numbers from a file offset.
	 */
	pmp->pm_bpcluster = SecPerClust * DEV_BSIZE;
	pmp->pm_crbomask = pmp->pm_bpcluster - 1;
	pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;

	/*
	 * Check for valid cluster size
	 * must be a power of 2
	 */
	if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
		error = EINVAL;
		goto error_exit;
	}

	/*
	 * Release the bootsector buffer.
	 */
	brelse(bp);
	bp = NULL;

	/*
	 * Check the fsinfo sector if we have one.  Silently fix up our
	 * in-core copy of fp->fsinxtfree if it is unknown (0xffffffff)
	 * or too large.  Ignore fp->fsinfree for now, since we need to
	 * read the entire FAT anyway to fill the inuse map.
	 */
	if (pmp->pm_fsinfo) {
		struct fsinfo *fp;

		if ((error = bread(devvp, pmp->pm_fsinfo, pmp->pm_BytesPerSec,
		    NOCRED, &bp)) != 0)
			goto error_exit;
		fp = (struct fsinfo *)bp->b_data;
		if (!bcmp(fp->fsisig1, "RRaA", 4)
		    && !bcmp(fp->fsisig2, "rrAa", 4)
		    && !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
			pmp->pm_nxtfree = getulong(fp->fsinxtfree);
			if (pmp->pm_nxtfree > pmp->pm_maxcluster)
				pmp->pm_nxtfree = CLUST_FIRST;
		} else
			pmp->pm_fsinfo = 0;
		brelse(bp);
		bp = NULL;
	}

	/*
	 * Finish initializing pmp->pm_nxtfree (just in case the first few
	 * sectors aren't properly reserved in the FAT).  This completes
	 * the fixup for fp->fsinxtfree, and fixes up the zero-initialized
	 * value if there is no fsinfo.  We will use pmp->pm_nxtfree
	 * internally even if there is no fsinfo.
	 */
	if (pmp->pm_nxtfree < CLUST_FIRST)
		pmp->pm_nxtfree = CLUST_FIRST;

	/*
	 * Allocate memory for the bitmap of allocated clusters, and then
	 * fill it in.
	 */
	pmp->pm_inusemap = malloc(howmany(pmp->pm_maxcluster + 1, N_INUSEBITS)
				  * sizeof(*pmp->pm_inusemap),
				  M_MSDOSFSFAT, M_WAITOK);

	/*
	 * fillinusemap() needs pm_devvp.
	 */
	pmp->pm_devvp = devvp;
	pmp->pm_dev = dev;

	/*
	 * Have the inuse map filled in.
	 */
	MSDOSFS_LOCK_MP(pmp);
	error = fillinusemap(pmp);
	MSDOSFS_UNLOCK_MP(pmp);
	if (error != 0)
		goto error_exit;

	/*
	 * If they want fat updates to be synchronous then let them suffer
	 * the performance degradation in exchange for the on disk copy of
	 * the fat being correct just about all the time.  I suppose this
	 * would be a good thing to turn on if the kernel is still flakey.
	 */
	if (mp->mnt_flag & MNT_SYNCHRONOUS)
		pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;

	/*
	 * Finish up.
	 */
	if (ronly)
		pmp->pm_flags |= MSDOSFSMNT_RONLY;
	else {
		if ((error = markvoldirty(pmp, 1)) != 0) {
			(void)markvoldirty(pmp, 0);
			goto error_exit;
		}
		pmp->pm_fmod = 1;
	}
	mp->mnt_data =  pmp;
	mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
	mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
	MNT_ILOCK(mp);
	mp->mnt_flag |= MNT_LOCAL;
	mp->mnt_kern_flag |= MNTK_USES_BCACHE;
	MNT_IUNLOCK(mp);

	if (pmp->pm_flags & MSDOSFS_LARGEFS)
		msdosfs_fileno_init(mp);

	return 0;

error_exit:
	if (bp)
		brelse(bp);
	if (cp != NULL) {
		DROP_GIANT();
		g_topology_lock();
		g_vfs_close(cp);
		g_topology_unlock();
		PICKUP_GIANT();
	}
	if (pmp) {
		lockdestroy(&pmp->pm_fatlock);
		if (pmp->pm_inusemap)
			free(pmp->pm_inusemap, M_MSDOSFSFAT);
		free(pmp, M_MSDOSFSMNT);
		mp->mnt_data = NULL;
	}
	dev_rel(dev);
	return (error);
}
Exemple #17
0
int
main(int argc, char **argv)
{
    int debug_flag = 0, log_level = SYSLOG_LEVEL_INFO;
    int opt, fopt_count = 0, j;
    char *tname, *cp, line[NI_MAXHOST];
    FILE *fp;
    u_long linenum;

    extern int optind;
    extern char *optarg;

    __progname = ssh_get_progname(argv[0]);
    seed_rng();
    TAILQ_INIT(&tq);

    /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
    sanitise_stdfd();

    if (argc <= 1)
        usage();

    while ((opt = getopt(argc, argv, "Hv46p:T:t:f:")) != -1) {
        switch (opt) {
        case 'H':
            hash_hosts = 1;
            break;
        case 'p':
            ssh_port = a2port(optarg);
            if (ssh_port <= 0) {
                fprintf(stderr, "Bad port '%s'\n", optarg);
                exit(1);
            }
            break;
        case 'T':
            timeout = convtime(optarg);
            if (timeout == -1 || timeout == 0) {
                fprintf(stderr, "Bad timeout '%s'\n", optarg);
                usage();
            }
            break;
        case 'v':
            if (!debug_flag) {
                debug_flag = 1;
                log_level = SYSLOG_LEVEL_DEBUG1;
            }
            else if (log_level < SYSLOG_LEVEL_DEBUG3)
                log_level++;
            else
                fatal("Too high debugging level.");
            break;
        case 'f':
            if (strcmp(optarg, "-") == 0)
                optarg = NULL;
            argv[fopt_count++] = optarg;
            break;
        case 't':
            get_keytypes = 0;
            tname = strtok(optarg, ",");
            while (tname) {
                int type = key_type_from_name(tname);
                switch (type) {
                case KEY_RSA1:
                    get_keytypes |= KT_RSA1;
                    break;
                case KEY_DSA:
                    get_keytypes |= KT_DSA;
                    break;
                case KEY_ECDSA:
                    get_keytypes |= KT_ECDSA;
                    break;
                case KEY_RSA:
                    get_keytypes |= KT_RSA;
                    break;
                case KEY_ED25519:
                    get_keytypes |= KT_ED25519;
                    break;
                case KEY_UNSPEC:
                    fatal("unknown key type %s", tname);
                }
                tname = strtok(NULL, ",");
            }
            break;
        case '4':
            IPv4or6 = AF_INET;
            break;
        case '6':
            IPv4or6 = AF_INET6;
            break;
        case '?':
        default:
            usage();
        }
    }
    if (optind == argc && !fopt_count)
        usage();

    log_init("ssh-keyscan", log_level, SYSLOG_FACILITY_USER, 1);

    maxfd = fdlim_get(1);
    if (maxfd < 0)
        fatal("%s: fdlim_get: bad value", __progname);
    if (maxfd > MAXMAXFD)
        maxfd = MAXMAXFD;
    if (MAXCON <= 0)
        fatal("%s: not enough file descriptors", __progname);
    if (maxfd > fdlim_get(0))
        fdlim_set(maxfd);
    fdcon = xcalloc(maxfd, sizeof(con));

    read_wait_nfdset = howmany(maxfd, NFDBITS);
    read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));

    for (j = 0; j < fopt_count; j++) {
        if (argv[j] == NULL)
            fp = stdin;
        else if ((fp = fopen(argv[j], "r")) == NULL)
            fatal("%s: %s: %s", __progname, argv[j],
                  strerror(errno));
        linenum = 0;

        while (read_keyfile_line(fp,
                                 argv[j] == NULL ? "(stdin)" : argv[j], line, sizeof(line),
                                 &linenum) != -1) {
            /* Chomp off trailing whitespace and comments */
            if ((cp = strchr(line, '#')) == NULL)
                cp = line + strlen(line) - 1;
            while (cp >= line) {
                if (*cp == ' ' || *cp == '\t' ||
                        *cp == '\n' || *cp == '#')
                    *cp-- = '\0';
                else
                    break;
            }

            /* Skip empty lines */
            if (*line == '\0')
                continue;

            do_host(line);
        }

        if (ferror(fp))
            fatal("%s: %s: %s", __progname, argv[j],
                  strerror(errno));

        fclose(fp);
    }

    while (optind < argc)
        do_host(argv[optind++]);

    while (ncon > 0)
        conloop();

    return (0);
}
Exemple #18
0
int
main(int argc, char *argv[])
{
    ino_t ino;
    int dirty;
    union dinode *dp;
    struct fstab *dt;
    struct statvfs *mntinfo, fsbuf;
    char *map, *cp;
    int ch;
    int i, anydirskipped, bflag = 0, Tflag = 0, Fflag = 0, honorlevel = 1;
    int snap_internal = 0;
    ino_t maxino;
    time_t tnow, date;
    int dirc;
    char *mountpoint;
    int just_estimate = 0;
    char labelstr[LBLSIZE];
    char buf[MAXPATHLEN], rbuf[MAXPATHLEN];
    char *new_time_format;
    char *snap_backup = NULL;

    spcl.c_date = 0;
    (void)time(&tnow);
    spcl.c_date = tnow;
    tzset(); /* set up timezone for strftime */
    if ((new_time_format = getenv("TIMEFORMAT")) != NULL)
        time_string = new_time_format;

    tsize = 0;	/* Default later, based on 'c' option for cart tapes */
    if ((tape = getenv("TAPE")) == NULL)
        tape = _PATH_DEFTAPE;
    dumpdates = _PATH_DUMPDATES;
    temp = _PATH_DTMP;
    strcpy(labelstr, "none");	/* XXX safe strcpy. */
    if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0)
        quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
    level = '0';
    timestamp = 0;

    if (argc < 2)
        usage();

    obsolete(&argc, &argv);
    while ((ch = getopt(argc, argv,
                        "0123456789aB:b:cd:eFf:h:ik:l:L:nr:s:StT:uWwx:X")) != -1)
        switch (ch) {
        /* dump level */
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            level = ch;
            break;

        case 'a':		/* `auto-size', Write to EOM. */
            unlimited = 1;
            break;

        case 'B':		/* blocks per output file */
            blocksperfile = numarg("blocks per file", 1L, 0L);
            break;

        case 'b':		/* blocks per tape write */
            ntrec = numarg("blocks per write", 1L, 1000L);
            bflag = 1;
            break;

        case 'c':		/* Tape is cart. not 9-track */
            cartridge = 1;
            break;

        case 'd':		/* density, in bits per inch */
            density = numarg("density", 10L, 327670L) / 10;
            if (density >= 625 && !bflag)
                ntrec = HIGHDENSITYTREC;
            break;

        case 'e':		/* eject full tapes */
            eflag = 1;
            break;

        case 'F':		/* files-to-dump is an fs image */
            Fflag = 1;
            break;

        case 'f':		/* output file */
            tape = optarg;
            break;

        case 'h':
            honorlevel = numarg("honor level", 0L, 10L);
            break;

        case 'i':	/* "true incremental" regardless level */
            level = 'i';
            trueinc = 1;
            break;

        case 'k':
            readblksize = numarg("read block size", 0, 64) * 1024;
            break;

        case 'l':		/* autoload after eject full tapes */
            eflag = 1;
            lflag = numarg("timeout (in seconds)", 1, 0);
            break;

        case 'L':
            /*
             * Note that although there are LBLSIZE characters,
             * the last must be '\0', so the limit on strlen()
             * is really LBLSIZE-1.
             */
            if (strlcpy(labelstr, optarg, sizeof(labelstr))
                    >= sizeof(labelstr)) {
                msg(
                    "WARNING Label `%s' is larger than limit of %lu characters.\n",
                    optarg,
                    (unsigned long)sizeof(labelstr) - 1);
                msg("WARNING: Using truncated label `%s'.\n",
                    labelstr);
            }
            break;
        case 'n':		/* notify operators */
            notify = 1;
            break;

        case 'r':		/* read cache size */
            readcache = numarg("read cache size", 0, 512);
            break;

        case 's':		/* tape size, feet */
            tsize = numarg("tape size", 1L, 0L) * 12 * 10;
            break;

        case 'S':		/* exit after estimating # of tapes */
            just_estimate = 1;
            break;

        case 't':
            timestamp = 1;
            break;

        case 'T':		/* time of last dump */
            spcl.c_ddate = unctime(optarg);
            if (spcl.c_ddate < 0) {
                (void)fprintf(stderr, "bad time \"%s\"\n",
                              optarg);
                exit(X_STARTUP);
            }
            Tflag = 1;
            lastlevel = '?';
            break;

        case 'u':		/* update /etc/dumpdates */
            uflag = 1;
            break;

        case 'W':		/* what to do */
        case 'w':
            lastdump(ch);
            exit(X_FINOK);	/* do nothing else */

        case 'x':
            snap_backup = optarg;
            break;

        case 'X':
            snap_internal = 1;
            break;

        default:
            usage();
        }
    argc -= optind;
    argv += optind;

    if (argc < 1) {
        (void)fprintf(stderr,
                      "Must specify disk or image, or file list\n");
        exit(X_STARTUP);
    }


    /*
     *	determine if disk is a subdirectory, and setup appropriately
     */
    getfstab();		/* /etc/fstab snarfed */
    disk = NULL;
    disk_dev = NULL;
    mountpoint = NULL;
    dirc = 0;
    for (i = 0; i < argc; i++) {
        struct stat sb;
        int error;

        error = lstat(argv[i], &sb);
        if (Fflag || (!error && (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)))) {
            if (error)
                quit("Cannot stat %s: %s\n", argv[i], strerror(errno));
            disk = argv[i];
multicheck:
            if (dirc != 0)
                quit("Can't dump a disk or image at the same time as a file list\n");
            break;
        }
        if ((dt = fstabsearch(argv[i])) != NULL) {
            disk = argv[i];
            mountpoint = xstrdup(dt->fs_file);
            goto multicheck;
        }
        if (statvfs(argv[i], &fsbuf) == -1)
            quit("Cannot statvfs %s: %s\n", argv[i],
                 strerror(errno));
        disk = fsbuf.f_mntfromname;
        if (strcmp(argv[i], fsbuf.f_mntonname) == 0)
            goto multicheck;
        if (mountpoint == NULL) {
            mountpoint = xstrdup(fsbuf.f_mntonname);
            if (uflag) {
                msg("Ignoring u flag for subdir dump\n");
                uflag = 0;
            }
            if (level > '0') {
                msg("Subdir dump is done at level 0\n");
                level = '0';
            }
            msg("Dumping sub files/directories from %s\n",
                mountpoint);
        } else {
            if (strcmp(mountpoint, fsbuf.f_mntonname) != 0)
                quit("%s is not on %s\n", argv[i], mountpoint);
        }
        msg("Dumping file/directory %s\n", argv[i]);
        dirc++;
    }
    if (mountpoint)
        free(mountpoint);

    if (dirc == 0) {
        argv++;
        if (argc != 1) {
            (void)fprintf(stderr, "Excess arguments to dump:");
            while (--argc)
                (void)fprintf(stderr, " %s", *argv++);
            (void)fprintf(stderr, "\n");
            exit(X_STARTUP);
        }
    }
    if (Tflag && uflag) {
        (void)fprintf(stderr,
                      "You cannot use the T and u flags together.\n");
        exit(X_STARTUP);
    }
    if (strcmp(tape, "-") == 0) {
        pipeout++;
        tape = "standard output";
    }

    if (blocksperfile)
        blocksperfile = blocksperfile / ntrec * ntrec; /* round down */
    else if (!unlimited) {
        /*
         * Determine how to default tape size and density
         *
         *		density				tape size
         * 9-track	1600 bpi (160 bytes/.1")	2300 ft.
         * 9-track	6250 bpi (625 bytes/.1")	2300 ft.
         * cartridge	8000 bpi (100 bytes/.1")	1700 ft.
         *						(450*4 - slop)
         */
        if (density == 0)
            density = cartridge ? 100 : 160;
        if (tsize == 0)
            tsize = cartridge ? 1700L*120L : 2300L*120L;
    }

    if ((cp = strchr(tape, ':')) != NULL) {
        host = tape;
        /* This is fine, because all the const strings don't have : */
        *cp++ = '\0';
        tape = cp;
#ifdef RDUMP
        if (rmthost(host) == 0)
            exit(X_STARTUP);
#else
        (void)fprintf(stderr, "remote dump not enabled\n");
        exit(X_STARTUP);
#endif
    }

    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
        signal(SIGHUP, sig);
    if (signal(SIGTRAP, SIG_IGN) != SIG_IGN)
        signal(SIGTRAP, sig);
    if (signal(SIGFPE, SIG_IGN) != SIG_IGN)
        signal(SIGFPE, sig);
    if (signal(SIGBUS, SIG_IGN) != SIG_IGN)
        signal(SIGBUS, sig);
#if 0
    if (signal(SIGSEGV, SIG_IGN) != SIG_IGN)
        signal(SIGSEGV, sig);
#endif
    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
        signal(SIGTERM, sig);
    if (signal(SIGINT, interrupt) == SIG_IGN)
        signal(SIGINT, SIG_IGN);

    /*
     *	disk can be either the full special file name, or
     *	the file system name.
     */
    mountpoint = NULL;
    mntinfo = mntinfosearch(disk);
    if ((dt = fstabsearch(disk)) != NULL) {
        if (getfsspecname(buf, sizeof(buf), dt->fs_spec) == NULL)
            quit("%s (%s)", buf, strerror(errno));
        if (getdiskrawname(rbuf, sizeof(rbuf), buf) == NULL)
            quit("Can't get disk raw name for `%s' (%s)",
                 buf, strerror(errno));
        disk = rbuf;
        mountpoint = dt->fs_file;
        msg("Found %s on %s in %s\n", disk, mountpoint, _PATH_FSTAB);
    } else if (mntinfo != NULL) {
        if (getdiskrawname(rbuf, sizeof(rbuf), mntinfo->f_mntfromname)
                == NULL)
            quit("Can't get disk raw name for `%s' (%s)",
                 mntinfo->f_mntfromname, strerror(errno));
        disk = rbuf;
        mountpoint = mntinfo->f_mntonname;
        msg("Found %s on %s in mount table\n", disk, mountpoint);
    }
    if (mountpoint != NULL) {
        if (dirc != 0)
            (void)snprintf(spcl.c_filesys, sizeof(spcl.c_filesys),
                           "a subset of %s", mountpoint);
        else
            (void)strlcpy(spcl.c_filesys, mountpoint,
                          sizeof(spcl.c_filesys));
    } else if (Fflag) {
        (void)strlcpy(spcl.c_filesys, "a file system image",
                      sizeof(spcl.c_filesys));
    } else {
        (void)strlcpy(spcl.c_filesys, "an unlisted file system",
                      sizeof(spcl.c_filesys));
    }
    (void)strlcpy(spcl.c_dev, disk, sizeof(spcl.c_dev));
    (void)strlcpy(spcl.c_label, labelstr, sizeof(spcl.c_label));
    (void)gethostname(spcl.c_host, sizeof(spcl.c_host));
    spcl.c_host[sizeof(spcl.c_host) - 1] = '\0';

    if ((snap_backup != NULL || snap_internal) && mntinfo == NULL) {
        msg("WARNING: Cannot use -x or -X on unmounted file system.\n");
        snap_backup = NULL;
        snap_internal = 0;
    }

#ifdef DUMP_LFS
    sync();
    if (snap_backup != NULL || snap_internal) {
        if (lfs_wrap_stop(mountpoint) < 0) {
            msg("Cannot stop writing on %s\n", mountpoint);
            exit(X_STARTUP);
        }
    }
    if ((diskfd = open(disk, O_RDONLY)) < 0) {
        msg("Cannot open %s\n", disk);
        exit(X_STARTUP);
    }
    disk_dev = disk;
#else /* ! DUMP_LFS */
    if (snap_backup != NULL || snap_internal) {
        diskfd = snap_open(mntinfo->f_mntonname, snap_backup,
                           &tnow, &disk_dev);
        if (diskfd < 0) {
            msg("Cannot open snapshot of %s\n",
                mntinfo->f_mntonname);
            exit(X_STARTUP);
        }
        spcl.c_date = tnow;
    } else {
        if ((diskfd = open(disk, O_RDONLY)) < 0) {
            msg("Cannot open %s\n", disk);
            exit(X_STARTUP);
        }
        disk_dev = disk;
    }
    sync();
#endif /* ! DUMP_LFS */

    needswap = fs_read_sblock(sblock_buf);

    /* true incremental is always a level 10 dump */
    spcl.c_level = trueinc? iswap32(10): iswap32(level - '0');
    spcl.c_type = iswap32(TS_TAPE);
    spcl.c_date = iswap32(spcl.c_date);
    spcl.c_ddate = iswap32(spcl.c_ddate);
    if (!Tflag)
        getdumptime();		/* /etc/dumpdates snarfed */

    date = iswap32(spcl.c_date);
    msg("Date of this level %c dump: %s", level,
        spcl.c_date == 0 ? "the epoch\n" : ctime(&date));
    date = iswap32(spcl.c_ddate);
    msg("Date of last level %c dump: %s", lastlevel,
        spcl.c_ddate == 0 ? "the epoch\n" : ctime(&date));
    msg("Dumping ");
    if (snap_backup != NULL || snap_internal)
        msgtail("a snapshot of ");
    if (dirc != 0)
        msgtail("a subset of ");
    msgtail("%s (%s) ", disk, spcl.c_filesys);
    if (host)
        msgtail("to %s on host %s\n", tape, host);
    else
        msgtail("to %s\n", tape);
    msg("Label: %s\n", labelstr);

    ufsib = fs_parametrize();

    dev_bshift = ffs(dev_bsize) - 1;
    if (dev_bsize != (1 << dev_bshift))
        quit("dev_bsize (%ld) is not a power of 2", dev_bsize);
    tp_bshift = ffs(TP_BSIZE) - 1;
    if (TP_BSIZE != (1 << tp_bshift))
        quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
    maxino = fs_maxino();
    mapsize = roundup(howmany(maxino, NBBY), TP_BSIZE);
    usedinomap = (char *)xcalloc((unsigned) mapsize, sizeof(char));
    dumpdirmap = (char *)xcalloc((unsigned) mapsize, sizeof(char));
    dumpinomap = (char *)xcalloc((unsigned) mapsize, sizeof(char));
    tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);

    nonodump = iswap32(spcl.c_level) < honorlevel;

    initcache(readcache, readblksize);

    (void)signal(SIGINFO, statussig);

    msg("mapping (Pass I) [regular files]\n");
    anydirskipped = mapfiles(maxino, &tapesize, mountpoint,
                             (dirc ? argv : NULL));

    msg("mapping (Pass II) [directories]\n");
    while (anydirskipped) {
        anydirskipped = mapdirs(maxino, &tapesize);
    }

    if (pipeout || unlimited) {
        tapesize += 10;	/* 10 trailer blocks */
        msg("estimated %llu tape blocks.\n",
            (unsigned long long)tapesize);
    } else {
        double fetapes;

        if (blocksperfile)
            fetapes = (double) tapesize / blocksperfile;
        else if (cartridge) {
            /* Estimate number of tapes, assuming streaming stops at
               the end of each block written, and not in mid-block.
               Assume no erroneous blocks; this can be compensated
               for with an artificially low tape size. */
            fetapes =
                (	  (double) tapesize	/* blocks */
                      * TP_BSIZE	/* bytes/block */
                      * (1.0/density)	/* 0.1" / byte */
                      +
                      (double) tapesize	/* blocks */
                      * (1.0/ntrec)	/* streaming-stops per block */
                      * 15.48		/* 0.1" / streaming-stop */
                ) * (1.0 / tsize );	/* tape / 0.1" */
        } else {
            /* Estimate number of tapes, for old fashioned 9-track
               tape */
            int tenthsperirg = (density == 625) ? 3 : 7;
            fetapes =
                (	  tapesize	/* blocks */
                      * TP_BSIZE	/* bytes / block */
                      * (1.0/density)	/* 0.1" / byte */
                      +
                      tapesize	/* blocks */
                      * (1.0/ntrec)	/* IRG's / block */
                      * tenthsperirg	/* 0.1" / IRG */
                ) * (1.0 / tsize );	/* tape / 0.1" */
        }
        etapes = fetapes;		/* truncating assignment */
        etapes++;
        /* count the dumped inodes map on each additional tape */
        tapesize += (etapes - 1) *
                    (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
        tapesize += etapes + 10;	/* headers + 10 trailer blks */
        msg("estimated %llu tape blocks on %3.2f tape(s).\n",
            (unsigned long long)tapesize, fetapes);
    }
    /*
     * If the user only wants an estimate of the number of
     * tapes, exit now.
     */
    if (just_estimate)
        exit(X_FINOK);

    /*
     * Allocate tape buffer.
     */
    if (!alloctape())
        quit("can't allocate tape buffers - try a smaller blocking factor.\n");

    startnewtape(1);
    (void)time((time_t *)&(tstart_writing));
    xferrate = 0;
    dumpmap(usedinomap, TS_CLRI, maxino - 1);

    msg("dumping (Pass III) [directories]\n");
    dirty = 0;		/* XXX just to get gcc to shut up */
    for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
        if (((ino - 1) % NBBY) == 0)	/* map is offset by 1 */
            dirty = *map++;
        else
            dirty >>= 1;
        if ((dirty & 1) == 0)
            continue;
        /*
         * Skip directory inodes deleted and maybe reallocated
         */
        dp = getino(ino);
        if ((DIP(dp, mode) & IFMT) != IFDIR)
            continue;
        (void)dumpino(dp, ino);
    }

    msg("dumping (Pass IV) [regular files]\n");
    for (map = dumpinomap, ino = 1; ino < maxino; ino++) {
        int mode;

        if (((ino - 1) % NBBY) == 0)	/* map is offset by 1 */
            dirty = *map++;
        else
            dirty >>= 1;
        if ((dirty & 1) == 0)
            continue;
        /*
         * Skip inodes deleted and reallocated as directories.
         */
        dp = getino(ino);
        mode = DIP(dp, mode) & IFMT;
        if (mode == IFDIR)
            continue;
        (void)dumpino(dp, ino);
    }

    spcl.c_type = iswap32(TS_END);
    for (i = 0; i < ntrec; i++)
        writeheader(maxino - 1);
    if (pipeout)
        msg("%lld tape blocks\n",(long long)iswap64(spcl.c_tapea));
    else
        msg("%lld tape blocks on %d volume%s\n",
            (long long)iswap64(spcl.c_tapea), iswap32(spcl.c_volume),
            (iswap32(spcl.c_volume) == 1) ? "" : "s");
    tnow = do_stats();
    date = iswap32(spcl.c_date);
    msg("Date of this level %c dump: %s", level,
        spcl.c_date == 0 ? "the epoch\n" : ctime(&date));
    msg("Date this dump completed:  %s", ctime(&tnow));
    msg("Average transfer rate: %d KB/s\n", xferrate / tapeno);
    putdumptime();
    trewind(0);
    broadcast("DUMP IS DONE!\a\a\n");
#ifdef DUMP_LFS
    lfs_wrap_go();
#endif /* DUMP_LFS */
    msg("DUMP IS DONE\n");
    Exit(X_FINOK);
    /* NOTREACHED */
    exit(X_FINOK);		/* XXX: to satisfy gcc */
}
Exemple #19
0
int
WaitForSomething(int *pClientsReady)
{
    struct timeval *wt,
               waittime;
    fd_set      clientsReadable;
    fd_set      clientsWriteable;
    long        curclient;
    int         selecterr;
    long        current_time = 0;
    long        timeout;
    int         nready,
                i;

    while (1) {
        /* handle the work Q */
        if (workQueue)
            ProcessWorkQueue();

        if (XFD_ANYSET(&ClientsWithInput)) {
            XFD_COPYSET(&ClientsWithInput, &clientsReadable);
            break;
        }
        /*
         * deal with KeepAlive timeouts.  if this seems to costly, SIGALRM
         * could be used, but its more dangerous since some it could catch us
         * at an inopportune moment (like inside un-reentrant malloc()).
         */
        current_time = GetTimeInMillis();
        timeout = current_time - LastReapTime;
        if (timeout > ReapClientTime) {
            ReapAnyOldClients();
            LastReapTime = current_time;
            timeout = ReapClientTime;
        }
        timeout = ReapClientTime - timeout;
        waittime.tv_sec = timeout / MILLI_PER_SECOND;
        waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
                           (1000000 / MILLI_PER_SECOND);
        wt = &waittime;

        XFD_COPYSET(&AllSockets, &LastSelectMask);

        BlockHandler(&wt, (pointer) &LastSelectMask);
        if (NewOutputPending)
            FlushAllOutput();

        if (AnyClientsWriteBlocked) {
            XFD_COPYSET(&ClientsWriteBlocked, &clientsWriteable);
            i = Select(MAXSOCKS, &LastSelectMask, &clientsWriteable, NULL, wt);
        } else {
            i = Select(MAXSOCKS, &LastSelectMask, NULL, NULL, wt);
        }
        selecterr = errno;

        WakeupHandler(i, (unsigned long *) &LastSelectMask);
        if (i <= 0) {		/* error or timeout */
            FD_ZERO(&clientsWriteable);
            if (i < 0) {
                if (selecterr == EBADF) {	/* somebody disconnected */
                    CheckConnections();
                } else if (selecterr != EINTR) {
                    ErrorF("WaitForSomething: select(): errno %d\n", selecterr);
                } else {
                    /*
                     * must have been broken by a signal.  go deal with any
                     * exception flags
                     */
                    return 0;
                }
            } else {		/* must have timed out */
                ReapAnyOldClients();
                LastReapTime = GetTimeInMillis();
            }
        } else {
            if (AnyClientsWriteBlocked && XFD_ANYSET(&clientsWriteable)) {
                NewOutputPending = TRUE;
                XFD_ORSET(&OutputPending, &clientsWriteable, &OutputPending);
                XFD_UNSET(&ClientsWriteBlocked, &clientsWriteable);
                if (!XFD_ANYSET(&ClientsWriteBlocked))
                    AnyClientsWriteBlocked = FALSE;
            }
            XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
            if (LastSelectMask.fds_bits[0] & WellKnownConnections.fds_bits[0])
                MakeNewConnections();
            if (XFD_ANYSET(&clientsReadable))
                break;

        }
    }
    nready = 0;

    if (XFD_ANYSET(&clientsReadable)) {
        ClientPtr   client;
        int         conn;

        if (current_time)	/* may not have been set */
            current_time = GetTimeInMillis();
        for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
            while (clientsReadable.fds_bits[i]) {
                curclient = xfd_ffs(clientsReadable.fds_bits[i]) - 1;
                conn = ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))];
                clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient);
                client = clients[conn];
                if (!client)
                    continue;
                pClientsReady[nready++] = conn;
                client->last_request_time = current_time;
                client->clientGone = CLIENT_ALIVE;

                if (nready >= MaxClients) {
                    /* pClientsReady buffer has no more room, get the
                       rest on the next time through select() loop */
                    return nready;
                }
            }
        }
    }
    return nready;
}
Exemple #20
0
/*
 * Wrapper for select(s, timeout). We are using select() on Mac OS due to Bug 7131399.
 * Auto restarts with adjusted timeout if interrupted by
 * signal other than our wakeup signal.
 */
int NET_Timeout(int s, long timeout) {
    long prevtime = 0, newtime;
    struct timeval t, *tp = &t;
    fd_set fds;
    fd_set* fdsp = NULL;
    int allocated = 0;
    threadEntry_t self;
    fdEntry_t *fdEntry = getFdEntry(s);

    /*
     * Check that fd hasn't been closed.
     */
    if (fdEntry == NULL) {
        errno = EBADF;
        return -1;
    }

    /*
     * Pick up current time as may need to adjust timeout
     */
    if (timeout > 0) {
        /* Timed */
        struct timeval now;
        gettimeofday(&now, NULL);
        prevtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
        t.tv_sec = timeout / 1000;
        t.tv_usec = (timeout % 1000) * 1000;
    } else if (timeout < 0) {
        /* Blocking */
        tp = 0;
    } else {
        /* Poll */
        t.tv_sec = 0;
        t.tv_usec = 0;
    }

    if (s < FD_SETSIZE) {
        fdsp = &fds;
        FD_ZERO(fdsp);
    } else {
        int length = (howmany(s+1, NFDBITS)) * sizeof(int);
        fdsp = (fd_set *) calloc(1, length);
        if (fdsp == NULL) {
            return -1;   // errno will be set to ENOMEM
        }
        allocated = 1;
    }
    FD_SET(s, fdsp);

    for(;;) {
        int rv;

        /*
         * call select on the fd. If interrupted by our wakeup signal
         * errno will be set to EBADF.
         */

        startOp(fdEntry, &self);
        rv = select(s+1, fdsp, 0, 0, tp);
        endOp(fdEntry, &self);

        /*
         * If interrupted then adjust timeout. If timeout
         * has expired return 0 (indicating timeout expired).
         */
        if (rv < 0 && errno == EINTR) {
            if (timeout > 0) {
                struct timeval now;
                gettimeofday(&now, NULL);
                newtime = now.tv_sec * 1000  +  now.tv_usec / 1000;
                timeout -= newtime - prevtime;
                if (timeout <= 0) {
                    if (allocated != 0)
                        free(fdsp);
                    return 0;
                }
                prevtime = newtime;
                t.tv_sec = timeout / 1000;
                t.tv_usec = (timeout % 1000) * 1000;
            }
        } else {
            if (allocated != 0)
                free(fdsp);
            return rv;
        }

    }
}
Exemple #21
0
void
printlong(const DISPLAY *dp)
{
	struct stat *sp;
	FTSENT *p;
	NAMES *np;
	char buf[20];
#ifdef COLORLS
	int color_printed = 0;
#endif

	if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
	    (f_longform || f_size)) {
		xo_emit("{L:total} {:total-blocks/%lu}\n",
			howmany(dp->btotal, blocksize));
	}

	xo_open_list("entry");
	for (p = dp->list; p; p = p->fts_link) {
		char *name;
		if (IS_NOPRINT(p))
			continue;
		xo_open_instance("entry");
		sp = p->fts_statp;
		name = getname(p->fts_name);
		if (name)
		    xo_emit("{ke:name}", name);
		if (f_inode)
			xo_emit("{:inode/%*ju} ",
			    dp->s_inode, (uintmax_t)sp->st_ino);
		if (f_size)
			xo_emit("{:blocks/%*jd} ",
			    dp->s_block, howmany(sp->st_blocks, blocksize));
		strmode(sp->st_mode, buf);
		aclmode(buf, p);
		np = p->fts_pointer;
		xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS);
		xo_emit("{t:mode/%s} {:links/%*u} {:user/%-*s}  {:group/%-*s}  ",
			buf, dp->s_nlink, sp->st_nlink,
			dp->s_user, np->user, dp->s_group, np->group);
		if (f_flags)
			xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags);
		if (f_label)
			xo_emit("{:label/%-*s} ", dp->s_label, np->label);
		if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
			printdev(dp->s_size, sp->st_rdev);
		else
			printsize("size", dp->s_size, sp->st_size);
		if (f_accesstime)
			printtime("access-time", sp->st_atime);
		else if (f_birthtime)
			printtime("birth-time", sp->st_birthtime);
		else if (f_statustime)
			printtime("change-time", sp->st_ctime);
		else
			printtime("modify-time", sp->st_mtime);
#ifdef COLORLS
		if (f_color)
			color_printed = colortype(sp->st_mode);
#endif

		if (name) {
		    xo_emit("{dk:name}", name);
		    free(name);
		}
		
#ifdef COLORLS
		if (f_color && color_printed)
			endcolor(0);
#endif
		if (f_type)
			(void)printtype(sp->st_mode);
		if (S_ISLNK(sp->st_mode))
			printlink(p);
		xo_close_instance("entry");
		xo_emit("\n");
	}
	xo_close_list("entry");
}
Exemple #22
0
int
adosfs_getattr(void *v)
{
	struct vop_getattr_args /* {
		struct vnode *a_vp;
		struct vattr *a_vap;
		kauth_cred_t a_cred;
	} */ *sp = v;
	struct vattr *vap;
	struct adosfsmount *amp;
	struct anode *ap;
	u_long fblks;

#ifdef ADOSFS_DIAGNOSTIC
	advopprint(sp);
#endif
	vap = sp->a_vap;
	ap = VTOA(sp->a_vp);
	amp = ap->amp;
	vattr_null(vap);
	vap->va_uid = ap->uid;
	vap->va_gid = ap->gid;
	vap->va_fsid = sp->a_vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0];
	vap->va_atime.tv_sec = vap->va_mtime.tv_sec = vap->va_ctime.tv_sec =
		ap->mtime.days * 24 * 60 * 60 + ap->mtime.mins * 60 +
		ap->mtime.ticks / 50 + (8 * 365 + 2) * 24 * 60 * 60;
	vap->va_atime.tv_nsec = vap->va_mtime.tv_nsec = vap->va_ctime.tv_nsec = 0;
	vap->va_gen = 0;
	vap->va_flags = 0;
	vap->va_rdev = NODEV;
	vap->va_fileid = ap->block;
	vap->va_type = sp->a_vp->v_type;
	vap->va_mode = adunixprot(ap->adprot) & amp->mask;
	if (sp->a_vp->v_type == VDIR) {
		vap->va_nlink = 1;	/* XXX bogus, oh well */
		vap->va_bytes = amp->bsize;
		vap->va_size = amp->bsize;
	} else {
		/*
		 * XXX actually we can track this if we were to walk the list
		 * of links if it exists.
		 * XXX for now, just set nlink to 2 if this is a hard link
		 * to a file, or a file with a hard link.
		 */
		vap->va_nlink = 1 + (ap->linkto != 0);
		/*
		 * round up to nearest blocks add number of file list
		 * blocks needed and mutiply by number of bytes per block.
		 */
		fblks = howmany(ap->fsize, amp->dbsize);
		fblks += howmany(fblks, ANODENDATBLKENT(ap));
		vap->va_bytes = fblks * amp->dbsize;
		vap->va_size = ap->fsize;

		vap->va_blocksize = amp->dbsize;
	}
#ifdef ADOSFS_DIAGNOSTIC
	printf(" 0)");
#endif
	return(0);
}
Exemple #23
0
void
printcol(const DISPLAY *dp)
{
	static FTSENT **array;
	static int lastentries = -1;
	FTSENT *p;
	FTSENT **narray;
	int base;
	int chcnt;
	int cnt;
	int col;
	int colwidth;
	int endcol;
	int num;
	int numcols;
	int numrows;
	int row;
	int tabwidth;

	if (f_notabs)
		tabwidth = 1;
	else
		tabwidth = 8;

	/*
	 * Have to do random access in the linked list -- build a table
	 * of pointers.
	 */
	if (dp->entries > lastentries) {
		if ((narray =
		    realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
			warn(NULL);
			printscol(dp);
			return;
		}
		lastentries = dp->entries;
		array = narray;
	}
	for (p = dp->list, num = 0; p; p = p->fts_link)
		if (p->fts_number != NO_PRINT)
			array[num++] = p;

	colwidth = dp->maxlen;
	if (f_inode)
		colwidth += dp->s_inode + 1;
	if (f_size)
		colwidth += dp->s_block + 1;
	if (f_type)
		colwidth += 1;

	colwidth = (colwidth + tabwidth) & ~(tabwidth - 1);
	if (termwidth < 2 * colwidth) {
		printscol(dp);
		return;
	}
	numcols = termwidth / colwidth;
	numrows = num / numcols;
	if (num % numcols)
		++numrows;

	if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
	    (f_longform || f_size)) {
		(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
	}

	base = 0;
	for (row = 0; row < numrows; ++row) {
		endcol = colwidth;
		if (!f_sortacross)
			base = row;
		for (col = 0, chcnt = 0; col < numcols; ++col) {
			chcnt += printaname(array[base], dp->s_inode,
			    dp->s_block);
			if (f_sortacross)
				base++;
			else
				base += numrows;
			if (base >= num)
				break;
			while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1)))
			    <= endcol) {
				if (f_sortacross && col + 1 >= numcols)
					break;
				(void)putchar(f_notabs ? ' ' : '\t');
				chcnt = cnt;
			}
			endcol += colwidth;
		}
		(void)putchar('\n');
	}
}
Exemple #24
0
static int
load_fw(struct tegra_xhci_softc *sc)
{
	const struct firmware *fw;
	const struct tegra_xusb_fw_hdr *fw_hdr;
	vm_paddr_t fw_paddr, fw_base;
	vm_offset_t fw_vaddr;
	vm_size_t fw_size;
	uint32_t code_tags, code_size;
	struct clocktime fw_clock;
	struct timespec	fw_timespec;
	int i;

	/* Reset ARU */
	FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET);
	DELAY(3000);

	/* Check if FALCON already runs */
	if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) {
		device_printf(sc->dev,
		    "XUSB CPU is already loaded, CPUCTL: 0x%08X\n",
			 CSB_RD4(sc, XUSB_FALCON_CPUCTL));
		return (0);
	}

	fw = firmware_get(sc->fw_name);
	if (fw == NULL) {
		device_printf(sc->dev, "Cannot read xusb firmware\n");
		return (ENOENT);
	}

	/* Allocate uncached memory and copy firmware into. */
	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data;
	fw_size = fw_hdr->fwimg_len;

	fw_vaddr = kmem_alloc_contig(kernel_arena, fw_size,
	    M_WAITOK, 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
	fw_paddr = vtophys(fw_vaddr);
	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr;
	memcpy((void *)fw_vaddr, fw->data, fw_size);

	firmware_put(fw, FIRMWARE_UNLOAD);
	sc->fw_vaddr = fw_vaddr;
	sc->fw_size = fw_size;

	/* Setup firmware physical address and size. */
	fw_base = fw_paddr + sizeof(*fw_hdr);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH);

	/* Invalidate full L2IMEM context. */
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
	    L2IMEMOP_INVALIDATE_ALL);

	/* Program load of L2IMEM by boot code. */
	code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE);
	code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE,
	    L2IMEMOP_SIZE_OFFSET(code_tags) |
	    L2IMEMOP_SIZE_SIZE(code_size));

	/* Execute L2IMEM boot code fetch. */
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
	    L2IMEMOP_LOAD_LOCKED_RESULT);

	/* Program FALCON auto-fill range and block count */
	CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size);
	CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1,
	    IMFILLRNG1_TAG_LO(code_tags) |
	    IMFILLRNG1_TAG_HI(code_tags + code_size));

	CSB_WR4(sc, XUSB_FALCON_DMACTL, 0);
	/* Wait for CPU */
	for (i = 500; i > 0; i--) {
		if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) &
		     L2IMEMOP_RESULT_VLD)
			break;
		DELAY(100);
	}
	if (i <= 0) {
		device_printf(sc->dev, "Timedout while wating for DMA, "
		    "state: 0x%08X\n",
		    CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT));
		return (ETIMEDOUT);
	}

	/* Boot FALCON cpu */
	CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag);
	CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU);

	/* Wait for CPU */
	for (i = 50; i > 0; i--) {
		if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED)
			break;
		DELAY(100);
	}
	if (i <= 0) {
		device_printf(sc->dev, "Timedout while wating for FALCON cpu, "
		    "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL));
		return (ETIMEDOUT);
	}

	fw_timespec.tv_sec = fw_hdr->fwimg_created_time;
	fw_timespec.tv_nsec = 0;
	clock_ts_to_ct(&fw_timespec, &fw_clock);
	device_printf(sc->dev,
	    " Falcon firmware version: %02X.%02X.%04X,"
	    " (%d/%d/%d %d:%02d:%02d UTC)\n",
	    (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF,
	    fw_hdr->version_id & 0xFFFF,
	    fw_clock.day, fw_clock.mon, fw_clock.year,
	    fw_clock.hour, fw_clock.min, fw_clock.sec);

	return (0);
}
Exemple #25
0
int
main(int argc, char *argv[])
{
	struct stat sb;
	ino_t ino;
	int dirty;
	union dinode *dp;
	struct fstab *dt;
	char *map, *mntpt;
	int ch, mode, mntflags;
	int i, anydirskipped, bflag = 0, Tflag = 0, honorlevel = 1;
	int just_estimate = 0;
	ino_t maxino;
	char *tmsg;

	spcl.c_date = _time_to_time64(time(NULL));

	tsize = 0;	/* Default later, based on 'c' option for cart tapes */
	dumpdates = _PATH_DUMPDATES;
	popenout = NULL;
	tape = NULL;
	temp = _PATH_DTMP;
	if (TP_BSIZE / DEV_BSIZE == 0 || TP_BSIZE % DEV_BSIZE != 0)
		quit("TP_BSIZE must be a multiple of DEV_BSIZE\n");
	level = 0;
	rsync_friendly = 0;

	if (argc < 2)
		usage();

	obsolete(&argc, &argv);
	while ((ch = getopt(argc, argv,
	    "0123456789aB:b:C:cD:d:f:h:LnP:RrSs:T:uWw")) != -1)
		switch (ch) {
		/* dump level */
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			level = 10 * level + ch - '0';
			break;

		case 'a':		/* `auto-size', Write to EOM. */
			unlimited = 1;
			break;

		case 'B':		/* blocks per output file */
			blocksperfile = numarg("number of blocks per file",
			    1L, 0L);
			break;

		case 'b':		/* blocks per tape write */
			ntrec = numarg("number of blocks per write",
			    1L, 1000L);
			break;

		case 'C':
			cachesize = numarg("cachesize", 0, 0) * 1024 * 1024;
			break;

		case 'c':		/* Tape is cart. not 9-track */
			cartridge = 1;
			break;

		case 'D':
			dumpdates = optarg;
			break;

		case 'd':		/* density, in bits per inch */
			density = numarg("density", 10L, 327670L) / 10;
			if (density >= 625 && !bflag)
				ntrec = HIGHDENSITYTREC;
			break;

		case 'f':		/* output file */
			if (popenout != NULL)
				errx(X_STARTUP, "You cannot use the P and f "
				    "flags together.\n");
			tape = optarg;
			break;

		case 'h':
			honorlevel = numarg("honor level", 0L, 10L);
			break;

		case 'L':
			snapdump = 1;
			break;

		case 'n':		/* notify operators */
			notify = 1;
			break;

		case 'P':
			if (tape != NULL)
				errx(X_STARTUP, "You cannot use the P and f "
				    "flags together.\n");
			popenout = optarg;
			break;

		case 'r': /* store slightly less data to be friendly to rsync */
			if (rsync_friendly < 1)
				rsync_friendly = 1;
			break;

		case 'R': /* store even less data to be friendlier to rsync */
			if (rsync_friendly < 2)
				rsync_friendly = 2;
			break;

		case 'S':               /* exit after estimating # of tapes */
			just_estimate = 1;
			break;

		case 's':		/* tape size, feet */
			tsize = numarg("tape size", 1L, 0L) * 12 * 10;
			break;

		case 'T':		/* time of last dump */
			spcl.c_ddate = unctime(optarg);
			if (spcl.c_ddate < 0) {
				(void)fprintf(stderr, "bad time \"%s\"\n",
				    optarg);
				exit(X_STARTUP);
			}
			Tflag = 1;
			lastlevel = -1;
			break;

		case 'u':		/* update /etc/dumpdates */
			uflag = 1;
			break;

		case 'W':		/* what to do */
		case 'w':
			lastdump(ch);
			exit(X_FINOK);	/* do nothing else */

		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc < 1) {
		(void)fprintf(stderr, "Must specify disk or file system\n");
		exit(X_STARTUP);
	}
	disk = *argv++;
	argc--;
	if (argc >= 1) {
		(void)fprintf(stderr, "Unknown arguments to dump:");
		while (argc--)
			(void)fprintf(stderr, " %s", *argv++);
		(void)fprintf(stderr, "\n");
		exit(X_STARTUP);
	}
	if (rsync_friendly && (level > 0)) {
		(void)fprintf(stderr, "%s %s\n", "rsync friendly options",
		    "can be used only with level 0 dumps.");
		exit(X_STARTUP);
	}
	if (Tflag && uflag) {
	        (void)fprintf(stderr,
		    "You cannot use the T and u flags together.\n");
		exit(X_STARTUP);
	}
	if (popenout) {
		tape = "child pipeline process";
	} else if (tape == NULL && (tape = getenv("TAPE")) == NULL)
		tape = _PATH_DEFTAPE;
	if (strcmp(tape, "-") == 0) {
		pipeout++;
		tape = "standard output";
	}

	if (blocksperfile)
		blocksperfile = blocksperfile / ntrec * ntrec; /* round down */
	else if (!unlimited) {
		/*
		 * Determine how to default tape size and density
		 *
		 *         	density				tape size
		 * 9-track	1600 bpi (160 bytes/.1")	2300 ft.
		 * 9-track	6250 bpi (625 bytes/.1")	2300 ft.
		 * cartridge	8000 bpi (100 bytes/.1")	1700 ft.
		 *						(450*4 - slop)
		 * hilit19 hits again: "
		 */
		if (density == 0)
			density = cartridge ? 100 : 160;
		if (tsize == 0)
			tsize = cartridge ? 1700L*120L : 2300L*120L;
	}

	if (strchr(tape, ':')) {
		host = tape;
		tape = strchr(host, ':');
		*tape++ = '\0';
#ifdef RDUMP
		if (strchr(tape, '\n')) {
		    (void)fprintf(stderr, "invalid characters in tape\n");
		    exit(X_STARTUP);
		}
		if (rmthost(host) == 0)
			exit(X_STARTUP);
#else
		(void)fprintf(stderr, "remote dump not enabled\n");
		exit(X_STARTUP);
#endif
	}
	(void)setuid(getuid()); /* rmthost() is the only reason to be setuid */

	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		signal(SIGHUP, sig);
	if (signal(SIGTRAP, SIG_IGN) != SIG_IGN)
		signal(SIGTRAP, sig);
	if (signal(SIGFPE, SIG_IGN) != SIG_IGN)
		signal(SIGFPE, sig);
	if (signal(SIGBUS, SIG_IGN) != SIG_IGN)
		signal(SIGBUS, sig);
	if (signal(SIGSEGV, SIG_IGN) != SIG_IGN)
		signal(SIGSEGV, sig);
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
		signal(SIGTERM, sig);
	if (signal(SIGINT, interrupt) == SIG_IGN)
		signal(SIGINT, SIG_IGN);

	dump_getfstab();	/* /etc/fstab snarfed */
	/*
	 *	disk can be either the full special file name,
	 *	the suffix of the special file name,
	 *	the special name missing the leading '/',
	 *	the file system name with or without the leading '/'.
	 */
	dt = fstabsearch(disk);
	if (dt != NULL) {
		disk = rawname(dt->fs_spec);
 		if (disk == NULL)
 			errx(X_STARTUP, "%s: unknown file system", dt->fs_spec);
		(void)strncpy(spcl.c_dev, dt->fs_spec, NAMELEN);
		(void)strncpy(spcl.c_filesys, dt->fs_file, NAMELEN);
	} else {
		(void)strncpy(spcl.c_dev, disk, NAMELEN);
		(void)strncpy(spcl.c_filesys, "an unlisted file system",
		    NAMELEN);
	}
	spcl.c_dev[NAMELEN-1]='\0';
	spcl.c_filesys[NAMELEN-1]='\0';

	if ((mntpt = getmntpt(disk, &mntflags)) != 0) {
		if (mntflags & MNT_RDONLY) {
			if (snapdump != 0) {
				msg("WARNING: %s\n",
				    "-L ignored for read-only filesystem.");
				snapdump = 0;
			}
		} else if (snapdump == 0) {
			msg("WARNING: %s\n",
			    "should use -L when dumping live read-write "
			    "filesystems!");
		} else {
			char snapname[BUFSIZ], snapcmd[BUFSIZ];

			snprintf(snapname, sizeof snapname, "%s/.snap", mntpt);
			if ((stat(snapname, &sb) < 0) || !S_ISDIR(sb.st_mode)) {
				msg("WARNING: %s %s\n",
				    "-L requested but snapshot location",
				    snapname);
				msg("         %s: %s\n",
				    "is not a directory",
				    "dump downgraded, -L ignored");
				snapdump = 0;
			} else {
				snprintf(snapname, sizeof snapname,
				    "%s/.snap/dump_snapshot", mntpt);
				snprintf(snapcmd, sizeof snapcmd, "%s %s %s",
				    _PATH_MKSNAP_FFS, mntpt, snapname);
				unlink(snapname);
				if (system(snapcmd) != 0)
					errx(X_STARTUP, "Cannot create %s: %s\n",
					    snapname, strerror(errno));
				if ((diskfd = open(snapname, O_RDONLY)) < 0) {
					unlink(snapname);
					errx(X_STARTUP, "Cannot open %s: %s\n",
					    snapname, strerror(errno));
				}
				unlink(snapname);
				if (fstat(diskfd, &sb) != 0)
					err(X_STARTUP, "%s: stat", snapname);
				spcl.c_date = _time_to_time64(sb.st_mtime);
			}
		}
	} else if (snapdump != 0) {
		msg("WARNING: Cannot use -L on an unmounted filesystem.\n");
		snapdump = 0;
	}
	if (snapdump == 0) {
		if ((diskfd = open(disk, O_RDONLY)) < 0)
			err(X_STARTUP, "Cannot open %s", disk);
		if (fstat(diskfd, &sb) != 0)
			err(X_STARTUP, "%s: stat", disk);
		if (S_ISDIR(sb.st_mode))
			errx(X_STARTUP, "%s: unknown file system", disk);
	}

	(void)strcpy(spcl.c_label, "none");
	(void)gethostname(spcl.c_host, NAMELEN);
	spcl.c_level = level;
	spcl.c_type = TS_TAPE;
	if (rsync_friendly) {
		/* don't store real dump times */
		spcl.c_date = 0;
		spcl.c_ddate = 0;
	}
	if (spcl.c_date == 0) {
		tmsg = "the epoch\n";
	} else {
		time_t t = _time64_to_time(spcl.c_date);
		tmsg = ctime(&t);
	}
	msg("Date of this level %d dump: %s", level, tmsg);

	if (!Tflag && (!rsync_friendly))
	        getdumptime();		/* /etc/dumpdates snarfed */
	if (spcl.c_ddate == 0) {
		tmsg = "the epoch\n";
	} else {
		time_t t = _time64_to_time(spcl.c_ddate);
		tmsg = ctime(&t);
	}
	if (lastlevel < 0)
		msg("Date of last (level unknown) dump: %s", tmsg);
	else
		msg("Date of last level %d dump: %s", lastlevel, tmsg);

	msg("Dumping %s%s ", snapdump ? "snapshot of ": "", disk);
	if (dt != NULL)
		msgtail("(%s) ", dt->fs_file);
	if (host)
		msgtail("to %s on host %s\n", tape, host);
	else
		msgtail("to %s\n", tape);

	sync();
	sblock = (struct fs *)sblock_buf;
	for (i = 0; sblock_try[i] != -1; i++) {
		sblock->fs_fsize = SBLOCKSIZE; /* needed in bread */
		bread(sblock_try[i] >> dev_bshift, (char *) sblock, SBLOCKSIZE);
		if ((sblock->fs_magic == FS_UFS1_MAGIC ||
		     (sblock->fs_magic == FS_UFS2_MAGIC &&
		      sblock->fs_sblockloc == sblock_try[i])) &&
		    sblock->fs_bsize <= MAXBSIZE &&
		    sblock->fs_bsize >= sizeof(struct fs))
			break;
	}
	if (sblock_try[i] == -1)
		quit("Cannot find file system superblock\n");
	dev_bsize = sblock->fs_fsize / fsbtodb(sblock, 1);
	dev_bshift = ffs(dev_bsize) - 1;
	if (dev_bsize != (1 << dev_bshift))
		quit("dev_bsize (%ld) is not a power of 2", dev_bsize);
	tp_bshift = ffs(TP_BSIZE) - 1;
	if (TP_BSIZE != (1 << tp_bshift))
		quit("TP_BSIZE (%d) is not a power of 2", TP_BSIZE);
	maxino = sblock->fs_ipg * sblock->fs_ncg;
	mapsize = roundup(howmany(maxino, CHAR_BIT), TP_BSIZE);
	usedinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
	dumpdirmap = (char *)calloc((unsigned) mapsize, sizeof(char));
	dumpinomap = (char *)calloc((unsigned) mapsize, sizeof(char));
	tapesize = 3 * (howmany(mapsize * sizeof(char), TP_BSIZE) + 1);

	nonodump = spcl.c_level < honorlevel;

	passno = 1;
	setproctitle("%s: pass 1: regular files", disk);
	msg("mapping (Pass I) [regular files]\n");
	anydirskipped = mapfiles(maxino, &tapesize);

	passno = 2;
	setproctitle("%s: pass 2: directories", disk);
	msg("mapping (Pass II) [directories]\n");
	while (anydirskipped) {
		anydirskipped = mapdirs(maxino, &tapesize);
	}

	if (pipeout || unlimited) {
		tapesize += 10;	/* 10 trailer blocks */
		msg("estimated %ld tape blocks.\n", tapesize);
	} else {
		double fetapes;

		if (blocksperfile)
			fetapes = (double) tapesize / blocksperfile;
		else if (cartridge) {
			/* Estimate number of tapes, assuming streaming stops at
			   the end of each block written, and not in mid-block.
			   Assume no erroneous blocks; this can be compensated
			   for with an artificially low tape size. */
			fetapes =
			(	  (double) tapesize	/* blocks */
				* TP_BSIZE	/* bytes/block */
				* (1.0/density)	/* 0.1" / byte " */
			  +
				  (double) tapesize	/* blocks */
				* (1.0/ntrec)	/* streaming-stops per block */
				* 15.48		/* 0.1" / streaming-stop " */
			) * (1.0 / tsize );	/* tape / 0.1" " */
		} else {
			/* Estimate number of tapes, for old fashioned 9-track
			   tape */
			int tenthsperirg = (density == 625) ? 3 : 7;
			fetapes =
			(	  (double) tapesize	/* blocks */
				* TP_BSIZE	/* bytes / block */
				* (1.0/density)	/* 0.1" / byte " */
			  +
				  (double) tapesize	/* blocks */
				* (1.0/ntrec)	/* IRG's / block */
				* tenthsperirg	/* 0.1" / IRG " */
			) * (1.0 / tsize );	/* tape / 0.1" " */
		}
		etapes = fetapes;		/* truncating assignment */
		etapes++;
		/* count the dumped inodes map on each additional tape */
		tapesize += (etapes - 1) *
			(howmany(mapsize * sizeof(char), TP_BSIZE) + 1);
		tapesize += etapes + 10;	/* headers + 10 trailer blks */
		msg("estimated %ld tape blocks on %3.2f tape(s).\n",
		    tapesize, fetapes);
	}

        /*
         * If the user only wants an estimate of the number of
         * tapes, exit now.
         */
        if (just_estimate)
                exit(0);

	/*
	 * Allocate tape buffer.
	 */
	if (!alloctape())
		quit(
	"can't allocate tape buffers - try a smaller blocking factor.\n");

	startnewtape(1);
	(void)time((time_t *)&(tstart_writing));
	dumpmap(usedinomap, TS_CLRI, maxino - 1);

	passno = 3;
	setproctitle("%s: pass 3: directories", disk);
	msg("dumping (Pass III) [directories]\n");
	dirty = 0;		/* XXX just to get gcc to shut up */
	for (map = dumpdirmap, ino = 1; ino < maxino; ino++) {
		if (((ino - 1) % CHAR_BIT) == 0)	/* map is offset by 1 */
			dirty = *map++;
		else
			dirty >>= 1;
		if ((dirty & 1) == 0)
			continue;
		/*
		 * Skip directory inodes deleted and maybe reallocated
		 */
		dp = getino(ino, &mode);
		if (mode != IFDIR)
			continue;
		(void)dumpino(dp, ino);
	}

	passno = 4;
	setproctitle("%s: pass 4: regular files", disk);
	msg("dumping (Pass IV) [regular files]\n");
	for (map = dumpinomap, ino = 1; ino < maxino; ino++) {
		if (((ino - 1) % CHAR_BIT) == 0)	/* map is offset by 1 */
			dirty = *map++;
		else
			dirty >>= 1;
		if ((dirty & 1) == 0)
			continue;
		/*
		 * Skip inodes deleted and reallocated as directories.
		 */
		dp = getino(ino, &mode);
		if (mode == IFDIR)
			continue;
		(void)dumpino(dp, ino);
	}

	(void)time((time_t *)&(tend_writing));
	spcl.c_type = TS_END;
	for (i = 0; i < ntrec; i++)
		writeheader(maxino - 1);
	if (pipeout)
		msg("DUMP: %jd tape blocks\n", (intmax_t)spcl.c_tapea);
	else
		msg("DUMP: %jd tape blocks on %d volume%s\n",
		    (intmax_t)spcl.c_tapea, spcl.c_volume,
		    (spcl.c_volume == 1) ? "" : "s");

	/* report dump performance, avoid division through zero */
	if (tend_writing - tstart_writing == 0)
		msg("finished in less than a second\n");
	else
		msg("finished in %jd seconds, throughput %jd KBytes/sec\n",
		    (intmax_t)tend_writing - tstart_writing, 
		    (intmax_t)(spcl.c_tapea / 
		    (tend_writing - tstart_writing)));

	putdumptime();
	trewind();
	broadcast("DUMP IS DONE!\a\a\n");
	msg("DUMP IS DONE\n");
	Exit(X_FINOK);
	/* NOTREACHED */
}
Exemple #26
0
int
cluster_read_gb(struct vnode *vp, u_quad_t filesize, daddr_t lblkno, long size,
    struct ucred *cred, long totread, int seqcount, int gbflags,
    struct buf **bpp)
{
	struct buf *bp, *rbp, *reqbp;
	struct bufobj *bo;
	daddr_t blkno, origblkno;
	int maxra, racluster;
	int error, ncontig;
	int i;

	error = 0;
	bo = &vp->v_bufobj;
	if (!unmapped_buf_allowed)
		gbflags &= ~GB_UNMAPPED;

	/*
	 * Try to limit the amount of read-ahead by a few
	 * ad-hoc parameters.  This needs work!!!
	 */
	racluster = vp->v_mount->mnt_iosize_max / size;
	maxra = seqcount;
	maxra = min(read_max, maxra);
	maxra = min(nbuf/8, maxra);
	if (((u_quad_t)(lblkno + maxra + 1) * size) > filesize)
		maxra = (filesize / size) - lblkno;

	/*
	 * get the requested block
	 */
	*bpp = reqbp = bp = getblk(vp, lblkno, size, 0, 0, gbflags);
	origblkno = lblkno;

	/*
	 * if it is in the cache, then check to see if the reads have been
	 * sequential.  If they have, then try some read-ahead, otherwise
	 * back-off on prospective read-aheads.
	 */
	if (bp->b_flags & B_CACHE) {
		if (!seqcount) {
			return 0;
		} else if ((bp->b_flags & B_RAM) == 0) {
			return 0;
		} else {
			bp->b_flags &= ~B_RAM;
			BO_LOCK(bo);
			for (i = 1; i < maxra; i++) {
				/*
				 * Stop if the buffer does not exist or it
				 * is invalid (about to go away?)
				 */
				rbp = gbincore(&vp->v_bufobj, lblkno+i);
				if (rbp == NULL || (rbp->b_flags & B_INVAL))
					break;

				/*
				 * Set another read-ahead mark so we know 
				 * to check again. (If we can lock the
				 * buffer without waiting)
				 */
				if ((((i % racluster) == (racluster - 1)) ||
				    (i == (maxra - 1))) 
				    && (0 == BUF_LOCK(rbp, 
					LK_EXCLUSIVE | LK_NOWAIT, NULL))) {
					rbp->b_flags |= B_RAM;
					BUF_UNLOCK(rbp);
				}			
			}
			BO_UNLOCK(bo);
			if (i >= maxra) {
				return 0;
			}
			lblkno += i;
		}
		reqbp = bp = NULL;
	/*
	 * If it isn't in the cache, then get a chunk from
	 * disk if sequential, otherwise just get the block.
	 */
	} else {
		off_t firstread = bp->b_offset;
		int nblks;
		long minread;

		KASSERT(bp->b_offset != NOOFFSET,
		    ("cluster_read: no buffer offset"));

		ncontig = 0;

		/*
		 * Adjust totread if needed
		 */
		minread = read_min * size;
		if (minread > totread)
			totread = minread;

		/*
		 * Compute the total number of blocks that we should read
		 * synchronously.
		 */
		if (firstread + totread > filesize)
			totread = filesize - firstread;
		nblks = howmany(totread, size);
		if (nblks > racluster)
			nblks = racluster;

		/*
		 * Now compute the number of contiguous blocks.
		 */
		if (nblks > 1) {
	    		error = VOP_BMAP(vp, lblkno, NULL,
				&blkno, &ncontig, NULL);
			/*
			 * If this failed to map just do the original block.
			 */
			if (error || blkno == -1)
				ncontig = 0;
		}

		/*
		 * If we have contiguous data available do a cluster
		 * otherwise just read the requested block.
		 */
		if (ncontig) {
			/* Account for our first block. */
			ncontig = min(ncontig + 1, nblks);
			if (ncontig < nblks)
				nblks = ncontig;
			bp = cluster_rbuild(vp, filesize, lblkno,
			    blkno, size, nblks, gbflags, bp);
			lblkno += (bp->b_bufsize / size);
		} else {
			bp->b_flags |= B_RAM;
			bp->b_iocmd = BIO_READ;
			lblkno += 1;
		}
	}

	/*
	 * handle the synchronous read so that it is available ASAP.
	 */
	if (bp) {
		if ((bp->b_flags & B_CLUSTER) == 0) {
			vfs_busy_pages(bp, 0);
		}
		bp->b_flags &= ~B_INVAL;
		bp->b_ioflags &= ~BIO_ERROR;
		if ((bp->b_flags & B_ASYNC) || bp->b_iodone != NULL)
			BUF_KERNPROC(bp);
		bp->b_iooffset = dbtob(bp->b_blkno);
		bstrategy(bp);
		curthread->td_ru.ru_inblock++;
	}

	/*
	 * If we have been doing sequential I/O, then do some read-ahead.
	 */
	while (lblkno < (origblkno + maxra)) {
		error = VOP_BMAP(vp, lblkno, NULL, &blkno, &ncontig, NULL);
		if (error)
			break;

		if (blkno == -1)
			break;

		/*
		 * We could throttle ncontig here by maxra but we might as
		 * well read the data if it is contiguous.  We're throttled
		 * by racluster anyway.
		 */
		if (ncontig) {
			ncontig = min(ncontig + 1, racluster);
			rbp = cluster_rbuild(vp, filesize, lblkno, blkno,
			    size, ncontig, gbflags, NULL);
			lblkno += (rbp->b_bufsize / size);
			if (rbp->b_flags & B_DELWRI) {
				bqrelse(rbp);
				continue;
			}
		} else {
			rbp = getblk(vp, lblkno, size, 0, 0, gbflags);
			lblkno += 1;
			if (rbp->b_flags & B_DELWRI) {
				bqrelse(rbp);
				continue;
			}
			rbp->b_flags |= B_ASYNC | B_RAM;
			rbp->b_iocmd = BIO_READ;
			rbp->b_blkno = blkno;
		}
		if (rbp->b_flags & B_CACHE) {
			rbp->b_flags &= ~B_ASYNC;
			bqrelse(rbp);
			continue;
		}
		if ((rbp->b_flags & B_CLUSTER) == 0) {
			vfs_busy_pages(rbp, 0);
		}
		rbp->b_flags &= ~B_INVAL;
		rbp->b_ioflags &= ~BIO_ERROR;
		if ((rbp->b_flags & B_ASYNC) || rbp->b_iodone != NULL)
			BUF_KERNPROC(rbp);
		rbp->b_iooffset = dbtob(rbp->b_blkno);
		bstrategy(rbp);
		curthread->td_ru.ru_inblock++;
	}

	if (reqbp)
		return (bufwait(reqbp));
	else
		return (error);
}
Exemple #27
0
int
sbread(struct uufsd *disk)
{
	uint8_t block[MAXBSIZE];
	struct fs *fs;
	int sb, superblock;
	int i, size, blks;
	uint8_t *space;

	ERROR(disk, NULL);

	fs = &disk->d_fs;
	superblock = superblocks[0];

	for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
		if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) {
			ERROR(disk, "non-existent or truncated superblock");
			return (-1);
		}
		if (fs->fs_magic == FS_UFS1_MAGIC)
			disk->d_ufs = 1;
		if (fs->fs_magic == FS_UFS2_MAGIC &&
		    fs->fs_sblockloc == superblock)
			disk->d_ufs = 2;
		if (fs->fs_bsize <= MAXBSIZE &&
		    (size_t)fs->fs_bsize >= sizeof(*fs)) {
			if (disk->d_ufs)
				break;
		}
		disk->d_ufs = 0;
	}
	if (superblock == -1 || disk->d_ufs == 0) {
		/*
		 * Other error cases will result in errno being set, here we
		 * must set it to indicate no superblock could be found with
		 * which to associate this disk/filesystem.
		 */
		ERROR(disk, "no usable known superblock found");
		errno = ENOENT;
		return (-1);
	}
	disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
	disk->d_sblock = superblock / disk->d_bsize;
	/*
	 * Read in the superblock summary information.
	 */
	size = fs->fs_cssize;
	blks = howmany(size, fs->fs_fsize);
	size += fs->fs_ncg * sizeof(int32_t);
	space = malloc(size);
	if (space == NULL) {
		ERROR(disk, "failed to allocate space for summary information");
		return (-1);
	}
	fs->fs_csp = (struct csum *)space;
	for (i = 0; i < blks; i += fs->fs_frag) {
		size = fs->fs_bsize;
		if (i + fs->fs_frag > blks)
			size = (blks - i) * fs->fs_fsize;
		if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
		    == -1) {
			ERROR(disk, "Failed to read sb summary information");
			free(fs->fs_csp);
			return (-1);
		}
		bcopy(block, space, size);
		space += size;
	}
	fs->fs_maxcluster = (uint32_t *)space;
	disk->d_sbcsum = fs->fs_csp;

	return (0);
}
Exemple #28
0
int
verify_sb(xfs_sb_t *sb, int is_primary_sb)
{
	__uint32_t	bsize;
	xfs_extlen_t	align;
	int		i;

	/* check magic number and version number */

	if (sb->sb_magicnum != XFS_SB_MAGIC)
		return(XR_BAD_MAGIC);

	if (!xfs_sb_good_version(sb))
		return(XR_BAD_VERSION);

	/* does sb think mkfs really finished ? */

	if (is_primary_sb && sb->sb_inprogress == 1)
		return(XR_BAD_INPROGRESS);

	/* check to make sure blocksize is legal 2^N, 9 <= N <= 16 */

	if (sb->sb_blocksize == 0)
		return(XR_BAD_BLOCKSIZE);

	bsize = 1;

	for (i = 0; bsize < sb->sb_blocksize &&
		i < sizeof(sb->sb_blocksize) * NBBY; i++)
		bsize <<= 1;

	if (i < XFS_MIN_BLOCKSIZE_LOG || i > XFS_MAX_BLOCKSIZE_LOG)
		return(XR_BAD_BLOCKSIZE);

	/* check sb blocksize field against sb blocklog field */

	if (i != sb->sb_blocklog)
		return(XR_BAD_BLOCKLOG);

	/* sanity check ag count, size fields against data size field */

	if (sb->sb_dblocks == 0 ||
		sb->sb_dblocks >
			((__uint64_t)sb->sb_agcount * sb->sb_agblocks) ||
		sb->sb_dblocks <
			((__uint64_t)(sb->sb_agcount - 1) * sb->sb_agblocks
			+ XFS_MIN_AG_BLOCKS))
		return(XR_BAD_FS_SIZE_DATA);

	if (sb->sb_agblklog != (__uint8_t)libxfs_log2_roundup(sb->sb_agblocks))
		return(XR_BAD_FS_SIZE_DATA);

	if (sb->sb_inodesize < XFS_DINODE_MIN_SIZE ||
		sb->sb_inodesize > XFS_DINODE_MAX_SIZE ||
		sb->sb_inopblock != howmany(sb->sb_blocksize,sb->sb_inodesize))
		return(XR_BAD_INO_SIZE_DATA);

	/* check to make sure sectorsize is legal 2^N, 9 <= N <= 15 */

	if (sb->sb_sectsize == 0)
		return(XR_BAD_SECT_SIZE_DATA);

	bsize = 1;

	for (i = 0; bsize < sb->sb_sectsize &&
		i < sizeof(sb->sb_sectsize) * NBBY; i++)  {
		bsize <<= 1;
	}

	if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG)
		return(XR_BAD_SECT_SIZE_DATA);

	/* check sb sectorsize field against sb sectlog field */

	if (i != sb->sb_sectlog)
		return(XR_BAD_SECT_SIZE_DATA);

	if (xfs_sb_version_hassector(sb))  {

		/* check to make sure log sector is legal 2^N, 9 <= N <= 15 */

		if (sb->sb_logsectsize == 0)
			return(XR_BAD_SECT_SIZE_DATA);

		bsize = 1;

		for (i = 0; bsize < sb->sb_logsectsize &&
			i < sizeof(sb->sb_logsectsize) * NBBY; i++)  {
			bsize <<= 1;
		}

		if (i < XFS_MIN_SECTORSIZE_LOG || i > XFS_MAX_SECTORSIZE_LOG)
			return(XR_BAD_SECT_SIZE_DATA);

		/* check sb log sectorsize field against sb log sectlog field */

		if (i != sb->sb_logsectlog)
			return(XR_BAD_SECT_SIZE_DATA);
	}

	/*
	 * real-time extent size is always set
	 */
	if (sb->sb_rextsize * sb->sb_blocksize > XFS_MAX_RTEXTSIZE)
		return(XR_BAD_RT_GEO_DATA);

	if (sb->sb_rextsize * sb->sb_blocksize < XFS_MIN_RTEXTSIZE)
			return(XR_BAD_RT_GEO_DATA);

	if (sb->sb_rblocks == 0)  {
		if (sb->sb_rextents != 0)
			return(XR_BAD_RT_GEO_DATA);

		if (sb->sb_rbmblocks != 0)
			return(XR_BAD_RT_GEO_DATA);

		if (sb->sb_rextslog != 0)
			return(XR_BAD_RT_GEO_DATA);

		if (sb->sb_frextents != 0)
			return(XR_BAD_RT_GEO_DATA);
	} else  {
		/*
		 * if we have a real-time partition, sanity-check geometry
		 */
		if (sb->sb_rblocks / sb->sb_rextsize != sb->sb_rextents)
			return(XR_BAD_RT_GEO_DATA);

		if (sb->sb_rextslog !=
				libxfs_highbit32((unsigned int)sb->sb_rextents))
			return(XR_BAD_RT_GEO_DATA);

		if (sb->sb_rbmblocks != (xfs_extlen_t) howmany(sb->sb_rextents,
						NBBY * sb->sb_blocksize))
			return(XR_BAD_RT_GEO_DATA);
	}

	/*
	 * verify correctness of inode alignment if it's there
	 */
	if (xfs_sb_version_hasalign(sb))  {
		align = calc_ino_align(sb);

		if (align != sb->sb_inoalignmt)
			return(XR_BAD_INO_ALIGN);
	}

	/*
	 * verify max. % of inodes (sb_imax_pct)
	 */
	if (sb->sb_imax_pct > 100)
		return(XR_BAD_INO_MAX_PCT);

	/*
	 * verify stripe alignment fields if present
	 */
	if (xfs_sb_version_hasdalign(sb)) {
		if ((!sb->sb_unit && sb->sb_width) ||
		    (sb->sb_unit && sb->sb_agblocks % sb->sb_unit))
			return(XR_BAD_SB_UNIT);
		if ((sb->sb_unit && !sb->sb_width) ||
		    (sb->sb_width && sb->sb_unit && sb->sb_width % sb->sb_unit))
			return(XR_BAD_SB_WIDTH);
	}

	/*
	 * if shared bit is set, verify that the version number is sane
	 */
	if (xfs_sb_version_hasshared(sb))  {
		if (sb->sb_shared_vn > XFS_SB_MAX_SHARED_VN)
			return(XR_BAD_SVN);
	}

	/*
	 * mkfs's that stamped a feature bit besides the ones in the
	 * mask below could leave garbage in the secondary superblock
	 * sectors.  Anything stamping the shared fs bit or better into
	 * the secondaries is ok and should generate clean secondary
	 * superblock sectors.
	 *
	 * check primary and clean secondary superblocks more strictly
	 */
	if (is_primary_sb || sb->sb_versionnum & XR_PART_SECSB_VNMASK)  {
		/*
		 * return errors if shared vn or alignment fields
		 * are set without their feature bits being set
		 */
		if ((!pre_65_beta && (sb->sb_versionnum & XR_PART_SECSB_VNMASK)) ||
		    (pre_65_beta && (sb->sb_versionnum & XR_ALPHA_SECSB_VNMASK))) {
			/*
			 * shared version # and inode alignment fields
			 * should be valid
			 */
			if (sb->sb_shared_vn && !xfs_sb_version_hasshared(sb))
				return(XR_BAD_SVN);
			if (sb->sb_inoalignmt && !xfs_sb_version_hasalign(sb))
				return(XR_BAD_INO_ALIGN);
		}
		if ((!pre_65_beta &&
		     (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK)) ||
		    (pre_65_beta &&
		     (sb->sb_versionnum & XFS_SB_VERSION_DALIGNBIT)))  {
			/*
			 * stripe alignment values should be valid
			 */
			if (sb->sb_unit && !xfs_sb_version_hasdalign(sb))
				return(XR_BAD_SB_UNIT);
			if (sb->sb_width && !xfs_sb_version_hasdalign(sb))
				return(XR_BAD_SB_WIDTH);
		}

#if 0
		/*
		 * checks involving later superblock fields get added here...
		 */
		if (sb->sb_versionnum & XR_GOOD_SECSB_VNMASK)  {
		}
#endif
	}

	return(XR_OK);
}
int
sftp_server_main(int argc, char **argv, struct passwd *user_pw)
{
	fd_set *rset, *wset;
	int in, out, max, ch, skipargs = 0, log_stderr = 0;
	ssize_t len, olen, set_size;
	SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
	char *cp, buf[4*4096];
	const char *errmsg;
	mode_t mask;

	extern char *optarg;
	extern char *__progname;

	__progname = ssh_get_progname(argv[0]);
	log_init(__progname, log_level, log_facility, log_stderr);

    fake_permissions = 0;
	while (!skipargs && (ch = getopt(argc, argv, "f:l:u:cehRU")) != -1) {
		switch (ch) {
		case 'R':
			readonly = 1;
			break;
		case 'c':
			/*
			 * Ignore all arguments if we are invoked as a
			 * shell using "sftp-server -c command"
			 */
			skipargs = 1;
			break;
		case 'e':
			log_stderr = 1;
			break;
		case 'l':
			log_level = log_level_number(optarg);
			if (log_level == SYSLOG_LEVEL_NOT_SET)
				error("Invalid log level \"%s\"", optarg);
			break;
		case 'f':
			log_facility = log_facility_number(optarg);
			if (log_facility == SYSLOG_FACILITY_NOT_SET)
				error("Invalid log facility \"%s\"", optarg);
			break;
		case 'u':
			mask = (mode_t)strtonum(optarg, 0, 0777, &errmsg);
			if (errmsg != NULL)
				fatal("Invalid umask \"%s\": %s",
				    optarg, errmsg);
			(void)umask(mask);
			break;
		case 'U': /* Fake permissions */
			fake_permissions = 1;
			break;
		case 'h':
		default:
			sftp_server_usage();
		}
	}

	log_init(__progname, log_level, log_facility, log_stderr);

	if ((cp = getenv("SSH_CONNECTION")) != NULL) {
		client_addr = xstrdup(cp);
		if ((cp = strchr(client_addr, ' ')) == NULL) {
			error("Malformed SSH_CONNECTION variable: \"%s\"",
			    getenv("SSH_CONNECTION"));
			sftp_server_cleanup_exit(255);
		}
		*cp = '\0';
	} else
		client_addr = xstrdup("UNKNOWN");

	pw = pwcopy(user_pw);

	logit("session opened for local user %s from [%s]",
	    pw->pw_name, client_addr);

	in = STDIN_FILENO;
	out = STDOUT_FILENO;

#ifdef HAVE_CYGWIN
	setmode(in, O_BINARY);
	setmode(out, O_BINARY);
#endif

	max = 0;
	if (in > max)
		max = in;
	if (out > max)
		max = out;

	buffer_init(&iqueue);
	buffer_init(&oqueue);

	set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
	rset = (fd_set *)xmalloc(set_size);
	wset = (fd_set *)xmalloc(set_size);

	for (;;) {
		memset(rset, 0, set_size);
		memset(wset, 0, set_size);

		/*
		 * Ensure that we can read a full buffer and handle
		 * the worst-case length packet it can generate,
		 * otherwise apply backpressure by stopping reads.
		 */
		if (buffer_check_alloc(&iqueue, sizeof(buf)) &&
		    buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
			FD_SET(in, rset);

		olen = buffer_len(&oqueue);
		if (olen > 0)
			FD_SET(out, wset);

		if (select(max+1, rset, wset, NULL, NULL) < 0) {
			if (errno == EINTR)
				continue;
			error("select: %s", strerror(errno));
			sftp_server_cleanup_exit(2);
		}

		/* copy stdin to iqueue */
		if (FD_ISSET(in, rset)) {
			len = read(in, buf, sizeof buf);
			if (len == 0) {
				debug("read eof");
				sftp_server_cleanup_exit(0);
			} else if (len < 0) {
				error("read: %s", strerror(errno));
				sftp_server_cleanup_exit(1);
			} else {
				buffer_append(&iqueue, buf, len);
			}
		}
		/* send oqueue to stdout */
		if (FD_ISSET(out, wset)) {
			len = write(out, buffer_ptr(&oqueue), olen);
			if (len < 0) {
				error("write: %s", strerror(errno));
				sftp_server_cleanup_exit(1);
			} else {
				buffer_consume(&oqueue, len);
			}
		}

		/*
		 * Process requests from client if we can fit the results
		 * into the output buffer, otherwise stop processing input
		 * and let the output queue drain.
		 */
		if (buffer_check_alloc(&oqueue, SFTP_MAX_MSG_LENGTH))
			process();
	}
}
Exemple #30
0
/*
 * Waits for the server identification string, and sends our own
 * identification string.
 */
void
ssh_exchange_identification(struct ssh *ssh, int timeout_ms)
{
	char buf[256], remote_version[256];	/* must be same size! */
	int remote_major, remote_minor, mismatch;
	int connection_in = ssh_packet_get_connection_in(ssh);
	int connection_out = ssh_packet_get_connection_out(ssh);
	int minor1 = PROTOCOL_MINOR_1;
	u_int i, n;
	size_t len;
	int fdsetsz, remaining, rc;
	struct timeval t_start, t_remaining;
	fd_set *fdset;

	fdsetsz = howmany(connection_in + 1, NFDBITS) * sizeof(fd_mask);
	fdset = xcalloc(1, fdsetsz);

	/* Read other side's version identification. */
	remaining = timeout_ms;
	for (n = 0;;) {
		for (i = 0; i < sizeof(buf) - 1; i++) {
			if (timeout_ms > 0) {
				gettimeofday(&t_start, NULL);
				ms_to_timeval(&t_remaining, remaining);
				FD_SET(connection_in, fdset);
				rc = select(connection_in + 1, fdset, NULL,
				    fdset, &t_remaining);
				ms_subtract_diff(&t_start, &remaining);
				if (rc == 0 || remaining <= 0)
					fatal("Connection timed out during "
					    "banner exchange");
				if (rc == -1) {
					if (errno == EINTR)
						continue;
					fatal("ssh_exchange_identification: "
					    "select: %s", strerror(errno));
				}
			}

			len = roaming_atomicio(read, connection_in, &buf[i], 1);

			if (len != 1 && errno == EPIPE)
				fatal("ssh_exchange_identification: "
				    "Connection closed by remote host");
			else if (len != 1)
				fatal("ssh_exchange_identification: "
				    "read: %.100s", strerror(errno));
			if (buf[i] == '\r') {
				buf[i] = '\n';
				buf[i + 1] = 0;
				continue;		/**XXX wait for \n */
			}
			if (buf[i] == '\n') {
				buf[i + 1] = 0;
				break;
			}
			if (++n > 65536)
				fatal("ssh_exchange_identification: "
				    "No banner received");
		}
		buf[sizeof(buf) - 1] = 0;
		if (strncmp(buf, "SSH-", 4) == 0)
			break;
		debug("ssh_exchange_identification: %s", buf);
	}
	server_version_string = xstrdup(buf);
	xfree(fdset);

	/*
	 * Check that the versions match.  In future this might accept
	 * several versions and set appropriate flags to handle them.
	 */
	if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
	    &remote_major, &remote_minor, remote_version) != 3)
		fatal("Bad remote protocol version identification: '%.100s'", buf);
	debug("Remote protocol version %d.%d, remote software version %.100s",
	    remote_major, remote_minor, remote_version);

	ssh->compat = compat_datafellows(remote_version);
	mismatch = 0;

	switch (remote_major) {
	case 1:
		if (remote_minor == 99 &&
		    (options.protocol & SSH_PROTO_2) &&
		    !(options.protocol & SSH_PROTO_1_PREFERRED)) {
			enable_compat20();
			break;
		}
		if (!(options.protocol & SSH_PROTO_1)) {
			mismatch = 1;
			break;
		}
		if (remote_minor < 3) {
			fatal("Remote machine has too old SSH software version.");
		} else if (remote_minor == 3 || remote_minor == 4) {
			/* We speak 1.3, too. */
			enable_compat13();
			minor1 = 3;
			if (options.forward_agent) {
				logit("Agent forwarding disabled for protocol 1.3");
				options.forward_agent = 0;
			}
		}
		break;
	case 2:
		if (options.protocol & SSH_PROTO_2) {
			enable_compat20();
			break;
		}
		/* FALLTHROUGH */
	default:
		mismatch = 1;
		break;
	}
	if (mismatch)
		fatal("Protocol major versions differ: %d vs. %d",
		    (options.protocol & SSH_PROTO_2) ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
		    remote_major);
	/* Send our own protocol version identification. */
	snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s",
	    compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
	    compat20 ? PROTOCOL_MINOR_2 : minor1,
	    SSH_VERSION, compat20 ? "\r\n" : "\n");
	if (roaming_atomicio(vwrite, connection_out, buf, strlen(buf))
	    != strlen(buf))
		fatal("write: %.100s", strerror(errno));
	client_version_string = xstrdup(buf);
	chop(client_version_string);
	chop(server_version_string);
	debug("Local version string %.100s", client_version_string);
}