Example #1
0
 shared_blk reserve( shared_blk blk , const int sz ) {
   if ( static_cast<int>(blk.size()) < sz ) {
     shared_blk nblk( sz );
     nblk.write( blk.read_ptr() , blk.length());
     blk.swap(nblk);
   }
   return blk;
 }
ITlvObject* CTlvSharedMemoryInfoCreator::create(const ITlvBlock &blk) const
{
	if (blk.length() < ITlvBlock::szHeader * 2) {
		PERR("TLV block size is too small.");
		return NULL;
	}

	// Get name.
	CSharedTlvBlock nblk(blk.value());
	if (blk.length() < nblk.plainSize() + CTlvUint32::Size) {
		PERR("TLV block size is too small.");
		return NULL;
	}
	CTlvString *name;
	if (!(name = dynamic_cast<CTlvString *>(CTlvObjectFactory::instance()->
			createTLVObject(nblk)))) {
		PERR("Unable to construct name string from TLV block.");
		return NULL;
	}

	// Get size.
	CSharedTlvBlock sblk(blk.value() + nblk.plainSize());
	CTlvUint32 *u32;
	if (!(u32 = dynamic_cast<CTlvUint32 *>(CTlvObjectFactory::instance()->
			createTLVObject(sblk)))) {
		PERR("Unable to construct size value from TLV block.");
		return NULL;
	}

	// Thank god it successes.
	CTlvSharedMemoryInfo *sminfo = new CTlvSharedMemoryInfo(name->toString(), u32->value());
	delete name;
	delete u32;

	return sminfo;
}
Example #3
0
/*
 * This function installs the database lock, opens the contents file for
 * reading and creates and opens the temporary contents file for read/write.
 * It returns 1 if successful, 0 otherwise.
 */
int
ocfile(PKGserver *server, VFP_T **r_tmpvfp, fsblkcnt_t map_blks)
{
	struct	stat64	statb, statl;
	struct	statvfs64	svfsb;
	fsblkcnt_t free_blocks;
	fsblkcnt_t need_blocks;
	fsblkcnt_t log_blocks;
	VFP_T		*tmpvfp = (VFP_T *)NULL;
	char		contents[PATH_MAX];
	char		logfile[PATH_MAX];
	int		n;
	off_t		cdiff_alloc;
	PKGserver	newserver;

	/* establish package administration contents directory location */

	if (pkgadm_dir == NULL) {
		if (set_cfdir(NULL) != 0) {
			progerr(gettext(ERR_CFDIR));
			return (0);
		}
	}

	/* Lock the file for exclusive access */

	if (!pkgWlock(1)) {
		progerr(gettext(ERR_NOLOCK));
		return (0);
	}

	if (*server != NULL) {
		vfpTruncate(*r_tmpvfp);
		(void) vfpClearModified(*r_tmpvfp);

		return (1);
	}

	newserver = pkgopenserver(NULL, pkgadm_dir, B_FALSE);

	/* The error has been reported. */
	if (newserver == NULL)
		return (0);

	/* reset return VFP/FILE pointers */

	(*r_tmpvfp) = (VFP_T *)NULL;

	/* determine path to the primary contents file */
	(void) snprintf(contents, sizeof (contents), "%s/contents", pkgadm_dir);

	/*
	 * Check and see if there is enough space for the packaging commands
	 * to back up the contents file, if there is not, then do not allow
	 * execution to continue by failing the ocfile() call.
	 */

	/* Get the contents file size */

	if (stat64(contents, &statb) == -1) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOCFILE), contents);
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	/* Get the filesystem space */

	if (statvfs64(contents, &svfsb) == -1) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOSTATV), contents);
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	free_blocks = (((fsblkcnt_t)svfsb.f_frsize > 0) ?
	    howmany(svfsb.f_frsize, DEV_BSIZE) :
	    howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bfree;

	/* determine blocks used by the logfile */
	(void) snprintf(logfile, sizeof (logfile), "%s/" PKGLOG, pkgadm_dir);

	if (stat64(logfile, &statl) == -1)
		log_blocks = 0;
	else
		log_blocks = nblk(statl.st_size, svfsb.f_bsize, svfsb.f_frsize);

	/*
	 * Calculate the number of blocks we need to be able to operate on
	 * the contents file and the log file.
	 * When adding a package (map_blks > 0), we add the size of the
	 * pkgmap file times 1.5 as the pkgmap is a bit smaller then the
	 * lines added to the contents file.  That data is written both to
	 * the new contents file and the log file (2 * 1.5 * map_blks).
	 * The new contents file is limited by the size of the current
	 * contents file and the increased log file.
	 * If we're removing a package, then the log might grow to the size
	 * of the full contents file but then the new contents file would
	 * be zero and so we only need to add the size of the contents file.
	 */
	need_blocks = map_blks * 3 +
	    /* Current log file */
	    log_blocks +
	    /* Current contents file */
	    nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize);

	if ((need_blocks + 10) > free_blocks) {
		progerr(gettext(ERR_CFBACK), contents);
		progerr(gettext(ERR_CFBACK1), need_blocks, free_blocks,
		    DEV_BSIZE);
		pkgcloseserver(newserver);
		return (0);
	}

	/*
	 * open the temporary contents file without a path name - this causes
	 * the "vfp" to be opened on in-memory storage only, the size of which
	 * is set following a successful return - this causes the temporary
	 * contents file to be maintained in memory only - if no changes are
	 * made as the primary contents file is processed, the in memory data
	 * is discarded and not written to the disk.
	 */

	if (vfpOpen(&tmpvfp, (char *)NULL, "w", VFP_NONE) != 0) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOTMPOPEN));
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		pkgcloseserver(newserver);
		return (0);
	}

	/*
	 * set size of allocation for temporary contents file - this sets the
	 * size of the in-memory buffer associated with the open vfp.
	 * We only store the new and changed entries.
	 * We allocate memory depending on the size of the pkgmap; it's not
	 * completely right but <some value + * 1.5 * map_blks * DEV_BSIZE>
	 * seems fine (an install adds the size if the name of the package.)
	 */

	cdiff_alloc = map_blks * DEV_BSIZE;
	cdiff_alloc += cdiff_alloc/2;
	if (cdiff_alloc < 1000000)
		cdiff_alloc += 1000000;

	if (vfpSetSize(tmpvfp, cdiff_alloc) != 0) {
		int	lerrno = errno;

		progerr(gettext(ERR_NOTMPOPEN));
		logerr(gettext(ERR_ERRNO), lerrno, strerror(lerrno));
		(void) vfpClose(&tmpvfp);
		pkgcloseserver(newserver);
		return (0);
	}

	/* set return ->s to open server/vfps */

	(*r_tmpvfp) = tmpvfp;
	*server = newserver;

	return (1);	/* All OK */
}
Example #4
0
/*
 * This function reads all of the package objects, maps them to their target
 * filesystems and adds up the amount of space used on each. Wherever you see
 * "fsys_value", that's the apparent filesystem which could be a temporary
 * loopback mount for the purpose of constructing the client filesystem. It
 * isn't necessarily the real target filesystem. Where you see "fsys_base"
 * that's the real filesystem to which fsys_value may just refer. If this is
 * installing to a standalone or a server, fsys_value will almost always be
 * the same as fsys_base.
 */
static int
readmap(int *error)
{
	struct fstable *fs_tab;
	struct cfextra *ext;
	struct cfent *ept;
	struct stat statbuf;
	char	tpath[PATH_MAX];
	fsblkcnt_t	blk;
	int	i, n;

	/*
	 * Handle the installation files (ftype i) that are in the
	 * pkgmap/eptlist.
	 */
	for (i = 0; (ext = extlist[i]) != NULL; i++) {
		ept = &(ext->cf_ent);

		if (ept->ftype != 'i')
			continue;

		/*
		 * These paths are treated differently from the others
		 * since their full pathnames are not included in the
		 * pkgmap.
		 */
		if (strcmp(ept->path, "pkginfo") == 0)
			(void) sprintf(tpath, "%s/%s", pkgloc, ept->path);
		else
			(void) sprintf(tpath, "%s/install/%s", pkgloc,
			    ept->path);

		/* If we haven't done an fsys() series, do one */
		if (ext->fsys_value == BADFSYS)
			ext->fsys_value = fsys(tpath);

		/*
		 * Now check if this is a base or apparent filesystem. If
		 * it's just apparent, get the resolved filesystem entry,
		 * otherwise, base and value are the same.
		 */
		if (use_srvr_map_n(ext->fsys_value))
			ext->fsys_base = resolved_fsys(tpath);
		else
			ext->fsys_base = ext->fsys_value;

		if (fsys_stat(ext->fsys_base)) {
			(*error)++;
			continue;
		}

		/*
		 * Don't accumulate space requirements on read-only
		 * remote filesystems.
		 */
		if (is_remote_fs_n(ext->fsys_value) &&
		    !is_fs_writeable_n(ext->fsys_value))
			continue;

		fs_tab = get_fs_entry(ext->fsys_base);

		fs_tab->fused++;
		if (ept->cinfo.size != BADCONT)
			blk = nblk(ept->cinfo.size,
			    fs_tab->bsize,
			    fs_tab->frsize);
		else
			blk = 0;
		fs_tab->bused += blk;
	}

	/*
	 * Handle the other files in the eptlist.
	 */
	for (i = 0; (ext = extlist[i]) != NULL; i++) {
		ept = &(extlist[i]->cf_ent);

		if (ept->ftype == 'i')
			continue;

		/*
		 * Don't recalculate package objects that are already in the
		 * table.
		 */
		if (ext->mstat.preloaded)
			continue;

		/*
		 * Don't accumulate space requirements on read-only
		 * remote filesystems.
		 */
		if (is_remote_fs(ept->path, &(ext->fsys_value)) &&
		    !is_fs_writeable(ept->path, &(ext->fsys_value)))
			continue;

		/*
		 * Now check if this is a base or apparent filesystem. If
		 * it's just apparent, get the resolved filesystem entry,
		 * otherwise, base and value are the same.
		 */
		if (use_srvr_map_n(ext->fsys_value))
			ext->fsys_base = resolved_fsys(tpath);
		else
			ext->fsys_base = ext->fsys_value;

		/* At this point we know we have a good fsys_base. */
		if (fsys_stat(ext->fsys_base)) {
			(*error)++;
			continue;
		}

		/*
		 * We have to stat this path based upon it's real location.
		 * If this is a server-remap, ept->path isn't the real
		 * location.
		 */
		if (use_srvr_map_n(ext->fsys_value))
			strcpy(tpath, server_map(ept->path, ext->fsys_value));
		else
			strcpy(tpath, ept->path);

		fs_tab = get_fs_entry(ext->fsys_base);
		if (stat(tpath, &statbuf)) {
			/* path cannot be accessed */
			fs_tab->fused++;
			if (strchr("dxs", ept->ftype))
				blk =
				    nblk(fs_tab->bsize,
				    fs_tab->bsize,
				    fs_tab->frsize);
			else if (ept->cinfo.size != BADCONT)
				blk = nblk(ept->cinfo.size,
				    fs_tab->bsize,
				    fs_tab->frsize);
			else
				blk = 0;
		} else {
			/* path already exists */
			if (strchr("dxs", ept->ftype))
				blk = 0;
			else if (ept->cinfo.size != BADCONT) {
				fsblkcnt_t new_size, old_size;
				new_size = nblk(ept->cinfo.size,
				    fs_tab->bsize,
				    fs_tab->frsize);
				old_size = nblk(statbuf.st_size,
				    fs_tab->bsize,
				    fs_tab->frsize);
				/*
				 * negative blocks show room freed, but since
				 * order of installation is uncertain show
				 * 0 blocks usage
				 */
				if (new_size < old_size)
					blk = 0;
				else
					blk = new_size - old_size;
			} else
				blk = 0;
		}
		fs_tab->bused += blk;
	}
	return (0);
}