1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/** quotaio.c 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Generic IO operations on quotafiles 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Jan Kara <jack@suse.cz> - sponsored by SuSE CR 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Aditya Kali <adityakali@google.com> - Ported to e2fsprogs 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdio.h> 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdlib.h> 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <time.h> 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/types.h> 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/file.h> 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "common.h" 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "quotaio.h" 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic const char * const extensions[MAXQUOTAS] = {"user", "group"}; 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic const char * const basenames[] = { 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "", /* undefined */ 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "quota", /* QFMT_VFS_OLD */ 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "aquota", /* QFMT_VFS_V0 */ 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "", /* QFMT_OCFS2 */ 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "aquota" /* QFMT_VFS_V1 */ 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Header in all newer quotafiles */ 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct disk_dqheader { 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall u_int32_t dqh_magic; 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall u_int32_t dqh_version; 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} __attribute__ ((packed)); 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/** 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Convert type of quota to written representation 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallconst char *type2name(int type) 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return extensions[type]; 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/** 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Creates a quota file name for given type and format. 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallconst char *quota_get_qf_name(int type, int fmt, char *buf) 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!buf) 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return NULL; 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall snprintf(buf, QUOTA_NAME_LEN, "%s.%s", 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall basenames[fmt], extensions[type]); 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return buf; 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallconst char *quota_get_qf_path(const char *mntpt, int qtype, int fmt, 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *path_buf, size_t path_buf_size) 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char qf_name[QUOTA_NAME_LEN]; 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!mntpt || !path_buf || !path_buf_size) 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return NULL; 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(path_buf, mntpt, path_buf_size); 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncat(path_buf, "/", 1); 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncat(path_buf, quota_get_qf_name(qtype, fmt, qf_name), 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall path_buf_size - strlen(path_buf)); 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return path_buf; 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Set grace time if needed 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid update_grace_times(struct dquot *q) 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall time_t now; 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall time(&now); 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (q->dq_dqb.dqb_bsoftlimit && toqb(q->dq_dqb.dqb_curspace) > 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_bsoftlimit) { 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!q->dq_dqb.dqb_btime) 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_btime = 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall now + q->dq_h->qh_info.dqi_bgrace; 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_btime = 0; 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (q->dq_dqb.dqb_isoftlimit && q->dq_dqb.dqb_curinodes > 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_isoftlimit) { 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!q->dq_dqb.dqb_itime) 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_itime = 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall now + q->dq_h->qh_info.dqi_igrace; 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall q->dq_dqb.dqb_itime = 0; 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int compute_num_blocks_proc(ext2_filsys fs, blk64_t *blocknr, 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ref_offset EXT2FS_ATTR((unused)), 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *private) 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *num_blocks = private; 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *num_blocks += 1; 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino) 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode inode; 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((err = ext2fs_read_inode(fs, ino, &inode))) 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((ino == EXT4_USR_QUOTA_INO) || (ino == EXT4_GRP_QUOTA_INO)) { 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_dtime = fs->now ? fs->now : time(0); 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_punch(fs, ino, &inode, NULL, 0, ~0ULL); 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->flags &= ~EXT2_FLAG_SUPER_ONLY; 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&inode, 0, sizeof(struct ext2_inode)); 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_flags &= ~EXT2_IMMUTABLE_FL; 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_write_inode(fs, ino, &inode); 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic ext2_off64_t compute_inode_size(ext2_filsys fs, ext2_ino_t ino) 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t num_blocks = 0; 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_iterate3(fs, ino, 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall BLOCK_FLAG_READ_ONLY, 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall NULL, 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall compute_num_blocks_proc, 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &num_blocks); 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return num_blocks * fs->blocksize; 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Functions to read/write quota file. */ 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int quota_write_nomount(struct quota_file *qf, 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_loff_t offset, 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *buf, unsigned int size) 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_file_t e2_file = qf->e2_file; 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int bytes_written = 0; 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL); 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_llseek failed: %ld", err); 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_write(e2_file, buf, size, &bytes_written); 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_write failed: %ld", err); 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Correct inode.i_size is set in end_io. */ 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return bytes_written; 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic unsigned int quota_read_nomount(struct quota_file *qf, 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_loff_t offset, 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *buf, unsigned int size) 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_file_t e2_file = qf->e2_file; 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int bytes_read = 0; 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_llseek(e2_file, offset, EXT2_SEEK_SET, NULL); 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_llseek failed: %ld", err); 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_read(e2_file, buf, size, &bytes_read); 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_read failed: %ld", err); 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return bytes_read; 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Detect quota format and initialize quota IO 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_file_open(struct quota_handle *h, ext2_filsys fs, 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t qf_ino, int type, int fmt, int flags) 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_file_t e2_file; 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fmt == -1) 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fmt = QFMT_VFS_V1; 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_read_bitmaps(fs); 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("Opening quota ino=%lu, type=%d", qf_ino, type); 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_open(fs, qf_ino, flags, &e2_file); 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_open failed: %s", error_message(err)); 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.e2_file = e2_file; 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.fs = fs; 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.ino = qf_ino; 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->e2fs_write = quota_write_nomount; 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->e2fs_read = quota_read_nomount; 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_io_flags = 0; 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_type = type; 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_fmt = fmt; 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&h->qh_info, 0, sizeof(h->qh_info)); 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_ops = "afile_ops_2; 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_ops->check_file && 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (h->qh_ops->check_file(h, type, fmt) == 0)) { 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("qh_ops->check_file failed"); 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(e2_file); 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_ops->init_io && (h->qh_ops->init_io(h) < 0)) { 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("qh_ops->init_io failed"); 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(e2_file); 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t quota_inode_init_new(ext2_filsys fs, ext2_ino_t ino) 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode inode; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err = 0; 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_read_inode(fs, ino, &inode); 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ex2fs_read_inode failed"); 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (EXT2_I_SIZE(&inode)) 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_inode_truncate(fs, ino); 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&inode, 0, sizeof(struct ext2_inode)); 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_iblk_set(fs, &inode, 0); 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_atime = inode.i_mtime = 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_ctime = fs->now ? fs->now : time(0); 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_links_count = 1; 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_mode = LINUX_S_IFREG | 0600; 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_flags |= EXT2_IMMUTABLE_FL; 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT3_FEATURE_INCOMPAT_EXTENTS) 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode.i_flags |= EXT4_EXTENTS_FL; 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_write_new_inode(fs, ino, &inode); 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_write_new_inode failed: %ld", err); 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Create new quotafile of specified format on given filesystem 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs, int type, int fmt) 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_file_t e2_file; 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int err; 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long qf_inum; 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fmt == -1) 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fmt = QFMT_VFS_V1; 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.fs = fs; 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (type == USRQUOTA) 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qf_inum = EXT4_USR_QUOTA_INO; 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (type == GRPQUOTA) 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall qf_inum = EXT4_GRP_QUOTA_INO; 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_read_bitmaps(fs); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out_err; 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = quota_inode_init_new(fs, qf_inum); 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("init_new_quota_inode failed"); 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out_err; 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.ino = qf_inum; 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->e2fs_write = quota_write_nomount; 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->e2fs_read = quota_read_nomount; 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_debug("Creating quota ino=%lu, type=%d", qf_inum, type); 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = ext2fs_file_open(fs, qf_inum, 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_FILE_WRITE | EXT2_FILE_CREATE, &e2_file); 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) { 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("ext2fs_file_open failed: %d", err); 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out_err; 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_qf.e2_file = e2_file; 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_io_flags = 0; 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_type = type; 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_fmt = fmt; 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&h->qh_info, 0, sizeof(h->qh_info)); 325e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_ops = "afile_ops_2; 326e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 327e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_ops->new_io && (h->qh_ops->new_io(h) < 0)) { 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("qh_ops->new_io failed"); 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto out_err1; 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 334e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout_err1: 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(e2_file); 336e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout_err: 337e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 338e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (qf_inum) 339e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall quota_inode_truncate(fs, qf_inum); 340e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 341e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 342e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 343e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Close quotafile and release handle 346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t quota_file_close(struct quota_handle *h) 348e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_io_flags & IOFL_INFODIRTY) { 350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_ops->write_info && h->qh_ops->write_info(h) < 0) 351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall h->qh_io_flags &= ~IOFL_INFODIRTY; 353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_ops->end_io && h->qh_ops->end_io(h) < 0) 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return -1; 357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (h->qh_qf.e2_file) { 358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_flush(h->qh_qf.e2_file); 359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_set_size2(h->qh_qf.e2_file, 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall compute_inode_size(h->qh_qf.fs, h->qh_qf.ino)); 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_close(h->qh_qf.e2_file); 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 365e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 366e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 367e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 368e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Create empty quota structure 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct dquot *get_empty_dquot(void) 371e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 372e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dquot *dquot; 373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_get_memzero(sizeof(struct dquot), &dquot)) { 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall log_err("Failed to allocate dquot"); 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return NULL; 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 379e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dquot->dq_id = -1; 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return dquot; 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 382