Commit ee9ffa77 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

basic reservations for VIEWs preveleges

parent 1be033f6
...@@ -9,8 +9,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3 ...@@ -9,8 +9,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost' GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost; grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1"; select * from mysql.user where user="mysqltest_1";
Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N SPECIFIED EDH-RSA-DES-CBC3-SHA 0 0 0 localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 0 0 0
show grants for mysqltest_1@localhost; show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
...@@ -61,7 +61,7 @@ revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost; ...@@ -61,7 +61,7 @@ revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost;
show grants for mysqltest_1@localhost; show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
revoke all privileges on mysqltest.* from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
......
...@@ -65,13 +65,15 @@ then ...@@ -65,13 +65,15 @@ then
c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_d="$c_d Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_d="$c_d Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_d="$c_d Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_d="$c_d PRIMARY KEY Host (Host,Db,User)," c_d="$c_d PRIMARY KEY Host (Host,Db,User),"
c_d="$c_d KEY User (User)" c_d="$c_d KEY User (User)"
c_d="$c_d )" c_d="$c_d )"
c_d="$c_d comment='Database privileges';" c_d="$c_d comment='Database privileges';"
i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); i_d="INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y');
INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');" INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y');"
fi fi
if test ! -f $mdata/host.frm if test ! -f $mdata/host.frm
...@@ -95,6 +97,8 @@ then ...@@ -95,6 +97,8 @@ then
c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_h="$c_h Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_h="$c_h Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_h="$c_h Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_h="$c_h PRIMARY KEY Host (Host,Db)" c_h="$c_h PRIMARY KEY Host (Host,Db)"
c_h="$c_h )" c_h="$c_h )"
c_h="$c_h comment='Host privileges; Merged with database privileges';" c_h="$c_h comment='Host privileges; Merged with database privileges';"
...@@ -131,6 +135,8 @@ then ...@@ -131,6 +135,8 @@ then
c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL," c_u="$c_u ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL,"
c_u="$c_u ssl_cipher BLOB NOT NULL," c_u="$c_u ssl_cipher BLOB NOT NULL,"
c_u="$c_u x509_issuer BLOB NOT NULL," c_u="$c_u x509_issuer BLOB NOT NULL,"
...@@ -144,21 +150,21 @@ then ...@@ -144,21 +150,21 @@ then
if test "$1" = "test" if test "$1" = "test"
then then
i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); REPLACE INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
INSERT INTO user (host,user) values ('localhost',''); INSERT INTO user (host,user) values ('localhost','');
INSERT INTO user (host,user) values ('$hostname','');" INSERT INTO user (host,user) values ('$hostname','');"
else else
i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" i_u="INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
if test "$windows" = "0" if test "$windows" = "0"
then then
i_u="$i_u i_u="$i_u
INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('$hostname','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
INSERT INTO user (host,user) values ('$hostname',''); INSERT INTO user (host,user) values ('$hostname','');
INSERT INTO user (host,user) values ('localhost','');" INSERT INTO user (host,user) values ('localhost','');"
else else
i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);" i_u="INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);"
fi fi
fi fi
fi fi
......
...@@ -86,6 +86,7 @@ ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv, ...@@ -86,6 +86,7 @@ ADD Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv,
ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv, ADD Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Execute_priv,
ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv; ADD Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_slave_priv;
UPDATE user SET show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"" AND @hadShowDbPriv = 0; UPDATE user SET show_db_priv= select_priv, super_priv=process_priv, execute_priv=process_priv, create_tmp_table_priv='Y', Lock_tables_priv='Y', Repl_slave_priv=file_priv, Repl_client_priv=file_priv where user<>"" AND @hadShowDbPriv = 0;
ALTER TABLE user ALTER TABLE user
...@@ -100,6 +101,20 @@ ALTER TABLE host ...@@ -100,6 +101,20 @@ ALTER TABLE host
ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, ADD Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,
ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL; ADD Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL;
#
# Create VIEWs privrlages (v5.1)
#
ALTER TABLE db ADD Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv;
ALTER TABLE host ADD Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Lock_tables_priv;
ALTER TABLE user ADD Create_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Repl_client_priv;
#
# Show VIEWs privrlages (v5.1)
#
ALTER TABLE db ADD Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_view_priv;
ALTER TABLE host ADD Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_view_priv;
ALTER TABLE user ADD Show_view_priv enum('N','Y') DEFAULT 'N' NOT NULL AFTER Create_view_priv;
# #
# Create some possible missing tables # Create some possible missing tables
# #
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
#define FIRST_NON_YN_FIELD 26
class acl_entry :public hash_filo_element class acl_entry :public hash_filo_element
{ {
public: public:
...@@ -303,9 +305,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -303,9 +305,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
user.sort= get_sort(2,user.host.hostname,user.user); user.sort= get_sort(2,user.host.hostname,user.user);
user.hostname_length= (user.host.hostname ? user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0); (uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{ {
char *ssl_type=get_field(&mem, table->field[24]); uint base_field= 24;
if (table->fields > 31) /* Starting from 5.1 we have more privileges */
base_field= 26;
char *ssl_type=get_field(&mem, table->field[base_field]);
if (!ssl_type) if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE; user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY")) else if (!strcmp(ssl_type, "ANY"))
...@@ -315,15 +322,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -315,15 +322,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else /* !strcmp(ssl_type, "SPECIFIED") */ else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED; user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table->field[25]); user.ssl_cipher= get_field(&mem, table->field[base_field+1]);
user.x509_issuer= get_field(&mem, table->field[26]); user.x509_issuer= get_field(&mem, table->field[base_field+2]);
user.x509_subject= get_field(&mem, table->field[27]); user.x509_subject= get_field(&mem, table->field[base_field+3]);
char *ptr = get_field(&mem, table->field[28]); char *ptr = get_field(&mem, table->field[base_field+4]);
user.user_resource.questions=atoi(ptr); user.user_resource.questions=atoi(ptr);
ptr = get_field(&mem, table->field[29]); ptr = get_field(&mem, table->field[base_field+5]);
user.user_resource.updates=atoi(ptr); user.user_resource.updates=atoi(ptr);
ptr = get_field(&mem, table->field[30]); ptr = get_field(&mem, table->field[base_field+6]);
user.user_resource.connections=atoi(ptr); user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates || if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections) user.user_resource.connections)
...@@ -3016,15 +3023,16 @@ static void add_user_option(String *grant, ulong value, const char *name) ...@@ -3016,15 +3023,16 @@ static void add_user_option(String *grant, ulong value, const char *name)
static const char *command_array[]= static const char *command_array[]=
{ {
"SELECT", "INSERT","UPDATE","DELETE","CREATE", "DROP", "RELOAD","SHUTDOWN", "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
"PROCESS","FILE","GRANT","REFERENCES","INDEX", "ALTER", "SHOW DATABASES", "SHUTDOWN", "PROCESS","FILE", "GRANT", "REFERENCES", "INDEX",
"SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
"REPLICATION SLAVE", "REPLICATION CLIENT", "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
"CREATE VIEW", "SHOW VIEW"
}; };
static uint command_lengths[]= static uint command_lengths[]=
{ {
6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9
}; };
......
...@@ -35,11 +35,13 @@ ...@@ -35,11 +35,13 @@
#define EXECUTE_ACL (1L << 18) #define EXECUTE_ACL (1L << 18)
#define REPL_SLAVE_ACL (1L << 19) #define REPL_SLAVE_ACL (1L << 19)
#define REPL_CLIENT_ACL (1L << 20) #define REPL_CLIENT_ACL (1L << 20)
#define CREATE_VIEW_ACL (1L << 21)
#define SHOW_VIEW_ACL (1L << 22)
#define DB_ACLS \ #define DB_ACLS \
(UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ (UPDATE_ACL | SELECT_ACL | INSERT_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | LOCK_TABLES_ACL) GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL | \
LOCK_TABLES_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL)
#define TABLE_ACLS \ #define TABLE_ACLS \
(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \ (SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL | CREATE_ACL | DROP_ACL | \
...@@ -53,7 +55,7 @@ ...@@ -53,7 +55,7 @@
RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \ RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL | GRANT_ACL | \
REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \ REFERENCES_ACL | INDEX_ACL | ALTER_ACL | SHOW_DB_ACL | SUPER_ACL | \
CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \ CREATE_TMP_ACL | LOCK_TABLES_ACL | REPL_SLAVE_ACL | REPL_CLIENT_ACL | \
EXECUTE_ACL) EXECUTE_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL)
#define EXTRA_ACL (1L << 29) #define EXTRA_ACL (1L << 29)
#define NO_ACCESS (1L << 30) #define NO_ACCESS (1L << 30)
...@@ -66,13 +68,21 @@ ...@@ -66,13 +68,21 @@
/* Continius bit-segments that needs to be shifted */ /* Continius bit-segments that needs to be shifted */
#define DB_REL1 (RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL) #define DB_REL1 (RELOAD_ACL | SHUTDOWN_ACL | PROCESS_ACL | FILE_ACL)
#define DB_REL2 (GRANT_ACL | REFERENCES_ACL) #define DB_REL2 (GRANT_ACL | REFERENCES_ACL)
#define DB_REL3 (INDEX_ACL | ALTER_ACL)
/* Privileges that needs to be reallocated (in continous chunks) */ /* Privileges that needs to be reallocated (in continous chunks) */
#define DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL) #define DB_CHUNK1 (GRANT_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL)
#define DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL) #define DB_CHUNK2 (CREATE_TMP_ACL | LOCK_TABLES_ACL)
#define DB_CHUNK3 (CREATE_VIEW_ACL | SHOW_VIEW_ACL)
#define fix_rights_for_db(A) (((A) & 63) | (((A) & DB_REL1) << 4) | (((A) & DB_REL2) << 6))
#define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6)) #define fix_rights_for_db(A) (((A) & 63) | \
(((A) & DB_REL1) << 4) | \
(((A) & DB_REL2) << 6) | \
(((A) & DB_REL3) << 9))
#define get_rights_for_db(A) (((A) & 63) | \
(((A) & DB_CHUNK1) >> 4) | \
(((A) & DB_CHUNK2) >> 6) | \
(((A) & DB_CHUNK3) >> 9))
#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) #define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) #define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
#define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment