1a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma/* lsattr.c - List file attributes on a Linux second extended file system. 2a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * 3a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * Copyright 2013 Ranjan Kumar <ranjankumar.bth@gmail.com> 4a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * Copyright 2013 Kyungwan Han <asura321@gmail.com> 5a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * 6a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * No Standard. 7a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 8a547cf11686a878d2fd1a42a05719b78903009adAshwini SharmaUSE_LSATTR(NEWTOY(lsattr, "vldaR", TOYFLAG_BIN)) 9a547cf11686a878d2fd1a42a05719b78903009adAshwini SharmaUSE_CHATTR(NEWTOY(chattr, NULL, TOYFLAG_BIN)) 10a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 11a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmaconfig LSATTR 12a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma bool "lsattr" 13a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma default y 14a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma help 15a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma usage: lsattr [-Radlv] [Files...] 16a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 17a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma List file attributes on a Linux second extended file system. 18a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 19a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -R Recursively list attributes of directories and their contents. 20a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -a List all files in directories, including files that start with '.'. 21a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -d List directories like other files, rather than listing their contents. 22a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -l List long flag names. 23a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -v List the file's version/generation number. 24a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 25a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmaconfig CHATTR 26a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma bool "chattr" 27a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma default y 28a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma help 29a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma usage: chattr [-R] [-+=AacDdijsStTu] [-v version] [File...] 30a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 31a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma Change file attributes on a Linux second extended file system. 32a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 33a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma Operators: 34a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma '-' Remove attributes. 35a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma '+' Add attributes. 36a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma '=' Set attributes. 37a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 38a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma Attributes: 39a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma A Don't track atime. 40a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma a Append mode only. 41a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma c Enable compress. 42a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma D Write dir contents synchronously. 43a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma d Don't backup with dump. 44a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma i Cannot be modified (immutable). 45a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma j Write all data to journal first. 46a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma s Zero disk storage when deleted. 47a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma S Write file contents synchronously. 48a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma t Disable tail-merging of partial blocks with other files. 49a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma u Allow file to be undeleted. 50a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -R Recurse. 51a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma -v Set the file's version/generation number. 52a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 53a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma*/ 54a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#define FOR_lsattr 55a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#include "toys.h" 56a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#include <linux/fs.h> 57a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 58a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic struct ext2_attr { 59a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char *name; 60a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma unsigned long flag; 61a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char opt; 62a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} e2attrs[] = { 63a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Secure_Deletion", FS_SECRM_FL, 's'}, // Secure deletion 64a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Undelete", FS_UNRM_FL, 'u'}, // Undelete 65a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Compression_Requested", FS_COMPR_FL, 'c'}, // Compress file 66a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Synchronous_Updates", FS_SYNC_FL, 'S'}, // Synchronous updates 67a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Immutable", FS_IMMUTABLE_FL, 'i'}, // Immutable file 68a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Append_Only", FS_APPEND_FL, 'a'}, // writes to file may only append 69a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"No_Dump", FS_NODUMP_FL, 'd'}, // do not dump file 70a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"No_Atime", FS_NOATIME_FL, 'A'}, // do not update atime 71a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Indexed_directory", FS_INDEX_FL, 'I'}, // hash-indexed directory 72a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Journaled_Data", FS_JOURNAL_DATA_FL, 'j'}, // file data should be journaled 73a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"No_Tailmerging", FS_NOTAIL_FL, 't'}, // file tail should not be merged 74a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Synchronous_Directory_Updates", FS_DIRSYNC_FL, 'D'}, // dirsync behaviour (directories only) 75a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {"Top_of_Directory_Hierarchies", FS_TOPDIR_FL, 'T'}, // Top of directory hierarchies 76a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma {NULL, -1, 0}, 77a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma}; 78a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 79a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Get file flags on a Linux second extended file system. 80a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic int ext2_getflag(int fd, struct stat *sb, unsigned long *flag) 81a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 82a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if(!S_ISREG(sb->st_mode) && !S_ISDIR(sb->st_mode)) { 83a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma errno = EOPNOTSUPP; 84a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return -1; 85a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 86a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return (ioctl(fd, FS_IOC_GETFLAGS, (void*)flag)); 87a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 88a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 89a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic void print_file_attr(char *path) 90a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 91a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma unsigned long flag = 0, version = 0; 92a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma int fd; 93a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma struct stat sb; 94a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 95a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!stat(path, &sb) && !S_ISREG(sb.st_mode) && !S_ISDIR(sb.st_mode)) { 96a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma errno = EOPNOTSUPP; 97a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma goto LABEL1; 98a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 99a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (-1 == (fd=open(path, O_RDONLY | O_NONBLOCK))) goto LABEL1; 100a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 101a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (toys.optflags & FLAG_v) { 102a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ioctl(fd, FS_IOC_GETVERSION, (void*)&version) < 0) goto LABEL2; 103a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xprintf("%5lu ", version); 104a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 105a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 106a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ext2_getflag(fd, &sb, &flag) < 0) perror_msg("reading flags '%s'", path); 107a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma else { 108a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma struct ext2_attr *ptr = e2attrs; 109a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 110a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (toys.optflags & FLAG_l) { 111a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma int name_found = 0; 112a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 113a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xprintf("%-50s ", path); 114a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (; ptr->name; ptr++) { 115a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (flag & ptr->flag) { 116a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (name_found) xprintf(", "); //for formatting. 117a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xprintf("%s", ptr->name); 118a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma name_found = 1; 119a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 120a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 121a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!name_found) xprintf("---"); 122a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xputc('\n'); 123a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } else { 124a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma int index = 0; 125a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 126a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (; ptr->name; ptr++) 127a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma toybuf[index++] = (flag & ptr->flag) ? ptr->opt : '-'; 128a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma toybuf[index] = '\0'; 129a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xprintf("%s %s\n", toybuf, path); 130a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 131a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 132a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xclose(fd); 133a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return; 134a547cf11686a878d2fd1a42a05719b78903009adAshwini SharmaLABEL2: xclose(fd); 135a547cf11686a878d2fd1a42a05719b78903009adAshwini SharmaLABEL1: perror_msg("reading '%s'", path); 136a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 137a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 138a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Get directory information. 139a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic int retell_dir(struct dirtree *root) 140a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 141a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char *fpath = NULL; 142a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 143fec3fd1f8ac1db9ed87b79bd3eb5e38aa835e881Rob Landley if (root->again) { 144a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xputc('\n'); 145a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return 0; 146a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 147a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (S_ISDIR(root->st.st_mode) && !root->parent) 148a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return (DIRTREE_RECURSE | DIRTREE_COMEAGAIN); 149a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 150a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma fpath = dirtree_path(root, NULL); 151a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma //Special case: with '-a' option and '.'/'..' also included in printing list. 152a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if ((root->name[0] != '.') || (toys.optflags & FLAG_a)) { 153a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma print_file_attr(fpath); 154a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (S_ISDIR(root->st.st_mode) && (toys.optflags & FLAG_R) 155a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma && dirtree_notdotdot(root)) { 156a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xprintf("\n%s:\n", fpath); 157a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma free(fpath); 158a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return (DIRTREE_RECURSE | DIRTREE_COMEAGAIN); 159a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 160a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 161a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma free(fpath); 162a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return 0; 163a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 164a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 165a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmavoid lsattr_main(void) 166a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 167a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!*toys.optargs) dirtree_read(".", retell_dir); 168a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma else 169a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (; *toys.optargs; toys.optargs++) { 170a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma struct stat sb; 171a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 172a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (lstat(*toys.optargs, &sb)) perror_msg("stat '%s'", *toys.optargs); 173a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma else if (S_ISDIR(sb.st_mode) && !(toys.optflags & FLAG_d)) 174a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma dirtree_read(*toys.optargs, retell_dir); 175a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma else print_file_attr(*toys.optargs);// to handle "./Filename" or "./Dir" 176a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 177a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 178a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 179a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Switch gears from lsattr to chattr. 180a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#define CLEANUP_lsattr 181a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#define FOR_chattr 182a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma#include "generated/flags.h" 183a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 184a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic struct _chattr { 185a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma unsigned long add, rm, set, version; 186a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma unsigned char vflag, recursive; 187a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} chattr; 188a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 189a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic inline void chattr_help(void) 190a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 191a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma toys.exithelp++; 192a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma error_exit("Invalid Argument"); 193a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 194a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 195a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Set file flags on a Linux second extended file system. 196a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic inline int ext2_setflag(int fd, struct stat *sb, unsigned long flag) 197a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 198a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!S_ISREG(sb->st_mode) && !S_ISDIR(sb->st_mode)) { 199a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma errno = EOPNOTSUPP; 200a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return -1; 201a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 202a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return (ioctl(fd, FS_IOC_SETFLAGS, (void*)&flag)); 203a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 204a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 205a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic unsigned long get_flag_val(char ch) 206a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 207a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma struct ext2_attr *ptr = e2attrs; 208a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 209a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (; ptr->name; ptr++) 210a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ptr->opt == ch) return ptr->flag; 211a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr_help(); // if no match found then Show help 212a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return 0; // silent warning. 213a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 214a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 215a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Parse command line argument and fill the chattr structure. 216a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic void parse_cmdline_arg(char ***argv) 217a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 218a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char *arg = **argv, *ptr = NULL; 219a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 220a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma while (arg) { 221a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma switch (arg[0]) { 222a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma case '-': 223a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (ptr = ++arg; *ptr; ptr++) { 224a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (*ptr == 'R') { 225a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr.recursive = 1; 226a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma continue; 227a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } else if (*ptr == 'v') {// get version from next argv. 228a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char *endptr; 229a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 230a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma errno = 0; 231a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma arg = *(*argv += 1); 232a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!arg) chattr_help(); 233a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (*arg == '-') perror_exit("Invalid Number '%s'", arg); 234a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr.version = strtoul(arg, &endptr, 0); 235a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (errno || *endptr) perror_exit("bad version '%s'", arg); 236a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr.vflag = 1; 237a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma continue; 238a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } else chattr.rm |= get_flag_val(*ptr); 239a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 240a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma break; 241a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma case '+': 242a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (ptr = ++arg; *ptr; ptr++) 243a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr.add |= get_flag_val(*ptr); 244a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma break; 245a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma case '=': 246a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (ptr = ++arg; *ptr; ptr++) 247a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma chattr.set |= get_flag_val(*ptr); 248a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma break; 249a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma default: return; 250a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 251a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma arg = *(*argv += 1); 252a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 253a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 254a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 255a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma// Update attribute of given file. 256a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmastatic int update_attr(struct dirtree *root) 257a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 258a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma unsigned long fval = 0; 259a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char *fpath = NULL; 260a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma int fd; 261a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 262a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!dirtree_notdotdot(root)) return 0; 263a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 264a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma /* 265a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * if file is a link and recursive is set or file is not regular+link+dir 266a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma * (like fifo or dev file) then escape the file. 267a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma */ 268a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if ((S_ISLNK(root->st.st_mode) && chattr.recursive) 269a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma || (!S_ISREG(root->st.st_mode) && !S_ISLNK(root->st.st_mode) 270a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma && !S_ISDIR(root->st.st_mode))) 271a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return 0; 272a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 273a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma fpath = dirtree_path(root, NULL); 274a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (-1 == (fd=open(fpath, O_RDONLY | O_NONBLOCK))) { 275a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma free(fpath); 276a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return DIRTREE_ABORT; 277a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 278a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma // Get current attr of file. 279a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ext2_getflag(fd, &(root->st), &fval) < 0) { 280a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma perror_msg("read flags of '%s'", fpath); 281a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma free(fpath); 282a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xclose(fd); 283a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return DIRTREE_ABORT; 284a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 285a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (chattr.set) { // for '=' operator. 286a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ext2_setflag(fd, &(root->st), chattr.set) < 0) 287a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma perror_msg("setting flags '%s'", fpath); 288a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } else { // for '-' / '+' operator. 289a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma fval &= ~(chattr.rm); 290a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma fval |= chattr.add; 291a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!S_ISDIR(root->st.st_mode)) fval &= ~FS_DIRSYNC_FL; 292a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ext2_setflag(fd, &(root->st), fval) < 0) 293a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma perror_msg("setting flags '%s'", fpath); 294a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 295a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (chattr.vflag) { // set file version 296a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (ioctl(fd, FS_IOC_SETVERSION, (void*)&chattr.version) < 0) 297a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma perror_msg("while setting version on '%s'", fpath); 298a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma } 299a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma free(fpath); 300a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma xclose(fd); 301a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 302a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (S_ISDIR(root->st.st_mode) && chattr.recursive) return DIRTREE_RECURSE; 303a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma return 0; 304a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 305a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 306a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharmavoid chattr_main(void) 307a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma{ 308a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma char **argv = toys.optargs; 309a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma 310a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma memset(&chattr, 0, sizeof(struct _chattr)); 311a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma parse_cmdline_arg(&argv); 312a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!*argv) chattr_help(); 313a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (chattr.set && (chattr.add || chattr.rm)) 314a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma error_exit("'=' is incompatible with '-' and '+'"); 315a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (chattr.rm & chattr.add) error_exit("Can't set and unset same flag."); 316a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma if (!(chattr.add || chattr.rm || chattr.set || chattr.vflag)) 317a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma error_exit(("Must use '-v', '=', '-' or '+'")); 318a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma for (; *argv; argv++) dirtree_read(*argv, update_attr); 319a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma toys.exitval = 0; //always set success at this point. 320a547cf11686a878d2fd1a42a05719b78903009adAshwini Sharma} 321