/* * stress on sync() * stress system by IO sync calls */ int stress_io( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { #if defined(__linux__) int fd; #endif (void)instance; #if !(defined(__linux__) && NEED_GLIBC(2,14,0)) (void)name; #endif #if defined(__linux__) fd = openat(AT_FDCWD, ".", O_RDONLY | O_NONBLOCK | O_DIRECTORY); #endif do { sync(); #if defined(__linux__) && NEED_GLIBC(2,14,0) if ((fd != -1) && (syncfs(fd) < 0)) pr_fail_err(name, "syncfs"); #endif (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); #if defined(__linux__) if (fd != -1) (void)close(fd); #endif return EXIT_SUCCESS; }
static void test_basics(void) { struct stat info1; struct stat info2; test_caseStart("Testing fs"); test_assertInt(mkdir("/newdir",DIR_DEF_MODE),0); fs_createFile("/newdir/file1","foobar"); fs_readFile("/newdir/file1","foobar"); test_assertInt(link("/newdir/file1","/newdir/file2"),0); test_assertInt(stat("/newdir/file1",&info1),0); test_assertInt(stat("/newdir/file2",&info2),0); test_assertInt(memcmp(&info1,&info2,sizeof(struct stat)),0); test_assertUInt(info1.st_nlink,2); test_assertInt(unlink("/newdir/file1"),0); test_assertInt(rmdir("/newdir"),-ENOTEMPTY); test_assertInt(stat("/newdir/file1",&info1),-ENOENT); test_assertInt(stat("/newdir/file2",&info2),0); test_assertUInt(info2.st_nlink,1); test_assertInt(unlink("/newdir/file2"),0); test_assertInt(rmdir("/newdir"),0); int fd = open("/",O_RDONLY); test_assertTrue(fd >= 0); test_assertInt(syncfs(fd),0); close(fd); test_caseSucceeded(); }
int do_unpack(void) { struct file_header untrusted_hdr; #ifdef HAVE_SYNCFS int cwd_fd; int saved_errno; #endif total_bytes = total_files = 0; /* initialize checksum */ crc32_sum = 0; while (read_all_with_crc(0, &untrusted_hdr, sizeof untrusted_hdr)) { /* check for end of transfer marker */ if (untrusted_hdr.namelen == 0) { errno = 0; break; } total_files++; if (files_limit && total_files > files_limit) do_exit(EDQUOT, untrusted_namebuf); process_one_file(&untrusted_hdr); } #ifdef HAVE_SYNCFS saved_errno = errno; cwd_fd = open(".", O_RDONLY); if (cwd_fd >= 0 && syncfs(cwd_fd) == 0 && close(cwd_fd) == 0) errno = saved_errno; #endif send_status_and_crc(errno, untrusted_namebuf); return errno; }
/* * stress on sync() * stress system by IO sync calls */ static int stress_io(const args_t *args) { #if defined(HAVE_SYNCFS) int i, fd, n_mnts; char *mnts[MAX_MNTS]; int fds[MAX_MNTS]; n_mnts = mount_get(mnts, MAX_MNTS); for (i = 0; i < n_mnts; i++) fds[i] = openat(AT_FDCWD, mnts[i], O_RDONLY | O_NONBLOCK | O_DIRECTORY); fd = openat(AT_FDCWD, ".", O_RDONLY | O_NONBLOCK | O_DIRECTORY); #endif do { (void)sync(); #if defined(HAVE_SYNCFS) if ((fd != -1) && (syncfs(fd) < 0)) pr_fail_err("syncfs"); /* try to sync on all the mount points */ for (i = 0; i < n_mnts; i++) if (fds[i] != -1) (void)syncfs(fds[i]); #endif inc_counter(args); } while (keep_stressing()); #if defined(HAVE_SYNCFS) if (fd != -1) (void)close(fd); for (i = 0; i < n_mnts; i++) if (fds[i] != -1) (void)close(fds[i]); mount_free(mnts, n_mnts); #endif return EXIT_SUCCESS; }
static int sync_path(const char *p) { _cleanup_close_ int fd = -1; fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) return -errno; if (syncfs(fd) < 0) return -errno; return 0; }
void marshal_daemon_destroy(void) { #if CONFIG_USE_SYNCFS == 1 if (syncfs(rund.ser_fd) < 0) log_warn("marshal_daemon_destroy(): syncfs(): %s\n", strerror(errno)); #else sync(); #endif /* Remove lock from serialization file */ if (lockf(rund.ser_fd, F_ULOCK, 0) < 0) log_warn("marshal_daemon_init(): lockf(): %s\n", strerror(errno)); if (close(rund.ser_fd) < 0) log_warn("marshal_daemon_destroy(): close(): %s\n", strerror(errno)); }
static void DebugWriteLog(const char * Msg, int size) { static int log_file = -1; char LogFileName[64] = {0}; if (log_file == -1) { sprintf(LogFileName, "./msg_log_%d.txt", (int)getpid()); log_file = open(LogFileName, O_CREAT | O_WRONLY | O_TRUNC | O_SYNC); } //printf(Msg); write(log_file, Msg, size); syncfs(log_file); return; }
static void test_largeFile(void) { /* ensure that the blocksize is not a multiple of this array size */ uint8_t pattern[62]; uint8_t buf[62]; /* reach some double indirect blocks */ const size_t size = 12 * 1024 + 256 * 1024 + 256 * 1024; test_caseStart("Creating a large file and reading it back"); for(size_t i = 0; i < ARRAY_SIZE(pattern); ++i) pattern[i] = i; /* write it */ { FILE *f = fopen("/largefile","w"); test_assertTrue(f != NULL); size_t rem = size; while(rem > 0) { size_t amount = MIN(rem,ARRAY_SIZE(pattern)); test_assertSize(fwrite(pattern,1,amount,f),amount); rem -= amount; } /* flush buffer cache */ test_assertInt(syncfs(fileno(f)),0); fclose(f); } /* read it back */ { FILE *f = fopen("/largefile","r"); test_assertTrue(f != NULL); size_t rem = size; while(rem > 0) { size_t amount = MIN(rem,ARRAY_SIZE(pattern)); test_assertSize(fread(buf,1,amount,f),amount); for(size_t i = 0; i < amount; ++i) test_assertInt(buf[i],pattern[i]); rem -= amount; } fclose(f); } test_assertInt(unlink("/largefile"),0); test_caseSucceeded(); }
int default_flush(void) { int fd, ret = SD_RES_SUCCESS; fd = open(obj_path, O_RDONLY); if (fd < 0) { eprintf("error at open() %s, %s\n", obj_path, strerror(errno)); return SD_RES_NO_OBJ; } if (syncfs(fd)) { eprintf("error at syncfs(), %s\n", strerror(errno)); ret = SD_RES_EIO; } close(fd); return ret; }
static void test_basics(void) { struct stat info1; struct stat info2; test_caseStart("Testing fs"); test_assertInt(mkdir("/newdir",DIR_DEF_MODE),0); fs_createFile("/newdir/file1","foobar"); fs_readFile("/newdir/file1","foobar"); test_assertInt(link("/newdir/file1","/newdir/file2"),0); test_assertInt(stat("/newdir/file1",&info1),0); test_assertInt(stat("/newdir/file2",&info2),0); // compare elements individually, because the structs might contain uninitialized padding test_assertUInt(info1.st_atime,info2.st_atime); test_assertUInt(info1.st_mtime,info2.st_mtime); test_assertUInt(info1.st_ctime,info2.st_ctime); test_assertUInt(info1.st_blocks,info2.st_blocks); test_assertUInt(info1.st_blksize,info2.st_blksize); test_assertUInt(info1.st_dev,info2.st_dev); test_assertUInt(info1.st_uid,info2.st_uid); test_assertUInt(info1.st_gid,info2.st_gid); test_assertUInt(info1.st_ino,info2.st_ino); test_assertUInt(info1.st_nlink,info2.st_nlink); test_assertUInt(info1.st_mode,info2.st_mode); test_assertUInt(info1.st_size,info2.st_size); test_assertUInt(info1.st_nlink,2); test_assertInt(unlink("/newdir/file1"),0); test_assertInt(rmdir("/newdir"),-ENOTEMPTY); test_assertInt(stat("/newdir/file1",&info1),-ENOENT); test_assertInt(stat("/newdir/file2",&info2),0); test_assertUInt(info2.st_nlink,1); test_assertInt(unlink("/newdir/file2"),0); test_assertInt(rmdir("/newdir"),0); int fd = open("/",O_RDONLY); test_assertTrue(fd >= 0); test_assertInt(syncfs(fd),0); close(fd); test_caseSucceeded(); }
int main(int argc, char** argv) { FILE *fp = fopen("/doug-test.txt", "w"); fp_log = fp; while(1) { print("/dev/console", "DOUGINIT: console\n"); print("/dev/tty1", "DOUGINIT: tty1\n"); fprintf(stderr, "DOUGINIT: stderr\n"); fflush(stderr); fprintf(stdout, "DOUGINIT: stdout\n"); fflush(stdout); if (fp) { fputs("Flushing and syncing\n", fp); fflush(fp); syncfs(fileno(fp)); } sleep(5); } return 0; }
void telnetd(void * button) { void * passwdw = JWGetData(button); char * passwd = JTxfGetText(passwdw); FILE * passwdfp; int prevpid = 1; if(telnetdid) { kill(telnetdid,1); telnetdid = 0; ((JBut*)button)->Label[2] = 'a'; //change button to say Start ((JBut*)button)->Label[3] = 'r'; ((JBut*)button)->Label[4] = 't'; JWReDraw(button); } else { if(strlen(passwd) > 0) { confignode = XMLgetNode(configxml,"/xml/passwd"); passwdfp = fopen(XMLgetAttr(confignode,"path"),"w"); if(passwdfp) { fprintf(passwdfp,"%s\n",passwd); JTxfSetText(passwdw,""); fclose(passwdfp); syncfs("/"); } } system("telnetd"); ((JBut*)button)->Label[2] = 'o'; //change button to say Stop ((JBut*)button)->Label[3] = 'p'; ((JBut*)button)->Label[4] = ' '; JWReDraw(button); do { prevpid = getPSInfo(prevpid, &APS); if(!strncmp(APS.Name,"telnetd",strlen("telnetd"))) { telnetdid = APS.PID; break; } } while(prevpid); printf("telnetd started, PID == %d\n",telnetdid); } }
void httpd(void * button) { void * webrootw = JWGetData(button); void * logfilew = JWGetData(webrootw); char * webroot = JTxfGetText(webrootw); char * logfile = JTxfGetText(logfilew); char * str; int prevpid = 1; if(httpdid) { kill(httpdid,1); httpdid = 0; ((JBut*)button)->Label[2] = 'a'; //change button to say Start ((JBut*)button)->Label[3] = 'r'; ((JBut*)button)->Label[4] = 't'; JWReDraw(button); } else { str = malloc(strlen("httpd")+strlen(webroot)+strlen(logfile)+5); sprintf(str,"httpd %s >>%s",webroot,logfile); system(str); free(str); ((JBut*)button)->Label[2] = 'o'; //change button to say Stop ((JBut*)button)->Label[3] = 'p'; ((JBut*)button)->Label[4] = ' '; JWReDraw(button); confignode = XMLgetNode(configxml,"/xml/webroot"); XMLsetAttr(confignode,"path",webroot); confignode = XMLgetNode(configxml,"/xml/logfile"); XMLsetAttr(confignode,"path",logfile); XMLsaveFile(configxml,fpathname("config.xml",getappdir(),1)); syncfs("/"); do { prevpid = getPSInfo(prevpid, &APS); if(!strncmp(APS.Name,"httpd",strlen("httpd"))) { httpdid = APS.PID; break; } } while(prevpid); printf("httpd started, PID == %d\n",httpdid); } }
/* * stress_hdd_write() * write with writev or write depending on mode */ static ssize_t stress_hdd_write(const int fd, uint8_t *buf, size_t count) { ssize_t ret; if (opt_hdd_flags & HDD_OPT_UTIMES) (void)futimes(fd, NULL); if (opt_hdd_flags & HDD_OPT_IOVEC) { struct iovec iov[HDD_IO_VEC_MAX]; size_t i; uint8_t *data = buf; const uint64_t sz = opt_hdd_write_size / HDD_IO_VEC_MAX; for (i = 0; i < HDD_IO_VEC_MAX; i++) { iov[i].iov_base = data; iov[i].iov_len = (size_t)sz; buf += sz; } ret = writev(fd, iov, HDD_IO_VEC_MAX); } else { ret = write(fd, buf, count); } #if _BSD_SOURCE || _XOPEN_SOURCE || _POSIX_C_SOURCE >= 200112L if (opt_hdd_flags & HDD_OPT_FSYNC) (void)fsync(fd); #endif #if _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE >= 500 if (opt_hdd_flags & HDD_OPT_FDATASYNC) (void)fdatasync(fd); #endif #if defined(_GNU_SOURCE) && NEED_GLIBC(2,14,0) && defined(__linux__) if (opt_hdd_flags & HDD_OPT_SYNCFS) (void)syncfs(fd); #endif return ret; }
int setup_machine_directory(uint64_t size, sd_bus_error *error) { _cleanup_release_lock_file_ LockFile lock_file = LOCK_FILE_INIT; struct loop_info64 info = { .lo_flags = LO_FLAGS_AUTOCLEAR, }; _cleanup_close_ int fd = -1, control = -1, loop = -1; _cleanup_free_ char* loopdev = NULL; char tmpdir[] = "/tmp/machine-pool.XXXXXX", *mntdir = NULL; bool tmpdir_made = false, mntdir_made = false, mntdir_mounted = false; char buf[FORMAT_BYTES_MAX]; int r, nr = -1; /* btrfs cannot handle file systems < 16M, hence use this as minimum */ if (size == (uint64_t) -1) size = VAR_LIB_MACHINES_SIZE_START; else if (size < 16*1024*1024) size = 16*1024*1024; /* Make sure we only set the directory up once at a time */ r = make_lock_file("/run/systemd/machines.lock", LOCK_EX, &lock_file); if (r < 0) return r; r = check_btrfs(); if (r < 0) return sd_bus_error_set_errnof(error, r, "Failed to determine whether /var/lib/machines is located on btrfs: %m"); if (r > 0) { (void) btrfs_subvol_make_label("/var/lib/machines"); r = btrfs_quota_enable("/var/lib/machines", true); if (r < 0) log_warning_errno(r, "Failed to enable quota for /var/lib/machines, ignoring: %m"); r = btrfs_subvol_auto_qgroup("/var/lib/machines", 0, true); if (r < 0) log_warning_errno(r, "Failed to set up default quota hierarchy for /var/lib/machines, ignoring: %m"); return 1; } if (path_is_mount_point("/var/lib/machines", AT_SYMLINK_FOLLOW) > 0) { log_debug("/var/lib/machines is already a mount point, not creating loopback file for it."); return 0; } r = dir_is_populated("/var/lib/machines"); if (r < 0 && r != -ENOENT) return r; if (r > 0) { log_debug("/var/log/machines is already populated, not creating loopback file for it."); return 0; } r = mkfs_exists("btrfs"); if (r == -ENOENT) { log_debug("mkfs.btrfs is missing, cannot create loopback file for /var/lib/machines."); return 0; } if (r < 0) return r; fd = setup_machine_raw(size, error); if (fd < 0) return fd; control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); if (control < 0) return sd_bus_error_set_errnof(error, errno, "Failed to open /dev/loop-control: %m"); nr = ioctl(control, LOOP_CTL_GET_FREE); if (nr < 0) return sd_bus_error_set_errnof(error, errno, "Failed to allocate loop device: %m"); if (asprintf(&loopdev, "/dev/loop%i", nr) < 0) { r = -ENOMEM; goto fail; } loop = open(loopdev, O_CLOEXEC|O_RDWR|O_NOCTTY|O_NONBLOCK); if (loop < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to open loopback device: %m"); goto fail; } if (ioctl(loop, LOOP_SET_FD, fd) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to bind loopback device: %m"); goto fail; } if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to enable auto-clear for loopback device: %m"); goto fail; } /* We need to make sure the new /var/lib/machines directory * has an access mode of 0700 at the time it is first made * available. mkfs will create it with 0755 however. Hence, * let's mount the directory into an inaccessible directory * below /tmp first, fix the access mode, and move it to the * public place then. */ if (!mkdtemp(tmpdir)) { r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount parent directory: %m"); goto fail; } tmpdir_made = true; mntdir = strjoina(tmpdir, "/mnt"); if (mkdir(mntdir, 0700) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount directory: %m"); goto fail; } mntdir_made = true; if (mount(loopdev, mntdir, "btrfs", 0, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to mount loopback device: %m"); goto fail; } mntdir_mounted = true; r = btrfs_quota_enable(mntdir, true); if (r < 0) log_warning_errno(r, "Failed to enable quota, ignoring: %m"); r = btrfs_subvol_auto_qgroup(mntdir, 0, true); if (r < 0) log_warning_errno(r, "Failed to set up default quota hierarchy, ignoring: %m"); if (chmod(mntdir, 0700) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to fix owner: %m"); goto fail; } (void) mkdir_p_label("/var/lib/machines", 0700); if (mount(mntdir, "/var/lib/machines", NULL, MS_BIND, NULL) < 0) { r = sd_bus_error_set_errnof(error, errno, "Failed to mount directory into right place: %m"); goto fail; } (void) syncfs(fd); log_info("Set up /var/lib/machines as btrfs loopback file system of size %s mounted on /var/lib/machines.raw.", format_bytes(buf, sizeof(buf), size)); (void) umount2(mntdir, MNT_DETACH); (void) rmdir(mntdir); (void) rmdir(tmpdir); return 1; fail: if (mntdir_mounted) (void) umount2(mntdir, MNT_DETACH); if (mntdir_made) (void) rmdir(mntdir); if (tmpdir_made) (void) rmdir(tmpdir); if (loop >= 0) { (void) ioctl(loop, LOOP_CLR_FD); loop = safe_close(loop); } if (control >= 0 && nr >= 0) (void) ioctl(control, LOOP_CTL_REMOVE, nr); return r; }
int __darwin_fcntl(int fd, int cmd, void* arg) { switch (cmd) { case DARWIN_F_DUPFD: cmd = F_DUPFD; break; case DARWIN_F_DUPFD_CLOEXEC: cmd = F_DUPFD_CLOEXEC; break; case DARWIN_F_GETFD: // CLOEXEC is compatible cmd = F_GETFD; break; case DARWIN_F_SETFD: cmd = F_SETFD; break; case DARWIN_F_GETFL: { int value = fcntl(fd, F_GETFL); if (value == -1) { errnoOut(); return -1; } else { return Darling::openflagsNativeToDarwin(value); } break; } case DARWIN_F_SETFL: { int value = (int)(uintptr_t) arg; value = Darling::openflagsDarwinToNative(value); cmd = F_SETFL; arg = (void*) value; break; } case DARWIN_F_GETOWN: cmd = F_GETOWN; break; case DARWIN_F_SETOWN: cmd = F_SETOWN; break; case DARWIN_F_GETPATH: { REQUIRE_ARG_PTR(arg); char procpath[255]; int rv; sprintf(procpath, "/proc/%d/fd/%d", getpid(), fd); rv = readlink(procpath, (char*) arg, DARWIN_MAXPATHLEN); if (rv == -1) { errnoOut(); return -1; } ((char*) arg)[rv] = 0; return 0; } case DARWIN_F_PREALLOCATE: { REQUIRE_ARG_PTR(arg); __darwin_fallocate* fa = static_cast<__darwin_fallocate*>(arg); fa->allocated = 0; // We disregard fa->flags, it's not supported on Linux if (fa->mode == DARWIN_F_PEOFPOSMODE) // like SEEK_END { struct stat st; if (fstat(fd, &st) == -1) { errnoOut(); return -1; } fa->offset += st.st_size; } else if (fa->mode == DARWIN_F_VOLPOSMODE) // like SEEK_CUR { fa->offset += lseek(fd, 0, SEEK_CUR); } else { errno = DARWIN_EINVAL; return -1; } int err = posix_fallocate(fd, fa->offset, fa->length); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else { fa->allocated = fa->length; return 0; } } case DARWIN_F_SETSIZE: { uint64_t size = uint64_t(arg); // Not identical to what F_SETSIZE is supposed to do // but it's the best we can do. if (ftruncate(fd, size) == -1) { errnoOut(); return -1; } return 0; } case DARWIN_F_RDADVISE: { REQUIRE_ARG_PTR(arg); const __darwin_rdadvise* adv = static_cast<__darwin_rdadvise*>(arg); int err = posix_fadvise(fd, adv->offset, adv->count, POSIX_FADV_WILLNEED); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_RDAHEAD: { REQUIRE_ARG_PTR(arg); int advice = (arg) ? POSIX_FADV_NORMAL : POSIX_FADV_RANDOM; int err = posix_fadvise(fd, 0, 1, advice); // on Linux, the offset and length doesn't matter for these advices if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_NOCACHE: { struct stat st; if (fstat(fd, &st) == -1) { errnoOut(); return -1; } // This is as close as we can get... int advice = (arg) ? POSIX_FADV_NORMAL : POSIX_FADV_DONTNEED; int err = posix_fadvise(fd, 0, 1, advice); if (err) // doesn't use errno! { errno = errnoLinuxToDarwin(err); return -1; } else return 0; } case DARWIN_F_FULLFSYNC: { if (fsync(fd) == -1) { errnoOut(); return -1; } // This is as close as we can get... // Linux 2.6.39+ if (syncfs(fd) == -1) { errnoOut(); return -1; } return 0; } case DARWIN_F_GETLK: { REQUIRE_ARG_PTR(arg); __darwin_flock* lock = static_cast<__darwin_flock*>(arg); struct flock native; memset(lock, 0, sizeof(*lock)); if (fcntl(fd, F_GETLK, &native) == -1) { errnoOut(); return -1; } lock->l_start = native.l_start; lock->l_len = native.l_len; lock->l_pid = native.l_pid; lock->l_type = native.l_type; lock->l_whence = native.l_whence; return 0; } case DARWIN_F_SETLK: case DARWIN_F_SETLKW: { REQUIRE_ARG_PTR(arg); int ncmd = (cmd == DARWIN_F_SETLK) ? F_SETLK : F_SETLKW; const __darwin_flock* lock = static_cast<__darwin_flock*>(arg); struct flock native; native.l_start = lock->l_start; native.l_len = lock->l_len; native.l_pid = lock->l_pid; native.l_type = lock->l_type; native.l_whence = lock->l_whence; return AutoErrno<int>(fcntl, fd, ncmd, &native); } case DARWIN_F_SETNOSIGPIPE: case DARWIN_F_GETNOSIGPIPE: case DARWIN_F_READBOOTSTRAP: case DARWIN_F_WRITEBOOTSTRAP: case DARWIN_F_LOG2PHYS: case DARWIN_F_LOG2PHYS_EXT: { errno = DARWIN_ENOSYS; return -1; } default: errno = DARWIN_EINVAL; return -1; } return AutoErrno<int>(fcntl, fd, cmd, arg); }
int main(int argc, char *argv[]){ return syncfs(STDIN_FILENO); }
int main(int argc, char **argv) { int32 length; int c, block = 1, last_type = ASCII; ifp = stdin; ofp = stdout; print_banner(); if (argc > 3) usage(); /* possibly open input & output files */ if (argc >= 2) { ifp = fopen(argv[1], "r"); if (!ifp) { fprintf(stderr, "error: cannot open %s for reading\n", argv[1]); exit(1); } } if (argc == 3) { ofp = fopen(argv[2], "w"); if (!ofp) { fprintf(stderr, "error: cannot open %s for writing\n", argv[2]); exit(1); } } #ifdef _MSDOS /* As we are processing a PFB (binary) input */ /* file, we must set its file mode to binary. */ _setmode(_fileno(ifp), _O_BINARY); #endif /* main loop through blocks */ for (;;) { c = fgetc(ifp); if (c == EOF) { break; } if (c != MARKER) { fprintf(stderr, "error: missing marker (128) at beginning of block %d", block); exit(1); } switch (c = fgetc(ifp)) { case ASCII: if (last_type != ASCII) fputc('\n', ofp); last_type = ASCII; for (length = read_length(); length > 0; length--) if ((c = fgetc(ifp)) == '\r') fputc('\n', ofp); else fputc(c, ofp); break; case BINARY: last_type = BINARY; for (length = read_length(); length > 0; length--) output_hex(fgetc(ifp)); break; case DONE: /* nothing to be done --- will exit at top of loop with EOF */ break; default: fprintf(stderr, "error: bad block type %d in block %d\n", c, block); break; } block++; } fclose(ifp); fclose(ofp); syncfs("/"); return 0; }