/** * Adjusts the current volume and sends a notification (if enabled). * * @param vol new volume value * @param dir select direction (-1 = accurate or first bellow, 0 = accurate, * 1 = accurate or first above) * @param notify whether to send notification * @return 0 on success otherwise negative error code */ int setvol(int vol, int dir, gboolean notify) { long min = 0, max = 0, value; int cur_perc = getvol(); double dvol = 0.01 * vol; int err = snd_mixer_selem_get_playback_dB_range(elem, &min, &max); if (err < 0 || min >= max || !normalize_vol()) { err = snd_mixer_selem_get_playback_volume_range(elem, &min, &max); value = lrint_dir(dvol * (max - min), dir) + min; snd_mixer_selem_set_playback_volume_all(elem, value); if (enable_noti && notify && cur_perc != getvol()) do_notify_volume(getvol(), FALSE); // intentionally set twice return snd_mixer_selem_set_playback_volume_all(elem, value); } if (use_linear_dB_scale(min, max)) { value = lrint_dir(dvol * (max - min), dir) + min; return snd_mixer_selem_set_playback_dB_all(elem, value, dir); } if (min != SND_CTL_TLV_DB_GAIN_MUTE) { double min_norm = exp10((min - max) / 6000.0); dvol = dvol * (1 - min_norm) + min_norm; } value = lrint_dir(6000.0 * log10(dvol), dir) + max; snd_mixer_selem_set_playback_dB_all(elem, value, dir); if (enable_noti && notify && cur_perc != getvol()) do_notify_volume(getvol(), FALSE); // intentionally set twice return snd_mixer_selem_set_playback_dB_all(elem, value, dir); }
/** * Mutes or unmutes playback and sends a notification (if enabled). * * @param notify whether to send notification */ void setmute(gboolean notify) { if (!snd_mixer_selem_has_playback_switch(elem)) return; if (ismuted()) { snd_mixer_selem_set_playback_switch_all(elem, 0); if (enable_noti && notify) do_notify_volume(getvol(), TRUE); } else { snd_mixer_selem_set_playback_switch_all(elem, 1); if (enable_noti && notify) do_notify_volume(getvol(), FALSE); } }
/* * NAME: hfs->vsetattr() * DESCRIPTION: change volume attributes */ int hfs_vsetattr(hfsvol *vol, hfsvolent *ent) { if (getvol(&vol) == -1) goto fail; if (ent->clumpsz % vol->mdb.drAlBlkSiz != 0) ERROR(EINVAL, "illegal clump size"); /* make sure "blessed" folder exists */ if (ent->blessed && v_getdthread(vol, ent->blessed, 0, 0) <= 0) ERROR(EINVAL, "illegal blessed folder"); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); vol->mdb.drClpSiz = ent->clumpsz; vol->mdb.drCrDate = d_mtime(ent->crdate); vol->mdb.drLsMod = d_mtime(ent->mddate); vol->mdb.drVolBkUp = d_mtime(ent->bkdate); vol->mdb.drFndrInfo[0] = ent->blessed; vol->flags |= HFS_VOL_UPDATE_MDB; return 0; fail: return -1; }
/** * Callback function for the mixer element which is * set in alsaset(). * * @param e mixer element * @param mask event mask * @return 0 on success otherwise a negative error code */ static int alsa_cb(snd_mixer_elem_t *e, unsigned int mask) { /* Test MASK_REMOVE first, according to Alsa documentation */ if (mask == SND_CTL_EVENT_MASK_REMOVE) { return 0; } /* Then check if mixer value changed */ if (mask & SND_CTL_EVENT_MASK_VALUE) { int muted; get_current_levels(); muted = ismuted(); on_volume_has_changed(); if (enable_noti && external_noti) { int vol = getvol(); if (muted) do_notify_volume(vol, FALSE); else do_notify_volume(vol, TRUE); } } return 0; }
/* * NAME: hfs->isopen() * DESCRIPTION: check if a file is open * RETURNS: */ int hfs_isopen(hfsvol *vol, const char *path) { hfsfile *file = 0; hfsfile *f = 0; if (getvol(&vol) == -1) ERROR(ENODEV, 0); file = ALLOC(hfsfile, 1); if (file == 0) ERROR(ENOMEM, 0); if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0) ERROR(ENOENT, 0); if (file->cat.cdrType != cdrFilRec) ERROR(EISDIR, 0); // see if it's already open ULongInt num = file->cat.u.fil.filFlNum; FREE(file); for(f = vol->files; f; f = f->next) { if (f->cat.u.fil.filFlNum == num) return 1; } return 0; fail: FREE(file); return -1; }
/* * NAME: hfs->mkdir() * DESCRIPTION: create a new directory */ int hfs_mkdir(hfsvol *vol, const char *path) { CatDataRec data; unsigned long parid; char name[HFS_MAX_FLEN + 1]; int found; if (getvol(&vol) == -1) goto fail; found = v_resolve(&vol, path, &data, &parid, name, 0); if (found == -1 || parid == 0) goto fail; if (found) ERROR(EEXIST, 0); if (parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); return v_mkdir(vol, parid, name); fail: return -1; }
int volume() { int ret, vol; char cmd[MAXLEN]; char buf[MAXLEN]=""; vol=getvol(); if(vol==-1) return -1; sprintf(cmd, "AT*EAID=4,1,\"Volume\",10,%d\r", (int) ((vol/10.0)+.5)); writeport(cmd, strlen(cmd)); if(waitfor("OK", 1, TIMEOUT) != 1) return -1; while(1) { while((ret = readport(buf, MAXLEN, TIMEOUT)) == -EINTR); if(ret <= 0) return -1; if(strncmp(buf, "*EAII: 15,",10)==0) setvol(atoi(buf+10)); if(strncmp(buf, "*EAII: 0", 8)==0 || strncmp(buf, "*EAAI", 5)==0) { setvol(vol); return 0; } if(strncmp(buf, "*EAII: 4,",9)==0) { setvol(atoi(buf+9)); return 1; } } }
/* * NAME: hfs->vstat() * DESCRIPTION: return volume statistics */ int hfs_vstat(hfsvol *vol, hfsvolent *ent) { if (getvol(&vol) == -1) goto fail; strcpy(ent->name, vol->mdb.drVN); ent->flags = (vol->flags & HFS_VOL_READONLY) ? HFS_ISLOCKED : 0; ent->totbytes = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz; ent->freebytes = vol->mdb.drFreeBks * vol->mdb.drAlBlkSiz; ent->alblocksz = vol->mdb.drAlBlkSiz; ent->clumpsz = vol->mdb.drClpSiz; ent->numfiles = vol->mdb.drFilCnt; ent->numdirs = vol->mdb.drDirCnt; ent->crdate = d_ltime(vol->mdb.drCrDate); ent->mddate = d_ltime(vol->mdb.drLsMod); ent->bkdate = d_ltime(vol->mdb.drVolBkUp); ent->blessed = vol->mdb.drFndrInfo[0]; return 0; fail: return -1; }
/* * NAME: hfs->getcwd() * DESCRIPTION: return the current working directory ID */ unsigned long hfs_getcwd(hfsvol *vol) { if (getvol(&vol) == -1) return 0; return vol->cwd; }
int main(void) { char status[100]; int l = 0; if (!(dpy = XOpenDisplay(NULL))) { fprintf(stderr, "Cannot open display.\n"); return 1; } for (;;sleep(2)) { l = getcpu(status, sizeof(status)); l += gettemp(status + l, sizeof(status) - l); l += getmem(status + l, sizeof(status) - l); l += getnetwork(status + l, sizeof(status) - l); l += getbattery(status + l, sizeof(status) - l); l += getvol(status + l, sizeof(status) - l); l += getdatetime(status + l, sizeof(status) - l); setstatus(status); } free(status); XCloseDisplay(dpy); return 0; }
/* * NAME: hfs->opendir() * DESCRIPTION: prepare to read the contents of a directory */ hfsdir *hfs_opendir(hfsvol *vol, const char *path) { hfsdir *dir = 0; CatKeyRec key; CatDataRec data; byte pkey[HFS_CATKEYLEN]; if (getvol(&vol) == -1) goto fail; dir = ALLOC(hfsdir, 1); if (dir == 0) ERROR(ENOMEM, 0); dir->vol = vol; if (*path == 0) { #ifdef CP_NO_STATIC /* meta-directory containing root dirs from all mounted volumes */ dir->dirid = 0; dir->vptr = hfs_mounts; #else assert(0); #endif } else { if (v_resolve(&vol, path, &data, 0, 0, 0) <= 0) goto fail; if (data.cdrType != cdrDirRec) ERROR(ENOTDIR, 0); dir->dirid = data.u.dir.dirDirID; dir->vptr = 0; r_makecatkey(&key, dir->dirid, ""); r_packcatkey(&key, pkey, 0); if (bt_search(&vol->cat, pkey, &dir->n) <= 0) goto fail; } dir->prev = 0; dir->next = vol->dirs; if (vol->dirs) vol->dirs->prev = dir; vol->dirs = dir; return dir; fail: FREE(dir); return 0; }
/* * NAME: hfs->umount() * DESCRIPTION: close an HFS volume */ int hfs_umount(hfsvol *vol) { int result = 0; if (getvol(&vol) == -1) goto fail; if (--vol->refs) { result = v_flush(vol); goto done; } /* close all open files and directories */ while (vol->files) { if (hfs_close(vol->files) == -1) result = -1; } while (vol->dirs) { if (hfs_closedir(vol->dirs) == -1) result = -1; } /* close medium */ if (v_close(vol) == -1) result = -1; /* remove from linked list of volumes */ if (vol->prev) vol->prev->next = vol->next; if (vol->next) vol->next->prev = vol->prev; if (vol == hfs_mounts) hfs_mounts = vol->next; if (vol == curvol) curvol = 0; FREE(vol); done: return result; fail: return -1; }
/* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */ hfsfile *hfs_open(hfsvol *vol, const char *path) { hfsfile *file = 0; hfsfile *f = 0; if (getvol(&vol) == -1) ERROR(ENODEV, 0); file = ALLOC(hfsfile, 1); if (file == 0) ERROR(ENOMEM, 0); if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0) ERROR(ENOENT, 0); if (file->cat.cdrType != cdrFilRec) ERROR(EISDIR, 0); // see if it's already open for(f = vol->files; f; f = f->next) { if (f->cat.u.fil.filFlNum == file->cat.u.fil.filFlNum) { // already open, increment refcount and return FREE(file); file = f; file->refs++; printf("REOPEN: file %s now has %d refs\n", path, file->refs); return file; } } /* package file handle for user */ file->refs = 1; file->vol = vol; file->flags = 0; f_selectfork(file, fkData); file->prev = 0; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; fail: FREE(file); return 0; }
void incvol(const Arg *arg) { long min, max; snd_mixer_elem_t* elem = getelem(alsachannel); snd_mixer_selem_get_playback_volume_range(elem, &min, &max); int delta = (arg->i*(max-min))/100; long vol = getvol(elem); int newvol = vol+delta; if (newvol < min) newvol = min; if (newvol > max) newvol = max; setvol(newvol, elem); }
/* * NAME: hfs->stat() * DESCRIPTION: return catalog information for an arbitrary path */ int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent) { CatDataRec data; unsigned long parid; char name[HFS_MAX_FLEN + 1]; if (getvol(&vol) == -1 || v_resolve(&vol, path, &data, &parid, name, NULL) <= 0) goto fail; r_unpackdirent(parid, name, &data, ent); return 0; fail: return -1; }
/* * NAME: hfs->rmdir() * DESCRIPTION: delete an empty directory */ int hfs_rmdir(hfsvol *vol, const char *path) { CatKeyRec key; CatDataRec data; unsigned long parid; char name[HFS_MAX_FLEN + 1]; byte pkey[HFS_CATKEYLEN]; if (getvol(&vol) == -1 || v_resolve(&vol, path, &data, &parid, name, 0) <= 0) goto fail; if (data.cdrType != cdrDirRec) ERROR(ENOTDIR, 0); if (data.u.dir.dirVal != 0) ERROR(ENOTEMPTY, 0); if (parid == HFS_CNID_ROOTPAR) ERROR(EINVAL, 0); if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); /* delete directory record */ r_makecatkey(&key, parid, name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1) goto fail; /* delete thread record */ r_makecatkey(&key, data.u.dir.dirDirID, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) == -1 || v_adjvalence(vol, parid, 1, -1) == -1) goto fail; return 0; fail: return -1; }
/* * NAME: hfs->dirinfo() * DESCRIPTION: given a directory ID, return its (name and) parent ID */ int hfs_dirinfo(hfsvol *vol, unsigned long *id, char *name) { CatDataRec thread; if (getvol(&vol) == -1 || v_getdthread(vol, *id, &thread, NULL) <= 0) goto fail; *id = thread.u.dthd.thdParID; if (name) strcpy(name, thread.u.dthd.thdCName); return 0; fail: return -1; }
/* * NAME: hfs->chdir() * DESCRIPTION: change current HFS directory */ int hfs_chdir(hfsvol *vol, const char *path) { CatDataRec data; if (getvol(&vol) == -1 || v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0) goto fail; if (data.cdrType != cdrDirRec) ERROR(ENOTDIR, NULL); vol->cwd = data.u.dir.dirDirID; return 0; fail: return -1; }
/* * NAME: hfs->setattr() * DESCRIPTION: change a file's attributes */ int hfs_setattr(hfsvol *vol, const char *path, const hfsdirent *ent) { CatDataRec data; node n; if (getvol(&vol) == -1 || v_resolve(&vol, path, &data, 0, 0, &n) <= 0) goto fail; if (vol->flags & HFS_VOL_READONLY) ERROR(EROFS, 0); r_packdirent(&data, ent); return v_putcatrec(&data, &n); fail: return -1; }
/** * Updates the tray icon. Usually called after volume has been muted * or changed. */ void update_tray_icon(void) { int muted; int tmpvol = getvol(); char tooltip[60]; gchar *active_card_name = (alsa_get_active_card())->name; const char *active_channel = alsa_get_active_channel(); muted = ismuted(); if (muted == 1) { GdkPixbuf *icon; if (tmpvol == 0) icon = status_icons[VOLUME_OFF]; else if (tmpvol < 33) icon = status_icons[VOLUME_LOW]; else if (tmpvol < 66) icon = status_icons[VOLUME_MEDIUM]; else icon = status_icons[VOLUME_HIGH]; sprintf(tooltip, _("%s (%s)\nVolume: %d %%"), active_card_name, active_channel, tmpvol); if (vol_meter_row) { GdkPixbuf *old_icon = icon_copy; icon_copy = gdk_pixbuf_copy(icon); draw_vol_meter(icon_copy, draw_offset, 5, (tmpvol * vol_div_factor)); if (old_icon) g_object_unref(old_icon); gtk_status_icon_set_from_pixbuf(tray_icon, icon_copy); } else gtk_status_icon_set_from_pixbuf(tray_icon, icon); } else { gtk_status_icon_set_from_pixbuf(tray_icon, status_icons[VOLUME_MUTED]); sprintf(tooltip, _("%s (%s)\nVolume: %d %%\nMuted"), active_card_name, active_channel, tmpvol); } gtk_status_icon_set_tooltip_text(tray_icon, tooltip); }
/** * This function is called before gdk/gtk can respond * to any(!) window event and handles pressed hotkeys. * * @param gdk_xevent the native event to filter * @param event the GDK event to which the X event will be translated * @param data user data set when the filter was installed * @return a GdkFilterReturn value, should be GDK_FILTER_CONTINUE only */ static GdkFilterReturn key_filter(GdkXEvent *gdk_xevent, G_GNUC_UNUSED GdkEvent *event, G_GNUC_UNUSED gpointer data) { int type; guint key, state; XKeyEvent *xevent; //gboolean bResult; xevent = gdk_xevent; type = xevent->type; if (type == KeyPress) { key = ((XKeyEvent *) xevent)->keycode; state = ((XKeyEvent *) xevent)->state; if ((int) key == volMuteKey && checkModKey(state, volMuteMods)) { setmute(enable_noti && hotkey_noti); on_volume_has_changed(); return GDK_FILTER_CONTINUE; } else { int cv = getvol(); if ((int) key == volUpKey && checkModKey(state, volUpMods)) { setvol(cv + volStep, 1, enable_noti && hotkey_noti); } else if ((int) key == volDownKey && checkModKey(state, volDownMods)) { setvol(cv - volStep, -1, enable_noti && hotkey_noti); } // just ignore unknown hotkeys if (ismuted() == 0) setmute(enable_noti && hotkey_noti); on_volume_has_changed(); // this will set the slider value get_current_levels(); } } return GDK_FILTER_CONTINUE; }
/* * NAME: hfs->setcwd() * DESCRIPTION: set the current working directory ID */ int hfs_setcwd(hfsvol *vol, unsigned long id) { if (getvol(&vol) == -1) goto fail; if (id == vol->cwd) goto done; /* make sure the directory exists */ if (v_getdthread(vol, id, NULL, NULL) <= 0) goto fail; vol->cwd = id; done: return 0; fail: return -1; }
/* * NAME: hfs->flush() * DESCRIPTION: flush all pending changes to an HFS volume */ int hfs_flush(hfsvol *vol) { hfsfile *file; if (getvol(&vol) == -1) goto fail; for (file = vol->files; file; file = file->next) { if (f_flush(file) == -1) goto fail; } if (v_flush(vol) == -1) goto fail; return 0; fail: return -1; }
/* * NAME: hfs->callback_close() * DESCRIPTION: close an HFS volume */ int hfs_callback_close(hfsvol *vol) { int result = 0; if (getvol(&vol) == -1) goto fail; if (--vol->refs) { result = v_flush(vol); goto done; } /* close all open files and directories */ while (vol->files) { if (hfs_close(vol->files) == -1) result = -1; } while (vol->dirs) { if (hfs_closedir(vol->dirs) == -1) result = -1; } /* close medium */ if (v_close(vol) == -1) result = -1; FREE(vol); done: return result; fail: return -1; }
static GdkFilterReturn key_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { int type; unsigned int key,state; XKeyEvent *xevent; //gboolean bResult; xevent = gdk_xevent; type = xevent->type; if (type == KeyPress) { key = ((XKeyEvent *)xevent)->keycode; state = ((XKeyEvent *)xevent)->state; if (key == volMuteKey && state == volMuteMods) { setmute(enable_noti&&hotkey_noti); get_mute_state(TRUE); return GDK_FILTER_CONTINUE; } else { int cv = getvol(); if (key == volUpKey && state == volUpMods) { setvol(cv+volStep,enable_noti&&hotkey_noti); } else if (key == volDownKey && state == volDownMods) { setvol(cv-volStep,enable_noti&&hotkey_noti); } // just ignore unknown hotkeys if (get_mute_state(TRUE) == 0) setmute(enable_noti&&hotkey_noti); // this will set the slider value get_current_levels(); } } return GDK_FILTER_CONTINUE; }
/* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */ hfsfile *hfs_open(hfsvol *vol, const char *path) { hfsfile *file = NULL; if (getvol(&vol) == -1) goto fail; file = ALLOC(hfsfile, 1); if (file == NULL) ERROR(ENOMEM, NULL); if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0) goto fail; if (file->cat.cdrType != cdrFilRec) ERROR(EISDIR, NULL); /* package file handle for user */ file->vol = vol; file->flags = 0; f_selectfork(file, fkData); file->prev = NULL; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file; fail: FREE(file); return NULL; }
/** * Checks whether playback is muted, updates the icon * and returns the result of ismuted(). * * @param set_check whether the GtkCheckButton 'Mute' on the * volume popup_window is updated * @return result of ismuted() */ int get_mute_state(gboolean set_check) { int muted; int tmpvol = getvol(); char tooltip [60]; muted = ismuted(); if( muted == 1 ) { GdkPixbuf *icon; if (set_check) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_check), FALSE); if (tmpvol < 33) icon = status_icons[1]; else if (tmpvol < 66) icon = status_icons[2]; else icon = status_icons[3]; sprintf(tooltip, _("Volume: %d %%"), tmpvol); if (vol_meter_row) { GdkPixbuf* old_icon = icon_copy; icon_copy = gdk_pixbuf_copy(icon); draw_vol_meter(icon_copy,draw_offset,5,(tmpvol*vol_div_factor)); if (old_icon) g_object_unref(old_icon); gtk_status_icon_set_from_pixbuf(tray_icon, icon_copy); } else gtk_status_icon_set_from_pixbuf(tray_icon, icon); } else { if (set_check) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_check), TRUE); gtk_status_icon_set_from_pixbuf(tray_icon, status_icons[0]); sprintf(tooltip, _("Volume: %d %%\nMuted"), tmpvol); } gtk_status_icon_set_tooltip_text(tray_icon, tooltip); return muted; }
/* * Find an inode header. * Complain if had to skip. */ static void findinode(struct s_spcl *header) { static long skipcnt = 0; long i; char buf[TP_BSIZE]; int htype; curfile.name = "<name unknown>"; curfile.action = UNKNOWN; curfile.mode = 0; curfile.ino = 0; do { htype = header->c_type; switch (htype) { case TS_ADDR: /* * Skip up to the beginning of the next record */ for (i = 0; i < header->c_count; i++) if (header->c_addr[i]) readtape(buf); while (gethead(header) == FAIL || _time64_to_time(header->c_date) != dumpdate) { skipcnt++; if (Dflag) { byteslide++; if (byteslide < TP_BSIZE) { blkcnt--; blksread--; } else byteslide = 0; } } break; case TS_INODE: curfile.mode = header->c_mode; curfile.uid = header->c_uid; curfile.gid = header->c_gid; curfile.file_flags = header->c_file_flags; curfile.rdev = header->c_rdev; curfile.atime_sec = header->c_atime; curfile.atime_nsec = header->c_atimensec; curfile.mtime_sec = header->c_mtime; curfile.mtime_nsec = header->c_mtimensec; curfile.birthtime_sec = header->c_birthtime; curfile.birthtime_nsec = header->c_birthtimensec; curfile.extsize = header->c_extsize; curfile.size = header->c_size; curfile.ino = header->c_inumber; break; case TS_END: /* If we missed some tapes, get another volume. */ if (tapesread & (tapesread + 1)) { getvol(0); continue; } curfile.ino = maxino; break; case TS_CLRI: curfile.name = "<file removal list>"; break; case TS_BITS: curfile.name = "<file dump list>"; break; case TS_TAPE: if (Dflag) fprintf(stderr, "unexpected tape header\n"); else panic("unexpected tape header\n"); default: if (Dflag) fprintf(stderr, "unknown tape header type %d\n", spcl.c_type); else panic("unknown tape header type %d\n", spcl.c_type); while (gethead(header) == FAIL || _time64_to_time(header->c_date) != dumpdate) { skipcnt++; if (Dflag) { byteslide++; if (byteslide < TP_BSIZE) { blkcnt--; blksread--; } else byteslide = 0; } } } } while (htype == TS_ADDR); if (skipcnt > 0) fprintf(stderr, "resync restore, skipped %ld %s\n", skipcnt, Dflag ? "bytes" : "blocks"); skipcnt = 0; }
/* * Read TP_BSIZE blocks from the input. * Handle read errors, and end of media. */ static void readtape(char *buf) { long rd, newvol, i, oldnumtrec; int cnt, seek_failed; if (blkcnt + (byteslide > 0) < numtrec) { memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); blksread++; tapeaddr++; return; } if (numtrec > 0) memmove(&tapebuf[-TP_BSIZE], &tapebuf[(numtrec-1) * TP_BSIZE], (long)TP_BSIZE); oldnumtrec = numtrec; for (i = 0; i < ntrec; i++) ((struct s_spcl *)&tapebuf[i * TP_BSIZE])->c_magic = 0; if (numtrec == 0) numtrec = ntrec; cnt = ntrec * TP_BSIZE; rd = 0; getmore: #ifdef RRESTORE if (host) i = rmtread(&tapebuf[rd], cnt); else #endif i = read(mt, &tapebuf[rd], cnt); /* * Check for mid-tape short read error. * If found, skip rest of buffer and start with the next. */ if (!pipein && !pipecmdin && numtrec < ntrec && i > 0) { dprintf(stdout, "mid-media short read error.\n"); numtrec = ntrec; } /* * Handle partial block read. */ if ((pipein || pipecmdin) && i == 0 && rd > 0) i = rd; else if (i > 0 && i != ntrec * TP_BSIZE) { if (pipein || pipecmdin) { rd += i; cnt -= i; if (cnt > 0) goto getmore; i = rd; } else { /* * Short read. Process the blocks read. */ if (i % TP_BSIZE != 0) vprintf(stdout, "partial block read: %ld should be %ld\n", i, ntrec * TP_BSIZE); numtrec = i / TP_BSIZE; } } /* * Handle read error. */ if (i < 0) { fprintf(stderr, "Tape read error while "); switch (curfile.action) { default: fprintf(stderr, "trying to set up tape\n"); break; case UNKNOWN: fprintf(stderr, "trying to resynchronize\n"); break; case USING: fprintf(stderr, "restoring %s\n", curfile.name); break; case SKIP: fprintf(stderr, "skipping over inode %ju\n", (uintmax_t)curfile.ino); break; } if (!yflag && !reply("continue")) done(1); i = ntrec * TP_BSIZE; memset(tapebuf, 0, i); #ifdef RRESTORE if (host) seek_failed = (rmtseek(i, 1) < 0); else #endif seek_failed = (lseek(mt, i, SEEK_CUR) == (off_t)-1); if (seek_failed) { fprintf(stderr, "continuation failed: %s\n", strerror(errno)); done(1); } } /* * Handle end of tape. */ if (i == 0) { vprintf(stdout, "End-of-tape encountered\n"); if (!pipein) { newvol = volno + 1; volno = 0; numtrec = 0; getvol(newvol); readtape(buf); return; } if (rd % TP_BSIZE != 0) panic("partial block read: %ld should be %ld\n", rd, ntrec * TP_BSIZE); terminateinput(); memmove(&tapebuf[rd], &endoftapemark, (long)TP_BSIZE); } if (oldnumtrec == 0) blkcnt = 0; else blkcnt -= oldnumtrec; memmove(buf, &tapebuf[(blkcnt++ * TP_BSIZE) + byteslide], (long)TP_BSIZE); blksread++; tapeaddr++; }
static int pkgxfer(char *srcinst, int options) { int r; struct pkginfo info; FILE *fp, *pp; char *pt, *src, *dst; char dstdir[PATH_MAX], temp[PATH_MAX], srcdir[PATH_MAX], cmd[CMDSIZE], pkgname[NON_ABI_NAMELNGTH]; int i, n, part, nparts, maxpartsize, curpartcnt, iscomp; char volnos[128], tmpvol[128]; struct statvfs64 svfsb; longlong_t free_blocks; struct stat srcstat; info.pkginst = NULL; /* required initialization */ /* * when this routine is entered, the first part of * the package to transfer is already available in * the directory indicated by 'src' --- unless the * source device is a datstream, in which case only * the pkginfo and pkgmap files are available in 'src' */ src = srcdev.dirname; dst = dstdev.dirname; if (!(options & PT_SILENT)) (void) fprintf(stderr, pkg_gt(MSG_TRANSFER), srcinst); (void) strlcpy(dstinst, srcinst, sizeof (dstinst)); if (!(options & PT_ODTSTREAM)) { /* destination is a (possibly mounted) directory */ (void) snprintf(dstdir, sizeof (dstdir), "%s/%s", dst, dstinst); /* * need to check destination directory to assure * that we will not be duplicating a package which * already resides there (though we are allowed to * overwrite the same version) */ pkgdir = src; if (fpkginfo(&info, srcinst)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_NOEXISTS), srcinst); (void) fpkginfo(&info, NULL); return (1); } pkgdir = dst; (void) strlcpy(temp, srcinst, sizeof (temp)); if (pt = strchr(temp, '.')) *pt = '\0'; (void) strlcat(temp, ".*", sizeof (temp)); if (pt = fpkginst(temp, info.arch, info.version)) { /* * the same instance already exists, although * its pkgid might be different */ if (options & PT_OVERWRITE) { (void) strlcpy(dstinst, pt, sizeof (dstinst)); (void) snprintf(dstdir, sizeof (dstdir), "%s/%s", dst, dstinst); } else { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_DUPVERS), srcinst); (void) fpkginfo(&info, NULL); (void) fpkginst(NULL); return (2); } } else if (options & PT_RENAME) { /* * find next available instance by appending numbers * to the package abbreviation until the instance * does not exist in the destination directory */ if (pt = strchr(temp, '.')) *pt = '\0'; for (i = 2; (access(dstdir, 0) == 0); i++) { (void) snprintf(dstinst, sizeof (dstinst), "%s.%d", temp, i); (void) snprintf(dstdir, sizeof (dstdir), "%s/%s", dst, dstinst); } } else if (options & PT_OVERWRITE) { /* * we're allowed to overwrite, but there seems * to be no valid package to overwrite, and we are * not allowed to rename the destination, so act * as if we weren't given permission to overwrite * --- this keeps us from removing a destination * instance which is named the same as the source * instance, but really reflects a different pkg! */ options &= (~PT_OVERWRITE); } (void) fpkginfo(&info, NULL); (void) fpkginst(NULL); if (ckoverwrite(dst, dstinst, options)) return (2); if (isdir(dstdir) && mkdir(dstdir, 0755)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_MKDIR), dstdir); return (1); } (void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst); if (stat(srcdir, &srcstat) != -1) { if (chmod(dstdir, (srcstat.st_mode & S_IAMB)) == -1) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHMODDIR), dstdir); return (1); } } else { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_STATDIR), srcdir); return (1); } } if (!(options & PT_SILENT) && strcmp(dstinst, srcinst)) (void) fprintf(stderr, pkg_gt(MSG_RENAME), dstinst); (void) snprintf(srcdir, sizeof (srcdir), "%s/%s", src, srcinst); if (chdir(srcdir)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHDIR), srcdir); return (1); } if (ids_name) { /* unpack the datatstream into a directory */ /* * transfer pkginfo & pkgmap first */ (void) snprintf(cmd, sizeof (cmd), "%s -pudm %s", CPIOPROC, dstdir); if ((pp = epopen(cmd, "w")) == NULL) { rpterr(); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_POPEN), cmd, errno); return (1); } (void) fprintf(pp, "%s\n%s\n", PKGINFO, PKGMAP); (void) sighold(SIGINT); (void) sighold(SIGHUP); r = epclose(pp); (void) sigrelse(SIGINT); (void) sigrelse(SIGHUP); if (r != 0) { rpterr(); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_PCLOSE), cmd, errno); return (1); } if (options & PT_INFO_ONLY) return (0); /* don't transfer objects */ if (chdir(dstdir)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHDIR), dstdir); return (1); } /* * for each part of the package, use cpio() to * unpack the archive into the destination directory */ nparts = ds_findpkg(srcdev.cdevice, srcinst); if (nparts < 0) { progerr(pkg_gt(ERR_TRANSFER)); return (1); } for (part = 1; part <= nparts; /* void */) { if (ds_getpkg(srcdev.cdevice, part, dstdir)) { progerr(pkg_gt(ERR_TRANSFER)); return (1); } part++; if (dstdev.mount) { (void) chdir("/"); if (pkgumount(&dstdev)) return (1); if (part <= nparts) { if (n = pkgmount(&dstdev, NULL, part+1, nparts, 1)) return (n); if (ckoverwrite(dst, dstinst, options)) return (1); if (isdir(dstdir) && mkdir(dstdir, 0755)) { progerr( pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_MKDIR), dstdir); return (1); } /* * since volume is removable, each part * must contain a duplicate of the * pkginfo file to properly identify the * volume */ if (chdir(srcdir)) { progerr( pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHDIR), srcdir); return (1); } if ((pp = epopen(cmd, "w")) == NULL) { rpterr(); progerr( pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_POPEN), cmd, errno); return (1); } (void) fprintf(pp, "pkginfo"); (void) sighold(SIGINT); (void) sighold(SIGHUP); r = epclose(pp); (void) sigrelse(SIGINT); (void) sigrelse(SIGHUP); if (r != 0) { rpterr(); progerr( pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_PCLOSE), cmd, errno); return (1); } if (chdir(dstdir)) { progerr( pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CHDIR), dstdir); return (1); } } } } return (0); } if ((fp = fopen(PKGMAP, "r")) == NULL) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_NOPKGMAP), srcinst); return (1); } nparts = 1; if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize)) return (1); else (void) fclose(fp); if (srcdev.mount) { if (ckvolseq(srcdir, 1, nparts)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_SEQUENCE)); return (1); } } /* write each part of this package */ if (options & PT_ODTSTREAM) { char line[128]; (void) mgets(line, 128); curpartcnt = -1; /* LINTED E_SEC_SCANF_UNBOUNDED_COPY */ if (sscanf(line, "%s %d %d %[ 0-9]", pkgname, &nparts, &maxpartsize, volnos) == 4) { (void) sscanf(volnos, "%d %[ 0-9]", &curpartcnt, tmpvol); (void) strlcpy(volnos, tmpvol, sizeof (volnos)); } } for (part = 1; part <= nparts; /* void */) { if (curpartcnt == 0 && (options & PT_ODTSTREAM)) { char prompt[128]; int index; ds_volno++; (void) ds_close(0); (void) sprintf(prompt, pkg_gt("Insert %%v %d of %d into %%p"), ds_volno, ds_volcnt); if (n = getvol(ods_name, NULL, DM_FORMAT, prompt)) return (n); if ((ds_fd = open(dstdev.cdevice, O_WRONLY)) < 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_OPEN), dstdev.cdevice, errno); return (1); } if (ds_ginit(dstdev.cdevice) < 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_OPEN), dstdev.cdevice, errno); (void) ds_close(0); return (1); } (void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol); (void) strlcpy(volnos, tmpvol, sizeof (volnos)); curpartcnt += index; } if (options & PT_INFO_ONLY) nparts = 0; if (part == 1) { (void) snprintf(cmd, sizeof (cmd), "find %s %s", PKGINFO, PKGMAP); if (nparts && (isdir(INSTALL) == 0)) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, INSTALL, sizeof (cmd)); } } else (void) snprintf(cmd, sizeof (cmd), "find %s", PKGINFO); if (nparts > 1) { (void) snprintf(temp, sizeof (temp), "%s.%d", RELOC, part); if (iscpio(temp, &iscomp) || isdir(temp) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, temp, sizeof (cmd)); } (void) snprintf(temp, sizeof (temp), "%s.%d", ROOT, part); if (iscpio(temp, &iscomp) || isdir(temp) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, temp, sizeof (cmd)); } (void) snprintf(temp, sizeof (temp), "%s.%d", ARCHIVE, part); if (isdir(temp) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, temp, sizeof (cmd)); } } else if (nparts) { for (i = 0; reloc_names[i] != NULL; i++) { if (iscpio(reloc_names[i], &iscomp) || isdir(reloc_names[i]) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, reloc_names[i], sizeof (cmd)); } } for (i = 0; root_names[i] != NULL; i++) { if (iscpio(root_names[i], &iscomp) || isdir(root_names[i]) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, root_names[i], sizeof (cmd)); } } if (isdir(ARCHIVE) == 0) { (void) strlcat(cmd, " ", sizeof (cmd)); (void) strlcat(cmd, ARCHIVE, sizeof (cmd)); } } if (options & PT_ODTSTREAM) { (void) snprintf(cmd + strlen(cmd), sizeof (cmd) - strlen(cmd), " -print | %s -ocD -C %d", CPIOPROC, (int)BLK_SIZE); } else { if (statvfs64(dstdir, &svfsb) == -1) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_STATVFS), dstdir, errno); return (1); } free_blocks = (((long)svfsb.f_frsize > 0) ? howmany(svfsb.f_frsize, DEV_BSIZE) : howmany(svfsb.f_bsize, DEV_BSIZE)) * svfsb.f_bavail; if ((has_comp_size ? compressedsize : maxpartsize) > free_blocks) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_NOSPACE), has_comp_size ? (long)compressedsize : (long)maxpartsize, free_blocks); return (1); } (void) snprintf(cmd + strlen(cmd), sizeof (cmd) - strlen(cmd), " -print | %s -pdum %s", CPIOPROC, dstdir); } n = esystem(cmd, -1, (options & PT_ODTSTREAM) ? ds_fd : -1); if (n) { rpterr(); progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CMDFAIL), cmd, n); return (1); } part++; if (srcdev.mount && (nparts > 1)) { /* unmount current source volume */ (void) chdir("/"); if (pkgumount(&srcdev)) return (1); /* loop until volume is mounted successfully */ while (part <= nparts) { /* read only */ n = pkgmount(&srcdev, NULL, part, nparts, 1); if (n) return (n); if (chdir(srcdir)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_CORRUPT)); (void) chdir("/"); (void) pkgumount(&srcdev); continue; } if (ckvolseq(srcdir, part, nparts)) { (void) chdir("/"); (void) pkgumount(&srcdev); continue; } break; } } if (!(options & PT_ODTSTREAM) && dstdev.mount) { /* unmount current volume */ if (pkgumount(&dstdev)) return (1); /* loop until next volume is mounted successfully */ while (part <= nparts) { /* writable */ n = pkgmount(&dstdev, NULL, part, nparts, 1); if (n) return (n); if (ckoverwrite(dst, dstinst, options)) continue; if (isdir(dstdir) && mkdir(dstdir, 0755)) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_MKDIR), dstdir); continue; } break; } } if ((options & PT_ODTSTREAM) && part <= nparts) { if (curpartcnt >= 0 && part > curpartcnt) { char prompt[128]; int index; ds_volno++; if (ds_close(0)) return (1); (void) sprintf(prompt, pkg_gt("Insert %%v %d of %d into %%p"), ds_volno, ds_volcnt); if (n = getvol(ods_name, NULL, DM_FORMAT, prompt)) return (n); if ((ds_fd = open(dstdev.cdevice, 1)) < 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_OPEN), dstdev.cdevice, errno); return (1); } if (ds_ginit(dstdev.cdevice) < 0) { progerr(pkg_gt(ERR_TRANSFER)); logerr(pkg_gt(MSG_OPEN), dstdev.cdevice, errno); (void) ds_close(0); return (1); } (void) sscanf(volnos, "%d %[ 0-9]", &index, tmpvol); (void) strlcpy(volnos, tmpvol, sizeof (volnos)); curpartcnt += index; } } } return (0); }