int swapcfile(PKGserver server, VFP_T **a_cfTmpVfp, char *pkginst, int dbchg) { char *pe; char *pl; char *ps; char line[256]; char timeb[BUFSIZ]; int retval = RESULT_OK; struct tm *timep; time_t clock; /* normalize pkginst so its never null */ if (pkginst == (char *)NULL) { dbchg = 0; pkginst = "<unknown>"; } /* * If no changes were made to the database, checkpoint the temporary * contents file - if this fails, then just close the file which causes * the contents file to be reopened and reread if it is needed again */ if ((dbchg == 0) && (vfpGetModified(*a_cfTmpVfp) == 0)) { (void) pkgWunlock(); /* Free the database lock. */ return (retval); } /* * changes made to the current temporary contents file - * remove any trailing comment lines in the temp contents file, then * append updated modification info records to temp contents file */ pe = vfpGetCurrCharPtr(*a_cfTmpVfp); /* last char in contents file */ ps = vfpGetFirstCharPtr(*a_cfTmpVfp); /* 1st char in contents file */ pl = pe; /* last match is last char in contents file */ /* skip past all trailing newlines and null bytes */ while ((pe > ps) && ((*pe == '\n') || (*pe == '\0'))) { pe--; } /* remove trailing comments as long as there are lines in the file */ while (pe > ps) { if (*pe != '\n') { /* curr char is not newline: backup one byte */ pl = pe--; } else if (*pl != '#') { /* curr char is newline next char not comment break */ break; } else { /* curr char is newline next char is comment - remove */ *pl = '\0'; vfpSetLastCharPtr(*a_cfTmpVfp, pl); pe--; } } /* create two update comment lines */ (void) time(&clock); timep = localtime(&clock); (void) strftime(timeb, sizeof (timeb), "%c\n", timep); (void) snprintf(line, sizeof (line), gettext("# Last modified by %s for %s package\n# %s"), get_prog_name(), pkginst, timeb); vfpPuts(*a_cfTmpVfp, line); /* commit temporary contents file bytes to storage */ if (pkgservercommitfile(*a_cfTmpVfp, server) != 0) { int lerrno = errno; logerr(gettext(ERR_COMMIT)); vfpClose(a_cfTmpVfp); pkgcloseserver(server); (void) pkgWunlock(); /* Free the database lock. */ return (RESULT_ERR); } return (relslock() == 0 ? RESULT_ERR : retval); }
int putcvfpfile(struct cfent *a_ept, VFP_T *a_vfp) { struct pinfo *pinfo; /* contents file does not maintain any 'i' file entries */ if (a_ept->ftype == 'i') { return (0); } /* cannot create an entry if it has no file name */ if (a_ept->path == NULL) { return (-1); } /* * Format of contents file line could be one of: * /file=./dir/file s class SUNWxxx * /file=../dir/file l class SUNWxxx * /dir d class mode owner group SUNWxxx SUNWyyy * /devices/name c class major minor mode owner group SUNWxxx * /file f class mode owner group size cksum modtime SUNWxxx * /file x class mode owner group SUNWppro * /file v class mode owner group size cksum modtime SUNWxxx * /file e class mode owner group size cksum modtime SUNWxxx * The package name could be prefixed by one of the following * status indicators: +-*!%@#~ */ /* * Adding an entry to the specified VFP. During normal processing the * contents file is copied to a temporary contents file and entries are * added as appropriate. When this processing is completed, a decision * is made on whether or not to overwrite the real contents file with * the contents of the temporary contents file. If the temporary * contents file is just a copy of the real contents file then there is * no need to overwrite the real contents file with the contents of the * temporary contents file. This decision is made in part on whether * or not any new or modified entries have been added to the temporary * contents file. Set the "data is modified" indication associated * with this VFP so that the real contents file is overwritten when * processing is done. */ (void) vfpSetModified(a_vfp); /* write initial path [all entries] */ vfpPuts(a_vfp, a_ept->path); /* if link, write out '=' portion */ if (a_ept->ainfo.local) { vfpPutc(a_vfp, '='); vfpPuts(a_vfp, a_ept->ainfo.local); } /* if volume, write it out */ if (a_ept->volno) { vfpPutc(a_vfp, ' '); vfpPutInteger(a_vfp, a_ept->volno); } /* write out <space><entry type><space>class> */ vfpPutc(a_vfp, ' '); vfpPutc(a_vfp, a_ept->ftype); vfpPutc(a_vfp, ' '); vfpPuts(a_vfp, a_ept->pkg_class); /* if char/block device, write out major/minor numbers */ if ((a_ept->ftype == 'c') || (a_ept->ftype == 'b')) { /* major device number */ if (a_ept->ainfo.major == BADMAJOR) { vfpPutc(a_vfp, ' '); vfpPutc(a_vfp, '?'); } else { vfpPutc(a_vfp, ' '); vfpPutInteger(a_vfp, a_ept->ainfo.major); } /* minor device number */ if (a_ept->ainfo.minor == BADMINOR) { vfpPutc(a_vfp, ' '); vfpPutc(a_vfp, '?'); } else { vfpPutc(a_vfp, ' '); vfpPutInteger(a_vfp, a_ept->ainfo.minor); } } /* if dxcbpfve, write out mode, owner, group */ if ((a_ept->ftype == 'd') || (a_ept->ftype == 'x') || (a_ept->ftype == 'c') || (a_ept->ftype == 'b') || (a_ept->ftype == 'p') || (a_ept->ftype == 'f') || (a_ept->ftype == 'v') || (a_ept->ftype == 'e')) { /* mode */ vfpPutFormat(a_vfp, ((a_ept->ainfo.mode == BADMODE) ? " ?" : " %04o"), a_ept->ainfo.mode); /* owner */ vfpPutc(a_vfp, ' '); vfpPuts(a_vfp, a_ept->ainfo.owner); /* group */ vfpPutc(a_vfp, ' '); vfpPuts(a_vfp, a_ept->ainfo.group); } /* if f/v/e, write out size, cksum, modtime */ if ((a_ept->ftype == 'f') || (a_ept->ftype == 'v') || (a_ept->ftype == 'e')) { /* size */ vfpPutFormat(a_vfp, ((a_ept->cinfo.size == BADCONT) ? " ?" : " %ld"), a_ept->cinfo.size); /* cksum */ vfpPutFormat(a_vfp, ((a_ept->cinfo.cksum == BADCONT) ? " ?" : " %ld"), a_ept->cinfo.cksum); /* modtime */ vfpPutFormat(a_vfp, ((a_ept->cinfo.modtime == BADCONT) ? " ?" : " %ld"), a_ept->cinfo.modtime); } /* write out list of all packages referencing this entry */ pinfo = a_ept->pinfo; while (pinfo) { vfpPutc(a_vfp, ' '); if (pinfo->status) { vfpPutc(a_vfp, pinfo->status); } vfpPuts(a_vfp, pinfo->pkg); if (pinfo->editflag) { vfpPutc(a_vfp, '\\'); } if (pinfo->aclass[0]) { vfpPutc(a_vfp, ':'); vfpPuts(a_vfp, pinfo->aclass); } pinfo = pinfo->next; } vfpPutc(a_vfp, '\n'); return (0); }