diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2012-04-13 16:42:51 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2012-04-13 16:42:51 +0200 |
commit | 6035662c8cfc75156a14cf2b8a85a73f7905a954 (patch) | |
tree | 3126b7058a566a3a99b5ef98d8a9efb4e932d93a | |
parent | d3e3ad5b428ed46aff71ee0b0e05902cd6ab9678 (diff) | |
download | pgfuse-6035662c8cfc75156a14cf2b8a85a73f7905a954.tar.gz pgfuse-6035662c8cfc75156a14cf2b8a85a73f7905a954.tar.bz2 |
replace isdir with mode (in database and in code)
-rw-r--r-- | pgfuse.c | 32 | ||||
-rw-r--r-- | pgsql.c | 85 | ||||
-rw-r--r-- | pgsql.h | 10 | ||||
-rw-r--r-- | schema.sql | 13 |
4 files changed, 74 insertions, 66 deletions
@@ -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; } @@ -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 *)¶m1, 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 *)¶m1, (char *)¶m2, (char *)¶m3 }; + 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 *)¶m1, new_file, path, (const char *)¶m2 }; + 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 *)¶m1, 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 *)¶m1, new_dir, path, (char *)¶m2 }; + 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 *)¶m1, (char *)¶m2 }; - 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; -} @@ -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 @@ -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 ); |