/* * get_mount_point - given a filesystem table index, return the * path of the mount point. Otherwise, * return NULL if it's a local filesystem. */ char * get_mount_point(uint32_t n) { if (!is_remote_fs_n(n)) return (NULL); /* local */ return (fs_tab[n]->name); }
/* * is_remote_fs - given a cfent entry, return 1 * if it's a remote filesystem, 0 if local. * * Also Note: Upon exit, a valid fsys() is guaranteed. This is * an interface requirement. */ int is_remote_fs(char *path, uint32_t *fsys_value) { if (*fsys_value == BADFSYS) *fsys_value = fsys(path); return (is_remote_fs_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); }
/* * get_remote_path - given a filesystem table index, return the * path of the filesystem on the remote system. Otherwise, * return NULL if it's a local filesystem. */ char * get_remote_path(uint32_t n) { char *p; if (!is_remote_fs_n(n)) return (NULL); /* local */ p = strchr(fs_tab[n]->remote_name, ':'); if (!p) p = fs_tab[n]->remote_name; /* Loopback */ else p++; /* remote */ return (p); }
/* * 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); }