/* * is_fs_writeable - given a cfent entry, return 1 * if it's writeable, 0 if read-only. * * Note: Upon exit, a valid fsys() is guaranteed. This is * an interface requirement. */ int is_fs_writeable(char *path, uint32_t *fsys_value) { if (*fsys_value == BADFSYS) *fsys_value = fsys(path); return (is_fs_writeable_n(*fsys_value)); }
static int readspace(char *spacefile, int *error) { FILE *fp; char line[LSIZE]; long blocks, nodes; int n; if (spacefile == NULL) return (0); if ((fp = fopen(spacefile, "r")) == NULL) { progerr(gettext("unable to open spacefile %s"), spacefile); return (-1); } while (fgets(line, LSIZE, fp)) { struct fstable *fs_tab; char *pt, path[PATH_MAX]; blocks = nodes = 0; for (pt = line; isspace(*pt); /* void */) pt++; if (*pt == '#' || *pt == '\0') continue; (void) sscanf(line, "%s %ld %ld", path, &blocks, &nodes); mappath(2, path); basepath(path, get_basedir(), get_inst_root()); canonize(path); n = resolved_fsys(path); if (fsys_stat(n)) { (*error)++; continue; } /* * Don't accumulate space requirements on read-only * remote filesystems. NOTE: For some reason, this * used to check for !remote && read only. If this * blows up later, then maybe that was correct -- JST */ if (is_remote_fs_n(n) && !is_fs_writeable_n(n)) continue; fs_tab = get_fs_entry(n); fs_tab->bused += blocks; fs_tab->fused += nodes; } (void) fclose(fp); return (0); }
static void write_dryrun_ascii() { int n; char *fs_mntpt, *src_name; if ((fp_dra = fopen(dryrun_sumasc, "wb")) == NULL) { progerr(gettext(ERR_NOOPEN), dryrun_sumasc); return; } (void) fprintf(fp_dra, "DR_TYPE=%s\n", (dr_info.type == REMOVE_TYPE ? "REMOVE" : "INSTALL")); (void) fprintf(fp_dra, "PKG_INSTALL_ROOT=%s\n", (((get_inst_root()) && (strcmp(get_inst_root(), "/") != 0)) ? get_inst_root() : "")); write_pkglist_ascii(); wr_OK(fp_dra, "CONTINUE", 1, !(dr_info.do_not_continue)); wr_OK(fp_dra, "PARTIAL", dr_info.partial_set, dr_info.partial); wr_OK(fp_dra, "RUNLEVEL", dr_info.runlevel_set, dr_info.runlevel); (void) fprintf(fp_dra, "REQUESTEXITCODE=%d\n", dr_info.reqexit); (void) fprintf(fp_dra, "CHECKINSTALLEXITCODE=%d\n", dr_info.checkexit); wr_OK(fp_dra, "PKGFILES", dr_info.pkgfiles_set, dr_info.pkgfiles); wr_OK(fp_dra, "DEPEND", dr_info.depend_set, dr_info.depend); wr_OK(fp_dra, "SPACE", dr_info.space_set, dr_info.space); wr_OK(fp_dra, "CONFLICT", dr_info.conflict_set, dr_info.conflict); wr_OK(fp_dra, "SETUID", dr_info.setuid_set, dr_info.setuid); wr_OK(fp_dra, "PRIV", dr_info.priv_set, dr_info.priv); wr_OK(fp_dra, "PKGDIRS", dr_info.pkgdirs_set, dr_info.pkgdirs); (void) fprintf(fp_dra, "EXITCODE=%d\n", dr_info.exitcode); (void) fprintf(fp_dra, "ERRORMSG=%s\n", (exitmsg ? exitmsg : "NONE")); (void) fclose(fp_dra); if ((fp_dra = fopen(dryrun_fsasc, "wb")) == NULL) { progerr(gettext(ERR_NOOPEN), dryrun_fsasc); return; } (void) fprintf(fp_dra, "%s\nFSUSAGE=\\\n\"\\\n", HDR_FSUSAGE); for (n = 0; fs_mntpt = get_fs_name_n(n); n++) { int bfree, bused; bfree = get_blk_free_n(n); bused = get_blk_used_n(n); if (bfree || bused) { (void) fprintf(fp_dra, "%s %s %s %d %d %lu %lu \\\n", fs_mntpt, ((src_name = get_source_name_n(n)) ? src_name : "none?"), (is_fs_writeable_n(n) ? "TRUE" : "FALSE"), bfree, bused, get_inode_free_n(n), get_inode_used_n(n)); } } dr_info.total_fs_recs = n; (void) fprintf(fp_dra, "\"\n"); (void) fclose(fp_dra); if ((fp_dra = fopen(dryrun_poasc, "wb")) == NULL) { progerr(gettext(ERR_NOOPEN), dryrun_poasc); return; } dr_info.total_ext_recs = 0; (void) fprintf(fp_dra, "WOULD_INSTALL=\\\n\"\\\n"); for (n = 0; extptr && extptr[n]; n++) { /* * Write it out if it's a successful change or it is from the * prior dryrun file (meaning it was a change back then). */ if ((this_exitcode == 0 && (extptr[n]->mstat.contchg || extptr[n]->mstat.attrchg)) || extptr[n]->mstat.preloaded) { (void) fprintf(fp_dra, "%c %s \\\n", extptr[n]->cf_ent.ftype, extptr[n]->client_path); /* Count it, if it's going into the dryrun file. */ if (extptr[n]->cf_ent.ftype != 'i') dr_info.total_ext_recs++; } } (void) fprintf(fp_dra, "\"\n"); (void) fclose(fp_dra); }
/* * 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); }
static char * check_db_entry(VFP_T *vfpo, struct cfextra *entry, int rmflag, char *myclass, int *dbchg) { struct pinfo *pinfo; int fs_entry; char *save_path = NULL; char *tp; /* write this entry to the contents file */ if (myclass && strcmp(myclass, entry->cf_ent.pkg_class)) { if (putcvfpfile(&entry->cf_ent, vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } return (NULL); } /* * Now scan each package instance holding this file or * directory and see if it matches the package we are * updating here. */ pinfo = entry->cf_ent.pinfo; while (pinfo) { if (strcmp(pkginst, pinfo->pkg) == 0) break; pinfo = pinfo->next; } /* * If pinfo == NULL at this point, then this file or * directory isn't part of the package of interest. * So the loop below executes only on files in the package * of interest. */ save_path = NULL; if (pinfo) { if (rmflag && (pinfo->status == RM_RDY)) { *dbchg = 1; (void) eptstat(&(entry->cf_ent), pkginst, '@'); if (entry->cf_ent.npkgs) { if (putcvfpfile(&(entry->cf_ent), vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } } return (NULL); } else if (!rmflag && (pinfo->status == INST_RDY)) { *dbchg = 1; /* tp is the server-relative path */ tp = fixpath(entry->cf_ent.path); /* save_path is the cmd line path */ save_path = entry->cf_ent.path; /* entry has the server-relative path */ entry->cf_ent.path = tp; /* * The next if statement figures out how * the contents file entry should be * annotated. * * Don't install or verify objects for * remote, read-only filesystems. We * need only verify their presence and * flag them appropriately from some * server. Otherwise, ok to do final * check. */ fs_entry = fsys(entry->cf_ent.path); if (is_remote_fs_n(fs_entry) && !is_fs_writeable_n(fs_entry)) { /* * Mark it shared whether it's present * or not. life's too funny for me * to explain. */ pinfo->status = SERVED_FILE; /* * restore for now. This may * chg soon. */ entry->cf_ent.path = save_path; } else { /* * If the object is accessible, check * the new entry for existence and * attributes. If there's a problem, * mark it NOT_FND; otherwise, * ENTRY_OK. */ if (is_mounted_n(fs_entry)) { int n; n = finalck((&entry->cf_ent), 1, 1, B_FALSE); pinfo->status = ENTRY_OK; if (n != 0) { pinfo->status = NOT_FND; } } /* * It's not remote, read-only but it * may look that way to the client. * If it does, overwrite the above * result - mark it shared. */ if (is_served_n(fs_entry)) pinfo->status = SERVED_FILE; /* restore original path */ entry->cf_ent.path = save_path; /* and clear save_path */ save_path = NULL; } } } /* Output entry to contents file. */ if (putcvfpfile(&(entry->cf_ent), vfpo)) { progerr(gettext(ERR_WRITE)); quit(99); } return (save_path); }