Modify inode attributes in the ext2 File System

Source: Internet
Author: User
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <time.h>#include <getopt.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <ext2fs/ext2fs.h>/* * Flags used by the common argument processing functions */#define CHECK_FS_RW0x0001#define CHECK_FS_BITMAPS0x0002#define CHECK_FS_NOTOPEN0x0004#ifdef DLL_EXPORT#define DLLEXPORT __declspec(dllexport)#else#define DLLEXPORT#endifext2_filsyscurrent_fs = NULL;ext2_ino_troot, cwd;DLLEXPORTint open_filesystem(char *device, int open_flags, blk_t superblock,    blk_t blocksize, int catastrophic){intretval;if (superblock != 0 && blocksize == 0) {com_err(device, 0, "if you specify the superblock, you must also specify the block size");current_fs = NULL;return;}if (catastrophic && (open_flags & EXT2_FLAG_RW)) {com_err(device, 0,"opening read-only because of catastrophic mode");open_flags &= ~EXT2_FLAG_RW;}retval = ext2fs_open(device, open_flags, superblock, blocksize,     nt_io_manager(), ¤t_fs);if (retval) {com_err(device, retval, "while opening filesystem");current_fs = NULL;return;}if (catastrophic)com_err(device, 0, "catastrophic mode - not reading inode or group bitmaps");else {retval = ext2fs_read_inode_bitmap(current_fs);if (retval) {com_err(device, retval, "while reading inode bitmap");goto errout;}retval = ext2fs_read_block_bitmap(current_fs);if (retval) {com_err(device, retval, "while reading block bitmap");goto errout;}}root = cwd = EXT2_ROOT_INO;return 0;errout:retval = ext2fs_close(current_fs);if (retval)com_err(device, retval, "while trying to close filesystem");current_fs = NULL;return -1;}DLLEXPORTvoid close_filesystem(void){intretval;if (current_fs->flags & EXT2_FLAG_IB_DIRTY) {retval = ext2fs_write_inode_bitmap(current_fs);if (retval)com_err("ext2fs_write_inode_bitmap", retval, "");}if (current_fs->flags & EXT2_FLAG_BB_DIRTY) {retval = ext2fs_write_block_bitmap(current_fs);if (retval)com_err("ext2fs_write_block_bitmap", retval, "");}retval = ext2fs_close(current_fs);if (retval)com_err("ext2fs_close", retval, "");current_fs = NULL;return;}/* * This routine is used whenever a command needs to turn a string into * an inode. */ext2_ino_t string_to_inode(char *str){ext2_ino_tino;intlen = strlen(str);char*end;intretval;/* * If the string is of the form <ino>, then treat it as an * inode number. */if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) {ino = strtoul(str+1, &end, 0);if (*end=='>')return ino;}retval = ext2fs_namei(current_fs, root, cwd, str, &ino);if (retval) {com_err(str, retval, "");return 0;}return ino;}/* * This routine returns 1 if the filesystem is not open, and prints an * error message to that effect. */int check_fs_open(char *name){if (!current_fs) {com_err(name, 0, "Filesystem not open");return 1;}return 0;}/* * This routine returns 1 if a filesystem is open, and prints an * error message to that effect. */int check_fs_not_open(char *name){if (current_fs) {com_err(name, 0,"Filesystem %s is still open.  Close it first.\n",current_fs->device_name);return 1;}return 0;}/* * This routine returns 1 if a filesystem is not opened read/write, * and prints an error message to that effect. */int check_fs_read_write(char *name){if (!(current_fs->flags & EXT2_FLAG_RW)) {com_err(name, 0, "Filesystem opened read/only");return 1;}return 0;}/* * This routine returns 1 if a filesystem is doesn't have its inode * and block bitmaps loaded, and prints an error message to that * effect. */int check_fs_bitmaps(char *name){if (!current_fs->block_map || !current_fs->inode_map) {com_err(name, 0, "Filesystem bitmaps not loaded");return 1;}return 0;}/* * This function takes a __u32 time value and converts it to a string, * using ctime */char *time_to_string(__u32 cl){time_tt = (time_t) cl;return ctime(&t);}int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode,const char *cmd){int retval;retval = ext2fs_read_inode(current_fs, ino, inode);if (retval) {com_err(cmd, retval, "while reading inode %u", ino);return 1;}return 0;}int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode,const char *cmd){int retval;retval = ext2fs_write_inode(current_fs, ino, inode);if (retval) {com_err(cmd, retval, "while writing inode %u", ino);return 1;}return 0;}/* * This is a common helper function used by the command processing * routines */int common_args_process(int argc, char *argv[], int min_argc, int max_argc,const char *cmd, const char *usage, int flags){if (argc < min_argc || argc > max_argc) {com_err(argv[0], 0, "Usage: %s %s", cmd, usage);return 1;}if (flags & CHECK_FS_NOTOPEN) {if (check_fs_not_open(argv[0]))return 1;} else {if (check_fs_open(argv[0]))return 1;}if ((flags & CHECK_FS_RW) && check_fs_read_write(argv[0]))return 1;if ((flags & CHECK_FS_BITMAPS) && check_fs_bitmaps(argv[0]))return 1;return 0;}/* * This is a helper function used by do_stat, do_freei, do_seti, and * do_testi, etc.  Basically, any command which takes a single * argument which is a file/inode number specifier. */int common_inode_args_process(int argc, char *argv[],      ext2_ino_t *inode, int flags){if (common_args_process(argc, argv, 2, 2, argv[0], "<file>", flags))return 1;*inode = string_to_inode(argv[1]);if (!*inode) return 1;return 0;}static void modify_u16(char *com, const char *prompt,       const char *format, __u16 *val){char buf[200];unsigned long v;char *tmp;sprintf(buf, format, *val);printf("%30s    [%s] ", prompt, buf);fgets(buf, sizeof(buf), stdin);if (buf[strlen (buf) - 1] == '\n')buf[strlen (buf) - 1] = '\0';if (!buf[0])return;v = strtoul(buf, &tmp, 0);if (*tmp)com_err(com, 0, "Bad value - %s", buf);else*val = v;}static void modify_u32(char *com, const char *prompt,       const char *format, __u32 *val){char buf[200];unsigned long v;char *tmp;sprintf(buf, format, *val);printf("%30s    [%s] ", prompt, buf);fgets(buf, sizeof(buf), stdin);if (buf[strlen (buf) - 1] == '\n')buf[strlen (buf) - 1] = '\0';if (!buf[0])return;v = strtoul(buf, &tmp, 0);if (*tmp)com_err(com, 0, "Bad value - %s", buf);else*val = v;}#define COMMAND_MI "mi"DLLEXPORTvoid do_modify_inode(int readonly, char *filename, unsigned long mode){struct ext2_inode inode;ext2_ino_tinode_num;int i;unsigned char*frag, *fsize;charbuf[80];int os;const char*hex_format = "0x%x";const char*octal_format = "0%o";const char*decimal_format = "%d";inode_num = string_to_inode(filename);if (!inode_num) return ;/*if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW))return;*/os = current_fs->super->s_creator_os;if (debugfs_read_inode(inode_num, &inode, filename))return;printf("Current Mode   [0%o] \n", inode.i_mode);inode.i_mode = mode;#if 0modify_u16(COMMAND_MI, "Mode", octal_format, &inode.i_mode);modify_u16(COMMAND_MI, "User ID", decimal_format, &inode.i_uid);modify_u16(COMMAND_MI, "Group ID", decimal_format, &inode.i_gid);modify_u32(COMMAND_MI, "Size", decimal_format, &inode.i_size);modify_u32(COMMAND_MI, "Creation time", decimal_format, &inode.i_ctime);modify_u32(COMMAND_MI, "Modification time", decimal_format, &inode.i_mtime);modify_u32(COMMAND_MI, "Access time", decimal_format, &inode.i_atime);modify_u32(COMMAND_MI, "Deletion time", decimal_format, &inode.i_dtime);modify_u16(COMMAND_MI, "Link count", decimal_format, &inode.i_links_count);modify_u32(COMMAND_MI, "Block count", decimal_format, &inode.i_blocks);modify_u32(COMMAND_MI, "File flags", hex_format, &inode.i_flags);modify_u32(COMMAND_MI, "Generation", hex_format, &inode.i_generation);#if 0          modify_u32(COMMAND_MI, "Reserved1", decimal_format, &inode.i_reserved1);#endifmodify_u32(COMMAND_MI, "File acl", decimal_format, &inode.i_file_acl);if (LINUX_S_ISDIR(inode.i_mode))modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);elsemodify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high);if (current_fs->super->s_creator_os == EXT2_OS_HURD)modify_u32(argv[0], "Translator Block",    decimal_format, &inode.osd1.hurd1.h_i_translator);modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr);switch (os) {    case EXT2_OS_LINUX:frag = &inode.osd2.linux2.l_i_frag;fsize = &inode.osd2.linux2.l_i_fsize;break;    case EXT2_OS_HURD:frag = &inode.osd2.hurd2.h_i_frag;fsize = &inode.osd2.hurd2.h_i_fsize;break;    case EXT2_OS_MASIX:frag = &inode.osd2.masix2.m_i_frag;fsize = &inode.osd2.masix2.m_i_fsize;break;    default:frag = fsize = 0;}if (frag)modify_u8(argv[0], "Fragment number", decimal_format, frag);if (fsize)modify_u8(argv[0], "Fragment size", decimal_format, fsize);for (i=0;  i < EXT2_NDIR_BLOCKS; i++) {sprintf(buf, "Direct Block #%d", i);modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]);}modify_u32(argv[0], "Indirect Block", decimal_format,    &inode.i_block[EXT2_IND_BLOCK]);    modify_u32(argv[0], "Double Indirect Block", decimal_format,    &inode.i_block[EXT2_DIND_BLOCK]);modify_u32(argv[0], "Triple Indirect Block", decimal_format,    &inode.i_block[EXT2_TIND_BLOCK]);#endifif (readonly)return;if (debugfs_write_inode(inode_num, &inode, filename))return;}/* * This function will convert a string to an unsigned long, printing * an error message if it fails, and returning success or failure in err. */unsigned long parse_ulong(const char *str, const char *cmd,  const char *descr, int *err){char*tmp;unsigned longret;ret = strtoul(str, &tmp, 0);if (*tmp == 0) {if (err)*err = 0;return ret;}com_err(cmd, 0, "Bad %s - %s", descr, str);if (err)*err = 1;elseexit(1);return 0;}/* * This function will convert a string to a block number.  It returns * 0 on success, 1 on failure. */int strtoblk(const char *cmd, const char *str, blk_t *ret){blk_tblk;interr;blk = parse_ulong(str, cmd, "block number", &err);*ret = blk;if (err == 0 && blk == 0) {com_err(cmd, 0, "Invalid block number 0");err = 1;}return err;}#ifdef MOD_EXEint main(int argc, char **argv){intcatastrophic = 0;blk_tsuperblock = 0;blk_tblocksize = 0;int open_flags = 0;char *file_path = NULL;char *dev_path = NULL;int c = 0;const char*usage = "Usage: chmod [-b blocksize] [-s superblock] [-f file] [-F] [-V] [-c] [-i] [-r] [-o device]";unsigned long mode;char *tmp = NULL;int readonly = 0;open_flags |= EXT2_FLAG_RW;while ((c = getopt (argc, argv, "icRF:f:b:s:o:Vr")) != EOF) {switch (c) {case 'F':open_flags |= EXT2_FLAG_FORCE;break;case 'f':file_path = optarg;break;case 'i':open_flags |= EXT2_FLAG_IMAGE_FILE;break;case 'o':dev_path = optarg;break;case 'b':blocksize = parse_ulong(optarg, argv[0], "block size", 0);break;case 's':superblock = parse_ulong(optarg, argv[0],  "superblock number", 0);break;case 'c':catastrophic = 1;break;case 'r':readonly = 1;break;case 'V':/* Print version number and exit */fprintf(stderr, "\tUsing %s\n",error_message(EXT2_ET_BASE));exit(0);default:com_err(argv[0], 0, usage);return 1;}}if (!file_path || !dev_path || (!readonly && !argv[optind])){com_err(argv[0], 0, usage);return 1;}if (!readonly) {printf("Change Mode   [%s] \n", argv[optind]);mode = strtoul(argv[optind], &tmp, 0);if (*tmp){com_err(argv[0], 0, "Bad Mode value - %s", argv[optind]);return 1;}}open_filesystem(dev_path, open_flags,superblock, blocksize, catastrophic);if (!current_fs){return 1;}do_modify_inode(readonly, file_path, mode);close_filesystem();return 0;}#endif

Refer:

E2fsprogs

Mingw

Msys

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.