📄 misc.c
字号:
/* * Copyright 1996-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */#define _GNU_SOURCE#include "misc.h"#include <stdio.h>#include <stdarg.h>#include <string.h>#include <errno.h>#include <mntent.h>#include <sys/vfs.h>#include <time.h>#include <utime.h>#include <ctype.h>#include <linux/hdreg.h>#include <dirent.h>#include <assert.h>#include <sys/ioctl.h>#include <signal.h>/* Debian modifications by Ed Boraas <ed@debian.org> */#include <sys/mount.h>/* End Debian mods */#define STAT_FIELD(Field, Type) \inline Type misc_device_##Field(char *device) { \ struct stat st; \ \ if (stat(device, &st) == 0) \ return st.st_##Field; \ \ fprintf(stderr, "Stat of the device '%s' failed.", device); \ exit(8); \}STAT_FIELD(mode, mode_t);STAT_FIELD(rdev, dev_t);STAT_FIELD(size, off_t);STAT_FIELD(blocks, blkcnt_t);void die (char * fmt, ...){ static char buf[1024]; va_list args; va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); fprintf (stderr, "\n%s\n", buf); abort ();}#define MEM_BEGIN "_mem_begin_"#define MEM_END "mem_end"#define MEM_FREED "__free_"#define CONTROL_SIZE (strlen (MEM_BEGIN) + 1 + sizeof (int) + strlen (MEM_END) + 1)unsigned int get_mem_size(char *p) { char *begin; begin = p - strlen (MEM_BEGIN) - 1 - sizeof(int); return *(int *)(begin + strlen (MEM_BEGIN) + 1);}void checkmem (char * p, int size){ char * begin; char * end; begin = p - strlen (MEM_BEGIN) - 1 - sizeof (int); if (strcmp (begin, MEM_BEGIN)) die ("checkmem: memory corrupted - invalid head sign"); if (*(int *)(begin + strlen (MEM_BEGIN) + 1) != size) die ("checkmem: memory corrupted - invalid size"); end = begin + size + CONTROL_SIZE - strlen (MEM_END) - 1; if (strcmp (end, MEM_END)) die ("checkmem: memory corrupted - invalid end sign");}void *getmem (int size){ char * mem; if ((mem = mem_alloc(size)) == NULL) die ("getmem: no more memory (%d)", size); memset (mem, 0, size);// checkmem (mem, size); return mem;}void *mem_alloc(int size) { char * p; char * mem; p = (char *)malloc (CONTROL_SIZE + size); if (!p) die ("getmem: no more memory (%d)", size); /* Write the MEM_BEGIN magic in the beginning of allocated memory. */ strcpy (p, MEM_BEGIN); p += strlen (MEM_BEGIN) + 1; /* Write the size after the magic. */ *(int *)p = size; p += sizeof (int); mem = p; p += size; strcpy (p, MEM_END); return mem;}void * expandmem (void * vp, int size, int by){ int allocated; char * mem, * p = vp; int expand_by = by; if (p) { checkmem (p, size); allocated = CONTROL_SIZE + size; p -= (strlen (MEM_BEGIN) + 1 + sizeof (int)); } else { allocated = 0; /* add control bytes to the new allocated area */ expand_by += CONTROL_SIZE; } p = realloc (p, allocated + expand_by); if (!p) die ("expandmem: no more memory (%d)", size); if (!vp) { strcpy (p, MEM_BEGIN); } mem = p + strlen (MEM_BEGIN) + 1 + sizeof (int); *(int *)(p + strlen (MEM_BEGIN) + 1) = size + by; /* fill new allocated area by 0s */ if(by > 0) memset (mem + size, 0, by); strcpy (mem + size + by, MEM_END);// checkmem (mem, size + by); return mem;}void freemem (void * vp){ char * p = vp; int size; if (!p) return; size = get_mem_size (vp); checkmem (p, size); p -= (strlen (MEM_BEGIN) + 1 + sizeof (int)); strcpy (p, MEM_FREED); strcpy (p + size + CONTROL_SIZE - strlen (MEM_END) - 1, MEM_FREED); free (p);}typedef int (*func_t) (char *);/* Lookup the @file in the @mntfile. @file is mntent.mnt_fsname if @fsname is set; mntent.mnt_dir otherwise. Return the mnt entry from the @mntfile. Warning: if the root fs is mounted RO, the content of /etc/mtab may be not correct. */static struct mntent *misc_mntent_lookup(char *mntfile, char *file, int path) { struct mntent *mnt; int name_match = 0; struct stat st; dev_t rdev = 0; dev_t dev = 0; ino_t ino = 0; char *name; FILE *fp; assert(mntfile != NULL); assert(file != NULL); if (stat(file, &st) == 0) { /* Devices is stated. */ if (S_ISBLK(st.st_mode)) { rdev = st.st_rdev; } else { dev = st.st_dev; ino = st.st_ino; } } if ((fp = setmntent(mntfile, "r")) == NULL) return INVAL_PTR; while ((mnt = getmntent(fp)) != NULL) { /* Check if names match. */ name = path ? mnt->mnt_dir : mnt->mnt_fsname; if (strcmp(file, name) == 0) name_match = 1; if (stat(name, &st)) continue; /* If names do not match, check if stats match. */ if (!name_match) { if (rdev && S_ISBLK(st.st_mode)) { if (rdev != st.st_rdev) continue; } else if (dev && !S_ISBLK(st.st_mode)) { if (dev != st.st_dev || ino != st.st_ino) continue; } else { continue; } } /* If not path and not block device do not check anything more. */ if (!path && !rdev) break; if (path) { /* Either names or stats match. Make sure the st_dev of the path is same as @mnt_fsname device rdev. */ if (stat(mnt->mnt_fsname, &st) == 0 && dev == st.st_rdev) break; } else { /* Either names or stats match. Make sure the st_dev of the mount entry is same as the given device rdev. */ if (stat(mnt->mnt_dir, &st) == 0 && rdev == st.st_dev) break; } } endmntent (fp); return mnt;}static int misc_root_mounted(char *device) { struct stat rootst, devst; assert(device != NULL); if (stat("/", &rootst) != 0) return -1; if (stat(device, &devst) != 0) return -1; if (!S_ISBLK(devst.st_mode) || devst.st_rdev != rootst.st_dev) return 0; return 1;}static int misc_file_ro(char *file) { if (utime(file, 0) == -1) { if (errno == EROFS) return 1; } return 0;}struct mntent *misc_mntent(char *device) { int proc = 0, path = 0, root = 0; struct mntent *mnt; struct statfs stfs; assert(device != NULL); /* Check if the root. */ if (misc_root_mounted(device) == 1) root = 1; #ifdef __linux__ /* Check if /proc is procfs. */ if (statfs("/proc", &stfs) == 0 && stfs.f_type == 0x9fa0) { proc = 1; if (root) { /* Lookup the "/" entry in /proc/mounts. Special case as root entry can present as: rootfs / rootfs rw 0 0 Look up the mount point in this case. */ mnt = misc_mntent_lookup("/proc/mounts", "/", 1); } else { /* Lookup the @device /proc/mounts */ mnt = misc_mntent_lookup("/proc/mounts", device, 0); } if (mnt == INVAL_PTR) proc = 0; else if (mnt) return mnt; }#endif /* __linux__ */#if defined(MOUNTED) || defined(_PATH_MOUNTED)#ifndef MOUNTED #define MOUNTED _PATH_MOUNTED#endif /* Check in MOUNTED (/etc/mtab) if RW. */ if (!misc_file_ro(MOUNTED)) { path = 1; if (root) { mnt = misc_mntent_lookup(MOUNTED, "/", 1); } else { mnt = misc_mntent_lookup(MOUNTED, device, 0); } if (mnt == INVAL_PTR) path = 0; else if (mnt) return mnt; }#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */ /* If has not been checked in neither /proc/mounts nor /etc/mtab (or errors have occured), return INVAL_PTR, NULL otherwise. */ return (!proc && !path) ? INVAL_PTR : NULL;}int misc_device_mounted(char *device) { struct mntent *mnt; /* Check for the "/" first to avoid any possible problem with reflecting the root fs info in mtab files. */ if (misc_root_mounted(device) == 1) { return misc_file_ro("/") ? MF_RO : MF_RW; } /* Lookup the mount entry. */ if ((mnt = misc_mntent(device)) == NULL) { return MF_NOT_MOUNTED; } else if (mnt == INVAL_PTR) { return 0; } return hasmntopt(mnt, MNTOPT_RO) ? MF_RO : MF_RW;}char buf1 [100];char buf2 [100];void print_how_fast (unsigned long passed, unsigned long total, int cursor_pos, int reset_time){ static time_t t0 = 0, t1 = 0, t2 = 0; int speed; int indent; if (reset_time) time (&t0); time (&t1); if (t1 != t0) { speed = passed / (t1 - t0); if (total - passed) { if (t1 - t2 < 1) return; t2 = t1; } } else speed = 0; /* what has to be written */ if (total) sprintf (buf1, "left %lu, %d /sec", total - passed, speed); else { /*(*passed) ++;*/ sprintf (buf1, "done %lu, %d /sec", passed, speed); } /* make indent */ indent = 79 - cursor_pos - strlen (buf1); memset (buf2, ' ', indent); buf2[indent] = 0; fprintf (stderr, "%s%s", buf2, buf1); memset (buf2, '\b', indent + strlen (buf1)); buf2 [indent + strlen (buf1)] = 0; fprintf (stderr, "%s", buf2); fflush (stderr);}static char * strs[] ={"0%",".",".",".",".","20%",".",".",".",".","40%",".",".",".",".","60%",".",".",".",".","80%",".",".",".",".","100%"};static char progress_to_be[1024];static char current_progress[1024];static void str_to_be (char * buf, int prosents){ int i; prosents -= prosents % 4; buf[0] = 0; for (i = 0; i <= prosents / 4; i ++) strcat (buf, strs[i]);}void print_how_far (FILE * fp, unsigned long * passed, unsigned long total, unsigned int inc, int quiet){ int percent; if (*passed == 0) current_progress[0] = 0; (*passed) += inc; if (*passed > total) {/* fprintf (fp, "\nprint_how_far: total %lu has been reached already. cur=%lu\n", total, *passed);*/ return; } percent = ((*passed) * 100) / total; str_to_be (progress_to_be, percent); if (strlen (current_progress) != strlen (progress_to_be)) { fprintf (fp, "%s", progress_to_be + strlen (current_progress)); } strcat (current_progress, progress_to_be + strlen (current_progress)); if (!quiet) { print_how_fast(*passed /* - inc*/, total, strlen (progress_to_be), (*passed == inc) ? 1 : 0); } fflush (fp);}#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)/* Note! Despite this call being called with *64, it must be encoded to * return only sizeof(size_t), since in earlier kernel versions it was * declared _IOR(0x12, 114, sizeof(u64)), making it use sizeof(sizeof(u64)). * * However, the call itself does always return 64bit! */# define BLKGETSIZE64 _IOR(0x12, 114, size_t)#endif/* To not have problem with last sectors on the block device when switching to smaller one. */#define MAX_BS (64 * 1024)int valid_offset( int fd, loff_t offset) { char ch; loff_t res; /*res = reiserfs_llseek (fd, offset, 0);*/ res = lseek (fd, offset, SEEK_SET); if (res < 0) return 0; /* if (read (fd, &ch, 1) < 0) does not wirk on files */ if (read (fd, &ch, 1) < 1) return 0; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -