pmt: initial 2.9.1 update

This commit is contained in:
2024-10-02 21:37:57 +03:00
parent 82bd2939cd
commit 7259d451c4
459 changed files with 86355 additions and 2404 deletions

View File

@@ -0,0 +1,43 @@
/*
* argv_parse.h --- header file for the argv parser.
*
* This file defines the interface for the functions argv_parse() and
* argv_free().
*
***********************************************************************
* int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
*
* This function takes as its first argument a string which it will
* parse into an argv argument vector, with each white-space separated
* word placed into its own slot in the argv. This function handles
* double quotes and backslashes so that the parsed words can contain
* special characters. The count of the number words found in the
* parsed string, as well as the argument vector, are returned into
* ret_argc and ret_argv, respectively.
***********************************************************************
* extern void argv_free(char **argv);
*
* This function frees the argument vector created by argv_parse().
***********************************************************************
*
* Copyright 1999 by Theodore Ts'o.
*
* Permission to use, copy, modify, and distribute this software for
* any purpose with or without fee is hereby granted, provided that
* the above copyright notice and this permission notice appear in all
* copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
* AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't
* it sick that the U.S. culture of lawsuit-happy lawyers requires
* this kind of disclaimer?)
*
* Version 1.1, modified 2/27/1999
*/
extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv);
extern void argv_free(char **argv);

View File

@@ -0,0 +1,36 @@
/*
*
* Various things common for all utilities
*
*/
#ifndef __QUOTA_COMMON_H__
#define __QUOTA_COMMON_H__
#if EXT2_FLAT_INCLUDES
#include "e2_types.h"
#else
#include <ext2fs/ext2_types.h>
#endif /* EXT2_FLAT_INCLUDES */
/* #define DEBUG_QUOTA 1 */
#ifndef __attribute__
# if !defined __GNUC__ || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
# define __attribute__(x)
# endif
#endif
#define log_err(format, arg ...) \
fprintf(stderr, "[ERROR] %s:%d:%s: " format "\n", \
__FILE__, __LINE__, __func__, ## arg)
#ifdef DEBUG_QUOTA
# define log_debug(format, arg ...) \
fprintf(stderr, "[DEBUG] %s:%d:%s: " format "\n", \
__FILE__, __LINE__, __func__, ## arg)
#else
# define log_debug(...)
#endif
#endif /* __QUOTA_COMMON_H__ */

View File

@@ -0,0 +1,6 @@
/*
* cstring.h -- header file for C string parse/print utilities
*/
extern int parse_c_string(char *str);
extern void print_c_string(FILE *f, const char *cp, int len);

View File

@@ -0,0 +1,19 @@
/*
* devname.c --- Figure out if a pathname is ext* or something else.
*
* Copyright (C) 2022 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com>
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#ifndef DEVNAME_H_
#define DEVNAME_H_
#include "blkid/blkid.h"
char *get_devname(blkid_cache cache, const char *token, const char *value);
#endif /* DEVNAME_H_ */

147
include/e2fsprogs/support/dict.h Executable file
View File

@@ -0,0 +1,147 @@
/*
* Dictionary Abstract Data Type
* Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
*
* Free Software License:
*
* All rights are reserved by the author, with the following exceptions:
* Permission is granted to freely reproduce and distribute this software,
* possibly in exchange for a fee, provided that this copyright notice appears
* intact. Permission is also granted to adapt this software to produce
* derivative works, as long as the modified versions carry this copyright
* notice and additional notices stating that the work has been modified.
* This source code may be translated into executable form and incorporated
* into proprietary software; there is no requirement for such software to
* contain a copyright notice related to this source.
*
* $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $
* $Name: kazlib_1_20 $
* The work has been modified.
*/
#ifndef DICT_H
#define DICT_H
#include <limits.h>
#ifdef KAZLIB_SIDEEFFECT_DEBUG
#include "sfx.h"
#endif
/*
* Blurb for inclusion into C++ translation units
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned long dictcount_t;
#define DICTCOUNT_T_MAX ULONG_MAX
/*
* The dictionary is implemented as a red-black tree
*/
typedef enum { dnode_red, dnode_black } dnode_color_t;
typedef struct dnode_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
struct dnode_t *dict_left;
struct dnode_t *dict_right;
struct dnode_t *dict_parent;
dnode_color_t dict_color;
const void *dict_key;
void *dict_data;
#else
int dict_dummy;
#endif
} dnode_t;
typedef int (*dict_comp_t)(const void *, const void *, const void *);
typedef dnode_t *(*dnode_alloc_t)(void *);
typedef void (*dnode_free_t)(dnode_t *, void *);
typedef struct dict_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
dnode_t dict_nilnode;
dictcount_t dict_nodecount;
dictcount_t dict_maxcount;
dict_comp_t dict_compare;
dnode_alloc_t dict_allocnode;
dnode_free_t dict_freenode;
void *dict_context;
const void *cmp_ctx;
int dict_dupes;
#else
int dict_dummmy;
#endif
} dict_t;
typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
typedef struct dict_load_t {
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
dict_t *dict_dictptr;
dnode_t dict_nilnode;
#else
int dict_dummmy;
#endif
} dict_load_t;
extern dict_t *dict_create(dictcount_t, dict_comp_t);
extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *);
extern void dict_set_cmp_context(dict_t *, const void *);
extern void dict_destroy(dict_t *);
extern void dict_free_nodes(dict_t *);
extern void dict_free(dict_t *);
extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t);
extern void dict_init_like(dict_t *, const dict_t *);
extern int dict_verify(dict_t *);
extern int dict_similar(const dict_t *, const dict_t *);
extern dnode_t *dict_lookup(dict_t *, const void *);
extern dnode_t *dict_lower_bound(dict_t *, const void *);
extern dnode_t *dict_upper_bound(dict_t *, const void *);
extern void dict_insert(dict_t *, dnode_t *, const void *);
extern dnode_t *dict_delete(dict_t *, dnode_t *);
extern int dict_alloc_insert(dict_t *, const void *, void *);
extern void dict_delete_free(dict_t *, dnode_t *);
extern dnode_t *dict_first(dict_t *);
extern dnode_t *dict_last(dict_t *);
extern dnode_t *dict_next(dict_t *, dnode_t *);
extern dnode_t *dict_prev(dict_t *, dnode_t *);
extern dictcount_t dict_count(dict_t *);
extern int dict_isempty(dict_t *);
extern int dict_isfull(dict_t *);
extern int dict_contains(dict_t *, dnode_t *);
extern void dict_allow_dupes(dict_t *);
extern int dnode_is_in_a_dict(dnode_t *);
extern dnode_t *dnode_create(void *);
extern dnode_t *dnode_init(dnode_t *, void *);
extern void dnode_destroy(dnode_t *);
extern void *dnode_get(dnode_t *);
extern const void *dnode_getkey(dnode_t *);
extern void dnode_put(dnode_t *, void *);
extern void dict_process(dict_t *, void *, dnode_process_t);
extern void dict_load_begin(dict_load_t *, dict_t *);
extern void dict_load_next(dict_load_t *, dnode_t *, const void *);
extern void dict_load_end(dict_load_t *);
extern void dict_merge(dict_t *, dict_t *);
#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG)
#ifdef KAZLIB_SIDEEFFECT_DEBUG
#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount)
#else
#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount)
#endif
#define dict_count(D) ((D)->dict_nodecount)
#define dict_isempty(D) ((D)->dict_nodecount == 0)
#define dnode_get(N) ((N)->dict_data)
#define dnode_getkey(N) ((N)->dict_key)
#define dnode_put(N, X) ((N)->dict_data = (X))
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,31 @@
/*
* Header file for disk format of new quotafile format
*
* Jan Kara <jack@suse.cz> - sponsored by SuSE CR
*/
#ifndef __QUOTA_DQBLK_V2_H__
#define __QUOTA_DQBLK_V2_H__
#include "quotaio_tree.h"
/* Structure for format specific information */
struct v2_mem_dqinfo {
struct qtree_mem_dqinfo dqi_qtree;
unsigned int dqi_flags; /* Flags set in quotafile */
unsigned int dqi_used_entries; /* Number of entries in file -
updated by scan_dquots */
unsigned int dqi_data_blocks; /* Number of data blocks in file -
updated by scan_dquots */
};
struct v2_mem_dqblk {
long long dqb_off; /* Offset of dquot in file */
};
struct quotafile_ops; /* Will be defined later in quotaio.h */
/* Operations above this format */
extern struct quotafile_ops quotafile_ops_2;
#endif /* __QUOTA_DQBLK_V2_H__ */

View File

@@ -0,0 +1,21 @@
#if defined(ENABLE_NLS) && !defined(DEBUGFS)
#include <libintl.h>
#include <locale.h>
#define _(a) (gettext (a))
#ifdef gettext_noop
#define N_(a) gettext_noop (a)
#else
#define N_(a) (a)
#endif
#define P_(singular, plural, n) (ngettext (singular, plural, n))
#ifndef NLS_CAT_NAME
#define NLS_CAT_NAME "e2fsprogs"
#endif
#ifndef LOCALEDIR
#define LOCALEDIR "/usr/share/locale"
#endif
#else
#define _(a) (a)
#define N_(a) a
#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural))
#endif

View File

@@ -0,0 +1,29 @@
/*
* plausible.h --- header file defining prototypes for helper functions
* used by tune2fs and mke2fs
*
* Copyright 2014 by Oracle, Inc.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
#ifndef PLAUSIBLE_H_
#define PLAUSIBLE_H_
/*
* Flags for check_plausibility()
*/
#define CHECK_BLOCK_DEV 0x0001
#define CREATE_FILE 0x0002
#define CHECK_FS_EXIST 0x0004
#define VERBOSE_CREATE 0x0008
#define NO_SIZE 0x0010
#define QUIET_CHECK 0x0020
extern int check_plausibility(const char *device, int flags,
int *ret_is_dev);
#endif /* PLAUSIBLE_H_ */

View File

@@ -0,0 +1,5 @@
/*
* print_flags.h -- header file for printing the fs flags
*/
void print_fs_flags(FILE * f, unsigned long flags);

View File

@@ -0,0 +1,49 @@
/*
* prof_err.h:
* This file is automatically generated; please do not edit it.
*/
#include <et/com_err.h>
#define PROF_VERSION (-1429577728L)
#define PROF_MAGIC_NODE (-1429577727L)
#define PROF_NO_SECTION (-1429577726L)
#define PROF_NO_RELATION (-1429577725L)
#define PROF_ADD_NOT_SECTION (-1429577724L)
#define PROF_SECTION_WITH_VALUE (-1429577723L)
#define PROF_BAD_LINK_LIST (-1429577722L)
#define PROF_BAD_GROUP_LVL (-1429577721L)
#define PROF_BAD_PARENT_PTR (-1429577720L)
#define PROF_MAGIC_ITERATOR (-1429577719L)
#define PROF_SET_SECTION_VALUE (-1429577718L)
#define PROF_EINVAL (-1429577717L)
#define PROF_READ_ONLY (-1429577716L)
#define PROF_SECTION_NOTOP (-1429577715L)
#define PROF_SECTION_SYNTAX (-1429577714L)
#define PROF_RELATION_SYNTAX (-1429577713L)
#define PROF_EXTRA_CBRACE (-1429577712L)
#define PROF_MISSING_OBRACE (-1429577711L)
#define PROF_MAGIC_PROFILE (-1429577710L)
#define PROF_MAGIC_SECTION (-1429577709L)
#define PROF_TOPSECTION_ITER_NOSUPP (-1429577708L)
#define PROF_INVALID_SECTION (-1429577707L)
#define PROF_END_OF_SECTIONS (-1429577706L)
#define PROF_BAD_NAMESET (-1429577705L)
#define PROF_NO_PROFILE (-1429577704L)
#define PROF_MAGIC_FILE (-1429577703L)
#define PROF_FAIL_OPEN (-1429577702L)
#define PROF_EXISTS (-1429577701L)
#define PROF_BAD_BOOLEAN (-1429577700L)
#define PROF_BAD_INTEGER (-1429577699L)
#define PROF_MAGIC_FILE_DATA (-1429577698L)
extern const struct error_table et_prof_error_table;
extern void initialize_prof_error_table(void);
/* For compatibility with Heimdal */
extern void initialize_prof_error_table_r(struct et_list **list);
#define ERROR_TABLE_BASE_prof (-1429577728L)
/* for compatibility with older versions... */
#define init_prof_err_tbl initialize_prof_error_table
#define prof_err_base ERROR_TABLE_BASE_prof

View File

@@ -0,0 +1,107 @@
/*
* profile.h
*
* Copyright (C) 2005 by Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*
* Copyright (C) 1985-2005 by the Massachusetts Institute of Technology.
*
* All rights reserved.
*
* Export of this software from the United States of America may require
* a specific license from the United States Government. It is the
* responsibility of any person or organization contemplating export to
* obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original MIT software.
* M.I.T. makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef _PROFILE_H
#define _PROFILE_H
typedef struct _profile_t *profile_t;
typedef void (*profile_syntax_err_cb_t)(const char *file, long err,
int line_num);
/*
* Used by the profile iterator in prof_get.c
*/
#define PROFILE_ITER_LIST_SECTION 0x0001
#define PROFILE_ITER_SECTIONS_ONLY 0x0002
#define PROFILE_ITER_RELATIONS_ONLY 0x0004
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
long profile_init
(const char * const *files, profile_t *ret_profile);
void profile_release
(profile_t profile);
long profile_set_default
(profile_t profile, const char *def_string);
long profile_get_string
(profile_t profile, const char *name, const char *subname,
const char *subsubname, const char *def_val,
char **ret_string);
long profile_get_integer
(profile_t profile, const char *name, const char *subname,
const char *subsubname, int def_val,
int *ret_default);
long profile_get_uint
(profile_t profile, const char *name, const char *subname,
const char *subsubname, unsigned int def_val,
unsigned int *ret_int);
long profile_get_double
(profile_t profile, const char *name, const char *subname,
const char *subsubname, double def_val,
double *ret_float);
long profile_get_boolean
(profile_t profile, const char *name, const char *subname,
const char *subsubname, int def_val,
int *ret_default);
long profile_iterator_create
(profile_t profile, const char *const *names,
int flags, void **ret_iter);
void profile_iterator_free
(void **iter_p);
long profile_iterator
(void **iter_p, char **ret_name, char **ret_value);
profile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _KRB5_H */

View File

@@ -0,0 +1,28 @@
/*
* profile_helpers.h -- Function prototypes for profile helper functions
*
* Copyright (C) 2006 by Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Public
* License.
* %End-Header%
*/
long profile_get_values
(profile_t profile, const char *const *names, char ***ret_values);
void profile_free_list
(char **list);
long profile_get_relation_names
(profile_t profile, const char **names, char ***ret_names);
long profile_get_subsection_names
(profile_t profile, const char **names, char ***ret_names);
void profile_release_string (char *str);
long profile_init_path
(const char * filelist, profile_t *ret_profile);

View File

@@ -0,0 +1,268 @@
/** quotaio.h
*
* Interface to the quota library.
*
* The quota library provides interface for creating and updating the quota
* files and the ext4 superblock fields. It supports the new VFS_V1 quota
* format. The quota library also provides support for keeping track of quotas
* in memory.
* The typical way to use the quota library is as follows:
* {
* quota_ctx_t qctx;
*
* quota_init_context(&qctx, fs, QUOTA_ALL_BIT);
* {
* quota_compute_usage(qctx);
* AND/OR
* quota_data_add/quota_data_sub/quota_data_inodes();
* }
* quota_write_inode(qctx, USRQUOTA);
* quota_write_inode(qctx, GRPQUOTA);
* quota_release_context(&qctx);
* }
*
* This initial version does not support reading the quota files. This support
* will be added in near future.
*
* Aditya Kali <adityakali@google.com>
* Header of IO operations for quota utilities
*
* Jan Kara <jack@suse.cz>
*/
#ifndef GUARD_QUOTAIO_H
#define GUARD_QUOTAIO_H
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ext2fs/ext2_fs.h"
#include "ext2fs/ext2fs.h"
#include "dqblk_v2.h"
typedef int64_t qsize_t; /* Type in which we store size limitations */
enum quota_type {
USRQUOTA = 0,
GRPQUOTA = 1,
PRJQUOTA = 2,
MAXQUOTAS = 3,
};
#if MAXQUOTAS > 32
#error "cannot have more than 32 quota types to fit in qtype_bits"
#endif
#define QUOTA_USR_BIT (1 << USRQUOTA)
#define QUOTA_GRP_BIT (1 << GRPQUOTA)
#define QUOTA_PRJ_BIT (1 << PRJQUOTA)
#define QUOTA_ALL_BIT (QUOTA_USR_BIT | QUOTA_GRP_BIT | QUOTA_PRJ_BIT)
typedef struct quota_ctx *quota_ctx_t;
struct dict_t;
struct quota_ctx {
ext2_filsys fs;
struct dict_t *quota_dict[MAXQUOTAS];
struct quota_handle *quota_file[MAXQUOTAS];
};
/*
* Definitions of magics and versions of current quota files
*/
#define INITQMAGICS {\
0xd9c01f11, /* USRQUOTA */\
0xd9c01927, /* GRPQUOTA */\
0xd9c03f14 /* PRJQUOTA */\
}
/* Size of blocks in which are counted size limits in generic utility parts */
#define QUOTABLOCK_BITS 10
#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
/* Quota format type IDs */
#define QFMT_VFS_OLD 1
#define QFMT_VFS_V0 2
#define QFMT_VFS_V1 4
/*
* The following constants define the default amount of time given a user
* before the soft limits are treated as hard limits (usually resulting
* in an allocation failure). The timer is started when the user crosses
* their soft limit, it is reset when they go below their soft limit.
*/
#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
#define IOFL_INFODIRTY 0x01 /* Did info change? */
struct quotafile_ops;
/* Generic information about quotafile */
struct util_dqinfo {
time_t dqi_bgrace; /* Block grace time for given quotafile */
time_t dqi_igrace; /* Inode grace time for given quotafile */
union {
struct v2_mem_dqinfo v2_mdqi;
} u; /* Format specific info about quotafile */
};
struct quota_file {
ext2_filsys fs;
ext2_ino_t ino;
ext2_file_t e2_file;
};
/* Structure for one opened quota file */
struct quota_handle {
enum quota_type qh_type; /* Type of quotafile */
int qh_fmt; /* Quotafile format */
int qh_file_flags;
int qh_io_flags; /* IO flags for file */
struct quota_file qh_qf;
unsigned int (*e2fs_read)(struct quota_file *qf, ext2_loff_t offset,
void *buf, unsigned int size);
unsigned int (*e2fs_write)(struct quota_file *qf, ext2_loff_t offset,
void *buf, unsigned int size);
struct quotafile_ops *qh_ops; /* Operations on quotafile */
struct util_dqinfo qh_info; /* Generic quotafile info */
};
/* Utility quota block */
struct util_dqblk {
qsize_t dqb_ihardlimit;
qsize_t dqb_isoftlimit;
qsize_t dqb_curinodes;
qsize_t dqb_bhardlimit;
qsize_t dqb_bsoftlimit;
qsize_t dqb_curspace;
time_t dqb_btime;
time_t dqb_itime;
union {
struct v2_mem_dqblk v2_mdqb;
} u; /* Format specific dquot information */
};
/* Structure for one loaded quota */
struct dquot {
struct dquot *dq_next; /* Pointer to next dquot in the list */
qid_t dq_id; /* ID dquot belongs to */
int dq_flags; /* Some flags for utils */
struct quota_handle *dq_h; /* Handle of quotafile for this dquot */
struct util_dqblk dq_dqb; /* Parsed data of dquot */
};
#define DQF_SEEN 0x0001
/* Structure of quotafile operations */
struct quotafile_ops {
/* Check whether quotafile is in our format */
int (*check_file) (struct quota_handle *h, int type, int fmt);
/* Open quotafile */
int (*init_io) (struct quota_handle *h);
/* Create new quotafile */
int (*new_io) (struct quota_handle *h);
/* Write all changes and close quotafile */
int (*end_io) (struct quota_handle *h);
/* Write info about quotafile */
int (*write_info) (struct quota_handle *h);
/* Read dquot into memory */
struct dquot *(*read_dquot) (struct quota_handle *h, qid_t id);
/* Write given dquot to disk */
int (*commit_dquot) (struct dquot *dquot);
/* Scan quotafile and call callback on every structure */
int (*scan_dquots) (struct quota_handle *h,
int (*process_dquot) (struct dquot *dquot,
void *data),
void *data);
/* Function to print format specific file information */
int (*report) (struct quota_handle *h, int verbose);
};
/* This might go into a special header file but that sounds a bit silly... */
extern struct quotafile_ops quotafile_ops_meta;
/* Open existing quotafile of given type (and verify its format) on given
* filesystem. */
errcode_t quota_file_open(quota_ctx_t qctx, struct quota_handle *h,
ext2_ino_t qf_ino, enum quota_type type,
int fmt, int flags);
/* Create new quotafile of specified format on given filesystem */
errcode_t quota_file_create(struct quota_handle *h, ext2_filsys fs,
enum quota_type qtype, int fmt);
/* Close quotafile */
errcode_t quota_file_close(quota_ctx_t qctx, struct quota_handle *h);
/* Get empty quota structure */
struct dquot *get_empty_dquot(void);
errcode_t quota_inode_truncate(ext2_filsys fs, ext2_ino_t ino);
const char *quota_type2name(enum quota_type qtype);
ext2_ino_t quota_type2inum(enum quota_type qtype, struct ext2_super_block *);
void update_grace_times(struct dquot *q);
/* size for the buffer returned by quota_get_qf_name(); must be greater
than maxlen of extensions[] and fmtnames[] (plus 2) found in quotaio.c */
#define QUOTA_NAME_LEN 16
const char *quota_get_qf_name(enum quota_type, int fmt, char *buf);
/* In mkquota.c */
errcode_t quota_init_context(quota_ctx_t *qctx, ext2_filsys fs,
unsigned int qtype_bits);
void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode,
ext2_ino_t ino, int adjust);
void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode,
ext2_ino_t ino, qsize_t space);
void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode,
ext2_ino_t ino, qsize_t space);
errcode_t quota_write_inode(quota_ctx_t qctx, enum quota_type qtype);
/* Flags for quota_read_all_dquots() */
#define QREAD_USAGE 0x01
#define QREAD_LIMITS 0x02
errcode_t quota_read_all_dquots(quota_ctx_t qctx, ext2_ino_t qf_ino,
enum quota_type type, unsigned int flags);
errcode_t quota_compute_usage(quota_ctx_t qctx);
void quota_release_context(quota_ctx_t *qctx);
errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype);
int quota_file_exists(ext2_filsys fs, enum quota_type qtype);
void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype);
errcode_t quota_compare_and_update(quota_ctx_t qctx, enum quota_type qtype,
int *usage_inconsistent);
int parse_quota_opts(const char *opts, int (*func)(char *));
/* parse_qtype.c */
int parse_quota_types(const char *in_str, unsigned int *qtype_bits,
char **err_token);
/*
* Return pointer to reserved inode field in superblock for given quota type.
*
* This allows the caller to get or set the quota inode by type without the
* need for the quota array to be contiguous in the superblock.
*/
static inline ext2_ino_t *quota_sb_inump(struct ext2_super_block *sb,
enum quota_type qtype)
{
switch (qtype) {
case USRQUOTA:
return &sb->s_usr_quota_inum;
case GRPQUOTA:
return &sb->s_grp_quota_inum;
case PRJQUOTA:
return &sb->s_prj_quota_inum;
default:
return NULL;
}
return NULL;
}
#endif /* GUARD_QUOTAIO_H */

View File

@@ -0,0 +1,64 @@
/*
* Definitions of structures for vfsv0 quota format
*/
#ifndef _LINUX_QUOTA_TREE_H
#define _LINUX_QUOTA_TREE_H
#include <sys/types.h>
typedef __u32 qid_t; /* Type in which we store ids in memory */
#define QT_TREEOFF 1 /* Offset of tree in file in blocks */
#define QT_TREEDEPTH 4 /* Depth of quota tree */
#define QT_BLKSIZE_BITS 10
#define QT_BLKSIZE (1 << QT_BLKSIZE_BITS) /* Size of block with quota
* structures */
/*
* Structure of header of block with quota structures. It is padded to 16 bytes
* so there will be space for exactly 21 quota-entries in a block
*/
struct qt_disk_dqdbheader {
__le32 dqdh_next_free; /* Number of next block with free
* entry */
__le32 dqdh_prev_free; /* Number of previous block with free
* entry */
__le16 dqdh_entries; /* Number of valid entries in block */
__le16 dqdh_pad1;
__le32 dqdh_pad2;
} __attribute__ ((packed));
struct dquot;
struct quota_handle;
/* Operations */
struct qtree_fmt_operations {
/* Convert given entry from in memory format to disk one */
void (*mem2disk_dqblk)(void *disk, struct dquot *dquot);
/* Convert given entry from disk format to in memory one */
void (*disk2mem_dqblk)(struct dquot *dquot, void *disk);
/* Is this structure for given id? */
int (*is_id)(void *disk, struct dquot *dquot);
};
/* In-memory copy of version specific information */
struct qtree_mem_dqinfo {
unsigned int dqi_blocks; /* # of blocks in quota file */
unsigned int dqi_free_blk; /* First block in list of free blocks */
unsigned int dqi_free_entry; /* First block with free entry */
unsigned int dqi_entry_size; /* Size of quota entry in quota file */
struct qtree_fmt_operations *dqi_ops; /* Operations for entry
* manipulation */
};
void qtree_write_dquot(struct dquot *dquot);
struct dquot *qtree_read_dquot(struct quota_handle *h, qid_t id);
void qtree_delete_dquot(struct dquot *dquot);
int qtree_entry_unused(struct qtree_mem_dqinfo *info, char *disk);
int qtree_scan_dquots(struct quota_handle *h,
int (*process_dquot) (struct dquot *, void *), void *data);
int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info);
#endif /* _LINUX_QUOTAIO_TREE_H */

View File

@@ -0,0 +1,69 @@
/*
*
* Header file for disk format of new quotafile format
*
*/
#ifndef GUARD_QUOTAIO_V2_H
#define GUARD_QUOTAIO_V2_H
#include <sys/types.h>
#include "quotaio.h"
/* Offset of info header in file */
#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader)
/* Supported version of quota-tree format */
#define V2_VERSION_R1 1
#define V2_VERSION_R0 0
struct v2_disk_dqheader {
__le32 dqh_magic; /* Magic number identifying file */
__le32 dqh_version; /* File version */
} __attribute__ ((packed));
/* Flags for version specific files */
#define V2_DQF_MASK 0x0000 /* Mask for all valid ondisk flags */
/* Header with type and version specific information */
struct v2_disk_dqinfo {
__le32 dqi_bgrace; /* Time before block soft limit becomes
* hard limit */
__le32 dqi_igrace; /* Time before inode soft limit becomes
* hard limit */
__le32 dqi_flags; /* Flags for quotafile (DQF_*) */
__le32 dqi_blocks; /* Number of blocks in file */
__le32 dqi_free_blk; /* Number of first free block in the list */
__le32 dqi_free_entry; /* Number of block with at least one
* free entry */
} __attribute__ ((packed));
struct v2r0_disk_dqblk {
__le32 dqb_id; /* id this quota applies to */
__le32 dqb_ihardlimit; /* absolute limit on allocated inodes */
__le32 dqb_isoftlimit; /* preferred inode limit */
__le32 dqb_curinodes; /* current # allocated inodes */
__le32 dqb_bhardlimit; /* absolute limit on disk space
* (in QUOTABLOCK_SIZE) */
__le32 dqb_bsoftlimit; /* preferred limit on disk space
* (in QUOTABLOCK_SIZE) */
__le64 dqb_curspace; /* current space occupied (in bytes) */
__le64 dqb_btime; /* time limit for excessive disk use */
__le64 dqb_itime; /* time limit for excessive inode use */
} __attribute__ ((packed));
struct v2r1_disk_dqblk {
__le32 dqb_id; /* id this quota applies to */
__le32 dqb_pad;
__le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
__le64 dqb_isoftlimit; /* preferred inode limit */
__le64 dqb_curinodes; /* current # allocated inodes */
__le64 dqb_bhardlimit; /* absolute limit on disk space
* (in QUOTABLOCK_SIZE) */
__le64 dqb_bsoftlimit; /* preferred limit on disk space
* (in QUOTABLOCK_SIZE) */
__le64 dqb_curspace; /* current space occupied (in bytes) */
__le64 dqb_btime; /* time limit for excessive disk use */
__le64 dqb_itime; /* time limit for excessive inode use */
} __attribute__ ((packed));
#endif

View File

@@ -0,0 +1,325 @@
/* Isaac Turner 29 April 2014 Public Domain */
#ifndef SORT_R_H_
#define SORT_R_H_
#include <stdlib.h>
#include <string.h>
/*
sort_r function to be exported.
Parameters:
base is the array to be sorted
nel is the number of elements in the array
width is the size in bytes of each element of the array
compar is the comparison function
arg is a pointer to be passed to the comparison function
void sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a, const void *_b, void *_arg),
void *arg);
*/
#define _SORT_R_INLINE inline
#if (defined HAVE_GNU_QSORT_R)
# define _SORT_R_GNU
#elif (defined HAVE_BSD_QSORT_R)
# define _SORT_R_BSD
#elif (defined __gnu_hurd__ || defined __GNU__ || \
defined __MINGW32__ || defined __GLIBC__)
# define _SORT_R_GNU
#elif (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \
defined __FreeBSD__ || defined __DragonFly__)
# define _SORT_R_BSD
#elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__)
# define _SORT_R_WINDOWS
# undef _SORT_R_INLINE
# define _SORT_R_INLINE __inline
#else
/* Using our own recursive quicksort sort_r_simple() */
#endif
#if (defined NESTED_QSORT && NESTED_QSORT == 0)
# undef NESTED_QSORT
#endif
#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
/* swap a and b */
/* a and b must not be equal! */
static _SORT_R_INLINE void sort_r_swap(char *__restrict a, char *__restrict b,
size_t w)
{
char tmp, *end = a+w;
for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
}
/* swap a, b iff a>b */
/* a and b must not be equal! */
/* __restrict is same as restrict but better support on old machines */
static _SORT_R_INLINE int sort_r_cmpswap(char *__restrict a,
char *__restrict b, size_t w,
int (*compar)(const void *_a,
const void *_b,
void *_arg),
void *arg)
{
if(compar(a, b, arg) > 0) {
sort_r_swap(a, b, w);
return 1;
}
return 0;
}
/*
Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
with the smallest swap so that the blocks are in the opposite order. Blocks may
be internally re-ordered e.g.
12345ab -> ab34512
123abc -> abc123
12abcde -> deabc12
*/
static _SORT_R_INLINE void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
{
if(na > 0 && nb > 0) {
if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
else { sort_r_swap(ptr, ptr+nb, na); }
}
}
/* Implement recursive quicksort ourselves */
/* Note: quicksort is not stable, equivalent values may be swapped */
static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w,
int (*compar)(const void *_a,
const void *_b,
void *_arg),
void *arg)
{
char *b = (char *)base, *end = b + nel*w;
/* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
printf("\n"); */
if(nel < 10) {
/* Insertion sort for arbitrarily small inputs */
char *pi, *pj;
for(pi = b+w; pi < end; pi += w) {
for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
}
}
else
{
/* nel > 6; Quicksort */
int cmp;
char *pl, *ple, *pr, *pre, *pivot;
char *last = b+w*(nel-1), *tmp;
/*
Use median of second, middle and second-last items as pivot.
First and last may have been swapped with pivot and therefore be extreme
*/
char *l[3];
l[0] = b + w;
l[1] = b+w*(nel/2);
l[2] = last - w;
/* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
if(compar(l[1],l[2],arg) > 0) {
SORT_R_SWAP(l[1], l[2], tmp);
if(compar(l[0],l[1],arg) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
}
/* swap mid value (l[1]), and last element to put pivot as last element */
if(l[1] != last) { sort_r_swap(l[1], last, w); }
/*
pl is the next item on the left to be compared to the pivot
pr is the last item on the right that was compared to the pivot
ple is the left position to put the next item that equals the pivot
ple is the last right position where we put an item that equals the pivot
v- end (beyond the array)
EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
^- b ^- ple ^- pl ^- pr ^- pre ^- last (where the pivot is)
Pivot comparison key:
E = equal, L = less than, u = unknown, G = greater than, E = equal
*/
pivot = last;
ple = pl = b;
pre = pr = last;
/*
Strategy:
Loop into the list from the left and right at the same time to find:
- an item on the left that is greater than the pivot
- an item on the right that is less than the pivot
Once found, they are swapped and the loop continues.
Meanwhile items that are equal to the pivot are moved to the edges of the
array.
*/
while(pl < pr) {
/* Move left hand items which are equal to the pivot to the far left.
break when we find an item that is greater than the pivot */
for(; pl < pr; pl += w) {
cmp = compar(pl, pivot, arg);
if(cmp > 0) { break; }
else if(cmp == 0) {
if(ple < pl) { sort_r_swap(ple, pl, w); }
ple += w;
}
}
/* break if last batch of left hand items were equal to pivot */
if(pl >= pr) { break; }
/* Move right hand items which are equal to the pivot to the far right.
break when we find an item that is less than the pivot */
for(; pl < pr; ) {
pr -= w; /* Move right pointer onto an unprocessed item */
cmp = compar(pr, pivot, arg);
if(cmp == 0) {
pre -= w;
if(pr < pre) { sort_r_swap(pr, pre, w); }
}
else if(cmp < 0) {
if(pl < pr) { sort_r_swap(pl, pr, w); }
pl += w;
break;
}
}
}
pl = pr; /* pr may have gone below pl */
/*
Now we need to go from: EEELLLGGGGEEEE
to: LLLEEEEEEEGGGG
Pivot comparison key:
E = equal, L = less than, u = unknown, G = greater than, E = equal
*/
sort_r_swap_blocks(b, ple-b, pl-ple);
sort_r_swap_blocks(pr, pre-pr, end-pre);
/*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
printf("\n");*/
sort_r_simple(b, (pl-ple)/w, w, compar, arg);
sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, arg);
}
}
#if defined NESTED_QSORT
static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a,
const void *_b,
void *aarg),
void *arg)
{
int nested_cmp(const void *a, const void *b)
{
return compar(a, b, arg);
}
qsort(base, nel, width, nested_cmp);
}
#else /* !NESTED_QSORT */
/* Declare structs and functions */
#if defined _SORT_R_BSD
/* Ensure qsort_r is defined */
extern void qsort_r(void *base, size_t nel, size_t width, void *thunk,
int (*compar)(void *_thunk,
const void *_a, const void *_b));
#endif
#if defined _SORT_R_BSD || defined _SORT_R_WINDOWS
/* BSD (qsort_r), Windows (qsort_s) require argument swap */
struct sort_r_data
{
void *arg;
int (*compar)(const void *_a, const void *_b, void *_arg);
};
static _SORT_R_INLINE int sort_r_arg_swap(void *s,
const void *a, const void *b)
{
struct sort_r_data *ss = (struct sort_r_data*)s;
return (ss->compar)(a, b, ss->arg);
}
#endif
#if defined _SORT_R_GNU
typedef int(* __compar_d_fn_t)(const void *, const void *, void *);
extern void qsort_r(void *base, size_t nel, size_t width,
__compar_d_fn_t __compar, void *arg)
__attribute__((nonnull (1, 4)));
#endif
/* implementation */
static _SORT_R_INLINE void sort_r(void *base, size_t nel, size_t width,
int (*compar)(const void *_a,
const void *_b, void *_arg),
void *arg)
{
#if defined _SORT_R_GNU
#if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8))
/* no qsort_r in glibc before 2.8, need to use nested qsort */
sort_r_simple(base, nel, width, compar, arg);
#else
qsort_r(base, nel, width, compar, arg);
#endif
#elif defined _SORT_R_BSD
struct sort_r_data tmp;
tmp.arg = arg;
tmp.compar = compar;
qsort_r(base, nel, width, &tmp, sort_r_arg_swap);
#elif defined _SORT_R_WINDOWS
struct sort_r_data tmp;
tmp.arg = arg;
tmp.compar = compar;
qsort_s(base, nel, width, sort_r_arg_swap, &tmp);
#else
/* Fall back to our own quicksort implementation */
sort_r_simple(base, nel, width, compar, arg);
#endif
}
#endif /* !NESTED_QSORT */
#undef _SORT_R_INLINE
#undef _SORT_R_WINDOWS
#undef _SORT_R_GNU
#undef _SORT_R_BSD
#endif /* SORT_R_H_ */