summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2012-04-13 16:42:51 +0200
committerAndreas Baumann <abaumann@yahoo.com>2012-04-13 16:42:51 +0200
commit6035662c8cfc75156a14cf2b8a85a73f7905a954 (patch)
tree3126b7058a566a3a99b5ef98d8a9efb4e932d93a
parentd3e3ad5b428ed46aff71ee0b0e05902cd6ab9678 (diff)
downloadpgfuse-6035662c8cfc75156a14cf2b8a85a73f7905a954.tar.gz
pgfuse-6035662c8cfc75156a14cf2b8a85a73f7905a954.tar.bz2
replace isdir with mode (in database and in code)
-rw-r--r--pgfuse.c32
-rw-r--r--pgsql.c85
-rw-r--r--pgsql.h10
-rw-r--r--schema.sql13
4 files changed, 74 insertions, 66 deletions
diff --git a/pgfuse.c b/pgfuse.c
index eed7ef7..2a05a68 100644
--- a/pgfuse.c
+++ b/pgfuse.c
@@ -45,6 +45,7 @@ typedef struct PgFuseFile {
size_t size; /* current size of the buffer (malloc/realloc) */
size_t used; /* used size in the buffer */
int ref_count; /* reference counter (for double opens, dup, etc.) */
+ mode_t mode; /* type and permissions of file */
} PgFuseFile;
static PgFuseFile pgfuse_files[MAX_NOF_OPEN_FILES];
@@ -108,18 +109,13 @@ static int pgfuse_getattr( const char *path, struct stat *stbuf )
}
if( data->verbose ) {
- syslog( LOG_DEBUG, "Id for %s '%s' is %d", meta.isdir ? "dir" : "file", path, id );
+ syslog( LOG_DEBUG, "Id for %s '%s' is %d",
+ S_ISDIR( meta.mode ) ? "dir" : "file", path, id );
}
stbuf->st_ino = id;
stbuf->st_blocks = 0;
- /* no mode information is stored currently
- * TODO: store mode in 'inode' table */
- if( meta.isdir ) {
- stbuf->st_mode = S_IFDIR | 0775;
- } else {
- stbuf->st_mode = S_IFREG | 0664;
- }
+ stbuf->st_mode = meta.mode;
stbuf->st_size = meta.size;
stbuf->st_blksize = STANDARD_BLOCK_SIZE;
stbuf->st_blocks = ( meta.size + STANDARD_BLOCK_SIZE - 1 ) / STANDARD_BLOCK_SIZE;
@@ -198,7 +194,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info *
syslog( LOG_DEBUG, "Id for dir '%s' is %d", path, id );
}
- if( meta.isdir ) {
+ if( S_ISDIR(meta.mode ) ) {
return -EISDIR;
}
@@ -217,7 +213,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info *
if( parent_id < 0 ) {
return parent_id;
}
- if( !meta.isdir ) {
+ if( !S_ISDIR(meta.mode ) ) {
return -ENOENT;
}
@@ -272,6 +268,7 @@ static int pgfuse_create( const char *path, mode_t mode, struct fuse_file_info *
return -ENOMEM;
}
f->ref_count = 1;
+ f->mode = mode;
fi->fh = id;
@@ -304,7 +301,7 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi )
syslog( LOG_DEBUG, "Id for file '%s' to open is %d", path, id );
}
- if( meta.isdir ) {
+ if( S_ISDIR( meta.mode ) ) {
return -EISDIR;
}
@@ -333,6 +330,7 @@ static int pgfuse_open( const char *path, struct fuse_file_info *fi )
return -ENOMEM;
}
f->ref_count = 1;
+ f->mode = meta.mode;
res = psql_read_buf( data->conn, id, path, &f->buf, f->used );
if( res != f->used ) {
@@ -421,7 +419,7 @@ static int pgfuse_mkdir( const char *path, mode_t mode )
if( parent_id < 0 ) {
return parent_id;
}
- if( !meta.isdir ) {
+ if( !S_ISDIR( meta.mode ) ) {
return -ENOENT;
}
@@ -438,6 +436,8 @@ static int pgfuse_mkdir( const char *path, mode_t mode )
}
new_dir = basename( copy_path );
+
+ mode |= S_IFDIR;
res = psql_create_dir( data->conn, parent_id, path, new_dir, mode );
@@ -461,7 +461,7 @@ static int pgfuse_rmdir( const char *path )
if( id < 0 ) {
return id;
}
- if( !meta.isdir ) {
+ if( !S_ISDIR( meta.mode ) ) {
return -ENOTDIR;
}
@@ -493,7 +493,7 @@ static int pgfuse_unlink( const char *path )
if( id < 0 ) {
return id;
}
- if( meta.isdir ) {
+ if( S_ISDIR( meta.mode ) ) {
return -EPERM;
}
@@ -542,6 +542,7 @@ static int pgfuse_fsync( const char *path, int isdatasync, struct fuse_file_info
res = 0;
if( !isdatasync ) {
meta.size = f->used;
+ meta.mode = f->mode;
res = psql_write_meta( data->conn, f->id, path, meta );
}
@@ -589,6 +590,7 @@ static int pgfuse_release( const char *path, struct fuse_file_info *fi )
}
meta.size = f->used;
+ meta.mode = f->mode;
res = psql_write_meta( data->conn, f->id, path, meta );
if( res >= 0 ) {
@@ -691,7 +693,7 @@ static int pgfuse_truncate( const char* path, off_t offset )
return id;
}
- if( meta.isdir ) {
+ if( S_ISDIR( meta.mode ) ) {
return -EISDIR;
}
diff --git a/pgsql.c b/pgsql.c
index bcec422..c43739c 100644
--- a/pgsql.c
+++ b/pgsql.c
@@ -29,16 +29,15 @@ int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta )
PGresult *res;
int i_id;
int i_size;
- int i_isdir;
+ int i_mode;
char *iptr;
- char *s;
int id;
const char *values[1] = { path };
int lengths[1] = { strlen( path ) };
int binary[1] = { 1 };
- res = PQexecParams( conn, "SELECT id, size, isdir FROM dir WHERE path = $1::varchar",
+ res = PQexecParams( conn, "SELECT id, size, mode FROM dir WHERE path = $1::varchar",
1, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_TUPLES_OK ) {
@@ -60,32 +59,56 @@ int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta )
i_id = PQfnumber( res, "id" );
i_size = PQfnumber( res, "size" );
- i_isdir = PQfnumber( res, "isdir" );
+ i_mode = PQfnumber( res, "mode" );
iptr = PQgetvalue( res, 0, i_id );
id = ntohl( *( (uint32_t *)iptr ) );
iptr = PQgetvalue( res, 0, i_size );
meta->size = ntohl( *( (uint32_t *)iptr ) );
- s = PQgetvalue( res, 0, i_isdir );
- meta->isdir = 0;
- if( s[0] == '\001' ) meta->isdir = 1;
+ iptr = PQgetvalue( res, 0, i_mode );
+ meta->mode = ntohl( *( (uint32_t *)iptr ) );
PQclear( res );
return id;
}
-int psql_create_file( PGconn *conn, const int parent_id, const char *path, const char *new_file, mode_t mode )
+int psql_write_meta( PGconn *conn, const int id, const char *path, PgMeta meta )
{
- int param1 = htonl( parent_id );
- const char *values[3] = { (char *)&param1, new_file, path };
- int lengths[3] = { sizeof( parent_id), strlen( new_file ), strlen( path ) };
- int binary[3] = { 1, 0, 0 };
+ int param1 = htonl( id );
+ int param2 = htonl( meta.size );
+ int param3 = htonl( meta.mode );
+ const char *values[3] = { (char *)&param1, (char *)&param2, (char *)&param3 };
+ int lengths[3] = { sizeof( param1 ), sizeof( param2 ), sizeof( param3 ) };
+ int binary[3] = { 1, 1, 1 };
PGresult *res;
- res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, isdir ) VALUES ($1::int4, $2::varchar, $3::varchar, false )",
+ res = PQexecParams( conn, "UPDATE dir SET size=$2::int4, mode=$3::int4 WHERE id=$1::int4",
3, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
+ syslog( LOG_ERR, "Error in psql_write_meta for file '%s': %s", path, PQerrorMessage( conn ) );
+ PQclear( res );
+ return -EIO;
+ }
+
+ PQclear( res );
+
+ return 0;
+}
+
+int psql_create_file( PGconn *conn, const int parent_id, const char *path, const char *new_file, const mode_t mode )
+{
+ int param1 = htonl( parent_id );
+ int param2 = htonl( mode );
+ const char *values[4] = { (const char *)&param1, new_file, path, (const char *)&param2 };
+ int lengths[4] = { sizeof( param1 ), strlen( new_file ), strlen( path ), sizeof( param2 ) };
+ int binary[4] = { 1, 0, 0, 1 };
+ PGresult *res;
+
+ res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, mode ) VALUES ($1::int4, $2::varchar, $3::varchar, $4::int4 )",
+ 4, NULL, values, lengths, binary, 1 );
+
+ if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
syslog( LOG_ERR, "Error in psql_create_file for path '%s': %s",
path, PQerrorMessage( conn ) );
PQclear( res );
@@ -164,16 +187,17 @@ int psql_readdir( PGconn *conn, const int parent_id, void *buf, fuse_fill_dir_t
return 0;
}
-int psql_create_dir( PGconn *conn, const int parent_id, const char *path, const char *new_dir, mode_t mode )
+int psql_create_dir( PGconn *conn, const int parent_id, const char *path, const char *new_dir, const mode_t mode )
{
int param1 = htonl( parent_id );
- const char *values[3] = { (char *)&param1, new_dir, path };
- int lengths[3] = { sizeof( parent_id), strlen( new_dir ), strlen( path ) };
- int binary[3] = { 1, 0, 0 };
+ int param2 = htonl( mode );
+ const char *values[4] = { (char *)&param1, new_dir, path, (char *)&param2 };
+ int lengths[4] = { sizeof( param1 ), strlen( new_dir ), strlen( path ), sizeof( param2 ) };
+ int binary[4] = { 1, 0, 0, 1 };
PGresult *res;
- res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, isdir ) VALUES ($1::int4, $2::varchar, $3::varchar, true )",
- 3, NULL, values, lengths, binary, 1 );
+ res = PQexecParams( conn, "INSERT INTO dir( parent_id, name, path, mode ) VALUES ($1::int4, $2::varchar, $3::varchar, $4::int4 )",
+ 4, NULL, values, lengths, binary, 1 );
if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
syslog( LOG_ERR, "Error in psql_create_dir for path '%s': %s", path, PQerrorMessage( conn ) );
@@ -278,26 +302,3 @@ int psql_write_buf( PGconn *conn, const int id, const char *path, const char *bu
return len;
}
-
-int psql_write_meta( PGconn *conn, const int id, const char *path, PgMeta meta )
-{
- int param1 = htonl( id );
- int param2 = htonl( meta.size );
- const char *values[2] = { (char *)&param1, (char *)&param2 };
- int lengths[2] = { sizeof( param1 ), sizeof( param2 ) };
- int binary[2] = { 1, 1 };
- PGresult *res;
-
- res = PQexecParams( conn, "UPDATE dir SET size=$2::int4 WHERE id=$1::int4",
- 2, NULL, values, lengths, binary, 1 );
-
- if( PQresultStatus( res ) != PGRES_COMMAND_OK ) {
- syslog( LOG_ERR, "Error in psql_write_meta for file '%s': %s", path, PQerrorMessage( conn ) );
- PQclear( res );
- return -EIO;
- }
-
- PQclear( res );
-
- return 0;
-}
diff --git a/pgsql.h b/pgsql.h
index 703a933..5cd2d7e 100644
--- a/pgsql.h
+++ b/pgsql.h
@@ -27,18 +27,20 @@
typedef struct PgMeta {
size_t size; /* the size of the file */
- int isdir; /* whether we have a directory or a file */
+ mode_t mode; /* type and permissions of file/directory */
} PgMeta;
int psql_get_meta( PGconn *conn, const char *path, PgMeta *meta );
-int psql_create_file( PGconn *conn, const int parent_id, const char *path, const char *new_file, mode_t mode );
+int psql_write_meta( PGconn *conn, const int id, const char *path, PgMeta meta );
+
+int psql_create_file( PGconn *conn, const int parent_id, const char *path, const char *new_file, const mode_t mode );
int psql_read_buf( PGconn *conn, const int id, const char *path, char **buf, const size_t len );
int psql_readdir( PGconn *conn, const int parent_id, void *buf, fuse_fill_dir_t filler );
-int psql_create_dir( PGconn *conn, const int parent_id, const char *path, const char *new_dir, mode_t mode );
+int psql_create_dir( PGconn *conn, const int parent_id, const char *path, const char *new_dir, const mode_t mode );
int psql_delete_dir( PGconn *conn, const int id, const char *path );
@@ -46,6 +48,4 @@ int psql_delete_file( PGconn *conn, const int id, const char *path );
int psql_write_buf( PGconn *conn, const int id, const char *path, const char *buf, const size_t len );
-int psql_write_meta( PGconn *conn, const int id, const char *path, PgMeta meta );
-
#endif
diff --git a/schema.sql b/schema.sql
index d48c890..9affe44 100644
--- a/schema.sql
+++ b/schema.sql
@@ -3,7 +3,6 @@ CREATE TABLE dir (
parent_id INTEGER REFERENCES dir( id ),
name TEXT,
path TEXT,
- isdir BOOL,
UNIQUE( name, parent_id ),
UNIQUE( path ),
mode INTEGER NOT NULL DEFAULT 0,
@@ -28,17 +27,23 @@ CREATE INDEX data_id_idx ON data( id );
-- directory listings
CREATE INDEX dir_parent_id_idx ON dir( parent_id );
+-- 16384 == S_IFDIR (S_IFDIR)
+-- TODO: should be created by the program after checking the OS
+-- it is running on (for full POSIX compatibility)
+
-- make sure file entries always get a data
-- section in the separate table
CREATE OR REPLACE RULE "dir_insert" AS ON
- INSERT TO dir WHERE NEW.isdir = false
+ INSERT TO dir WHERE NEW.mode & 16384 = 0
DO ALSO INSERT INTO data( id )
VALUES ( currval( 'dir_id_seq' ) );
-- garbage collect deleted file entries
CREATE OR REPLACE RULE "dir_remove" AS ON
- DELETE TO dir WHERE OLD.isdir = false
+ DELETE TO dir WHERE OLD.mode & 16384 = 0
DO ALSO DELETE FROM data WHERE id=OLD.id;
-- self-referencing anchor for root directory
-INSERT INTO dir values( 0, 0, '/', '/', true );
+-- 16895 = S_IFDIR and 0777 permissions
+-- TODO: should be done from outside, see note above
+INSERT INTO dir values( 0, 0, '/', '/', 16895 );