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; }
/* * 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 */ }
/* * 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); }