diff --git a/linux/linux.c b/linux/linux.c index 67ff272937e..2b4bb8032ec 100644 --- a/linux/linux.c +++ b/linux/linux.c @@ -49,7 +49,7 @@ toku_os_get_phys_memory_size(void) { int toku_os_get_file_size(int fildes, int64_t *fsize) { - struct stat sbuf; + toku_struct_stat sbuf; int r = fstat(fildes, &sbuf); if (r==0) { *fsize = sbuf.st_size; @@ -59,7 +59,7 @@ toku_os_get_file_size(int fildes, int64_t *fsize) { int toku_os_get_unique_file_id(int fildes, struct fileid *id) { - struct stat statbuf; + toku_struct_stat statbuf; memset(id, 0, sizeof(*id)); int r=fstat(fildes, &statbuf); if (r==0) { @@ -190,3 +190,16 @@ toku_os_get_max_process_data_size(uint64_t *maxdata) { r = errno; return r; } + +int +toku_stat(const char *name, toku_struct_stat *buf) { + int r = stat(name, buf); + return r; +} + +int +toku_stat(int fd, toku_struct_fstat *buf) { + int r = fstat(fd, buf); + return r; +} + diff --git a/linux/tests/test-stat.c b/linux/tests/test-stat.c new file mode 100644 index 00000000000..6055e7ff74c --- /dev/null +++ b/linux/tests/test-stat.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +void test_stat(char *dirname, int result, int ex_errno) { + int r; + toku_struct_stat buf; + r = toku_stat(dirname, &buf); + printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); + assert(r==result); + if (r!=0) assert(errno == ex_errno); +} + +int main(void) { + int r; + + test_stat(".", 0, 0); + test_stat("./", 0, 0); + + r = system("rm -rf testdir"); assert(r==0); + test_stat("testdir", -1, ENOENT); + test_stat("testdir/", -1, ENOENT); + test_stat("testdir/foo", -1, ENOENT); + test_stat("testdir/foo/", -1, ENOENT); + r = toku_os_mkdir("testdir", S_IRWXU); + assert(r == 0); + test_stat("testdir/foo", -1, ENOENT); + test_stat("testdir/foo/", -1, ENOENT); + r = system("touch testdir/foo"); assert(r==0); + test_stat("testdir/foo", 0, 0); + test_stat("testdir/foo/", -1, ENOENT); + + test_stat("testdir", 0, 0); + + test_stat("./testdir", 0, 0); + + test_stat("./testdir/", 0, 0); + + test_stat("/", 0, 0); + + test_stat("/usr", 0, 0); + test_stat("/usr/", 0, 0); + + return 0; +} diff --git a/linux/toku_os_types.h b/linux/toku_os_types.h index 38e923c7a84..285369dc467 100644 --- a/linux/toku_os_types.h +++ b/linux/toku_os_types.h @@ -14,6 +14,8 @@ struct fileid { ino_t st_ino; }; +typedef struct stat toku_struct_stat; + #if !defined(O_BINARY) #define O_BINARY 0 #endif diff --git a/newbrt/cachetable.c b/newbrt/cachetable.c index 23b09ffd027..c0f7d4bcbef 100644 --- a/newbrt/cachetable.c +++ b/newbrt/cachetable.c @@ -1508,9 +1508,9 @@ graceful_open_get_append_fd(const char *db_fname, BOOL *was_dirtyp, BOOL *create toku_graceful_fill_names(db_fname, cleanbuf, sizeof(cleanbuf), dirtybuf, sizeof(dirtybuf)); - struct stat tmpbuf; - clean_exists = (BOOL)(stat(cleanbuf, &tmpbuf) == 0); - dirty_exists = (BOOL)(stat(dirtybuf, &tmpbuf) == 0); + toku_struct_stat tmpbuf; + clean_exists = (BOOL)(toku_stat(cleanbuf, &tmpbuf) == 0); + dirty_exists = (BOOL)(toku_stat(dirtybuf, &tmpbuf) == 0); mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO; int r = 0; @@ -1538,10 +1538,10 @@ graceful_close_get_append_fd(const char *db_fname, BOOL *db_missing) { toku_graceful_fill_names(db_fname, cleanbuf, sizeof(cleanbuf), dirtybuf, sizeof(dirtybuf)); - struct stat tmpbuf; - clean_exists = (BOOL)(stat(cleanbuf, &tmpbuf) == 0); - dirty_exists = (BOOL)(stat(dirtybuf, &tmpbuf) == 0); - db_exists = (BOOL)(stat(db_fname, &tmpbuf) == 0); + toku_struct_stat tmpbuf; + clean_exists = (BOOL)(toku_stat(cleanbuf, &tmpbuf) == 0); + dirty_exists = (BOOL)(toku_stat(dirtybuf, &tmpbuf) == 0); + db_exists = (BOOL)(toku_stat(db_fname, &tmpbuf) == 0); mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO; int r = 0; @@ -1564,9 +1564,9 @@ graceful_dirty_get_append_fd(const char *db_fname) { toku_graceful_fill_names(db_fname, cleanbuf, sizeof(cleanbuf), dirtybuf, sizeof(dirtybuf)); - struct stat tmpbuf; - clean_exists = (BOOL)(stat(cleanbuf, &tmpbuf) == 0); - dirty_exists = (BOOL)(stat(dirtybuf, &tmpbuf) == 0); + toku_struct_stat tmpbuf; + clean_exists = (BOOL)(toku_stat(cleanbuf, &tmpbuf) == 0); + dirty_exists = (BOOL)(toku_stat(dirtybuf, &tmpbuf) == 0); mode_t mode = S_IRWXU|S_IRWXG|S_IRWXO; int r = 0; @@ -1687,10 +1687,10 @@ toku_graceful_delete(const char *db_fname) { sprintf(cleanbuf, "%s.clean", db_fname); sprintf(dirtybuf, "%s.dirty", db_fname); - struct stat tmpbuf; + toku_struct_stat tmpbuf; lock_for_graceful(); - clean_exists = (BOOL)(stat(cleanbuf, &tmpbuf) == 0); - dirty_exists = (BOOL)(stat(dirtybuf, &tmpbuf) == 0); + clean_exists = (BOOL)(toku_stat(cleanbuf, &tmpbuf) == 0); + dirty_exists = (BOOL)(toku_stat(dirtybuf, &tmpbuf) == 0); int r = 0; if (clean_exists) { diff --git a/newbrt/recover.c b/newbrt/recover.c index 25700258d6e..52f9e4f3549 100644 --- a/newbrt/recover.c +++ b/newbrt/recover.c @@ -113,9 +113,9 @@ internal_toku_recover_fopen_or_fcreate (int flags, int mode, char *fixedfname, F char cleanname[slen + sizeof(CLEANSUFFIX)]; char dirtyname[slen + sizeof(DIRTYSUFFIX)]; toku_graceful_fill_names(fixedfname, cleanname, sizeof(cleanname), dirtyname, sizeof(dirtyname)); - struct stat tmpbuf; - BOOL clean_exists = stat(cleanname, &tmpbuf)==0; - BOOL dirty_exists = stat(dirtyname, &tmpbuf)==0; + toku_struct_stat tmpbuf; + BOOL clean_exists = toku_stat(cleanname, &tmpbuf)==0; + BOOL dirty_exists = toku_stat(dirtyname, &tmpbuf)==0; if (dirty_exists) { if (clean_exists) { int r = unlink(dirtyname); assert(r==0); } else { int r = rename(dirtyname, cleanname); assert(r==0); } diff --git a/newbrt/tests/log-test4.c b/newbrt/tests/log-test4.c index 69c46993ca7..9341440aa73 100644 --- a/newbrt/tests/log-test4.c +++ b/newbrt/tests/log-test4.c @@ -35,8 +35,8 @@ test_main (int argc __attribute__((__unused__)), r = toku_logger_close(&logger); assert(r == 0); { - struct stat statbuf; - r = stat(dname "/log000000000000.tokulog", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(dname "/log000000000000.tokulog", &statbuf); assert(r==0); assert(statbuf.st_size==12+5); } diff --git a/newbrt/tests/log-test5.c b/newbrt/tests/log-test5.c index a545830075d..a27e39dec98 100644 --- a/newbrt/tests/log-test5.c +++ b/newbrt/tests/log-test5.c @@ -53,8 +53,8 @@ test_main (int argc __attribute__((__unused__)), if (strncmp(dirent->d_name, "log", 3)!=0) continue; char fname[sizeof(dname)+256+1]; snprintf(fname, sizeof(fname), "%s/%s", dname, dirent->d_name); - struct stat statbuf; - r = stat(fname, &statbuf); + toku_struct_stat statbuf; + r = toku_stat(fname, &statbuf); assert(r==0); assert(statbuf.st_size<=LSIZE); } diff --git a/newbrt/tests/log-test6.c b/newbrt/tests/log-test6.c index fd464897dd4..7900255f64c 100644 --- a/newbrt/tests/log-test6.c +++ b/newbrt/tests/log-test6.c @@ -59,8 +59,8 @@ test_main (int argc __attribute__((__unused__)), assert(r == 0); { - struct stat statbuf; - r = stat(dname "/log000000000000.tokulog", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(dname "/log000000000000.tokulog", &statbuf); assert(r==0); assert(statbuf.st_size<=LSIZE); } diff --git a/src/tests/test1324.c b/src/tests/test1324.c index 0e55af93d5d..01470b3a254 100644 --- a/src/tests/test1324.c +++ b/src/tests/test1324.c @@ -39,16 +39,16 @@ do_1324 (int moreflags) r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); { - struct stat sbuf; - r = stat(fname, &sbuf); + toku_struct_stat sbuf; + r = toku_stat(fname, &sbuf); if (r==0) { fprintf(stderr, "The rolltmp file %s should have been deleted, but was not.\n", fname); } assert(r!=0); } { - struct stat sbuf; - r = stat(fnamekeep, &sbuf); + toku_struct_stat sbuf; + r = toku_stat(fnamekeep, &sbuf); if (r!=0) { fprintf(stderr, "The keepme file %s should NOT have been deleted, but was not.\n", fnamekeep); } diff --git a/src/tests/test_abort1.c b/src/tests/test_abort1.c index a719fe9ec68..831431c2c68 100644 --- a/src/tests/test_abort1.c +++ b/src/tests/test_abort1.c @@ -21,7 +21,7 @@ test_db_open_aborts (void) { DB *db; int r; - struct stat buf; + toku_struct_stat buf; system("rm -rf " ENVDIR); r=toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); assert(r==0); r=db_env_create(&env, 0); assert(r==0); @@ -35,8 +35,8 @@ test_db_open_aborts (void) { r=tid->abort(tid); assert(r==0); } { - struct stat buf; - r=stat(ENVDIR "/foo.db", &buf); + toku_struct_stat buf; + r=toku_stat(ENVDIR "/foo.db", &buf); assert(r!=0); assert(errno==ENOENT); } @@ -59,22 +59,22 @@ test_db_open_aborts (void) { r=tid->abort(tid); assert(r==0); } { - r=stat(ENVDIR "/foo.db", &buf); + r=toku_stat(ENVDIR "/foo.db", &buf); assert(r!=0); assert(errno==ENOENT); - r=stat(ENVDIR "/foo.db.clean", &buf); + r=toku_stat(ENVDIR "/foo.db.clean", &buf); assert(r!=0); assert(errno==ENOENT); - r=stat(ENVDIR "/foo.db.dirty", &buf); + r=toku_stat(ENVDIR "/foo.db.dirty", &buf); assert(r!=0); assert(errno==ENOENT); } r=db->close(db, 0); assert(r==0); - r=stat(ENVDIR "/foo.db.clean", &buf); + r=toku_stat(ENVDIR "/foo.db.clean", &buf); assert(r!=0); assert(errno==ENOENT); - r=stat(ENVDIR "/foo.db.dirty", &buf); + r=toku_stat(ENVDIR "/foo.db.dirty", &buf); assert(r!=0); assert(errno==ENOENT); r=env->close(env, 0); assert(r==0); @@ -133,8 +133,8 @@ test_db_put_aborts (void) { } // The database should exist { - struct stat buf; - r=stat(ENVDIR "/foo.db", &buf); + toku_struct_stat buf; + r=toku_stat(ENVDIR "/foo.db", &buf); assert(r==0); } // But the item should not be in it. diff --git a/src/tests/test_abort4.c b/src/tests/test_abort4.c index b56a1d81ba1..a5f61370a38 100644 --- a/src/tests/test_abort4.c +++ b/src/tests/test_abort4.c @@ -110,9 +110,9 @@ do_nothing(DBT const *UU(a), DBT const *UU(b), void *UU(c)) { static void verify_and_tear_down(int close_first) { - struct stat temp; + toku_struct_stat temp; int r; - r = stat(ENVDIR "/foo.db", &temp); + r = toku_stat(ENVDIR "/foo.db", &temp); CKERR(r); if (close_first) { r=db->close(db, 0); CKERR(r); diff --git a/src/tests/test_abort5.c b/src/tests/test_abort5.c index 5cfb1af67e2..4066034111d 100644 --- a/src/tests/test_abort5.c +++ b/src/tests/test_abort5.c @@ -149,9 +149,9 @@ do_nothing(DBT const *UU(a), DBT const *UU(b), void *UU(c)) { static void verify_and_tear_down(int close_first) { - struct stat temp; + toku_struct_stat temp; int r; - r = stat(ENVDIR "/foo.db", &temp); + r = toku_stat(ENVDIR "/foo.db", &temp); CKERR(r); if (close_first) { r=db->close(db, 0); CKERR(r); diff --git a/src/tests/test_db_env_open_dir_priority.c b/src/tests/test_db_env_open_dir_priority.c index a98baf6703a..ec5c7921995 100644 --- a/src/tests/test_db_env_open_dir_priority.c +++ b/src/tests/test_db_env_open_dir_priority.c @@ -112,8 +112,8 @@ test_main(int argc, const char *argv[]) { //Verify it went in the right directory. { - struct stat buf; - r = stat(db_name, &buf); + toku_struct_stat buf; + r = toku_stat(db_name, &buf); CKERR(r); } #ifdef USE_TDB diff --git a/src/tests/test_log1.c b/src/tests/test_log1.c index 338ea41adf4..6c25751c751 100644 --- a/src/tests/test_log1.c +++ b/src/tests/test_log1.c @@ -44,8 +44,8 @@ test_main (int UU(argc), const char UU(*argv[])) { r=db->close(db, 0); assert(r==0); r=env->close(env, 0); assert(r==0); { - struct stat statbuf; - r = stat(ENVDIR "/foo.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/foo.db", &statbuf); assert(r==0); } return 0; diff --git a/src/tests/test_log1_abort.c b/src/tests/test_log1_abort.c index 59693ac1e6d..f5a3575c6ea 100644 --- a/src/tests/test_log1_abort.c +++ b/src/tests/test_log1_abort.c @@ -45,8 +45,8 @@ test_main (int UU(argc), const char UU(*argv[])) { r=db->close(db, 0); assert(r==0); r=env->close(env, 0); assert(r==0); { - struct stat statbuf; - r = stat(ENVDIR "/foo.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/foo.db", &statbuf); assert(r==-1); assert(errno==ENOENT); } diff --git a/src/tests/test_logmax.c b/src/tests/test_logmax.c index dedda08eff1..25d04f29c40 100644 --- a/src/tests/test_logmax.c +++ b/src/tests/test_logmax.c @@ -18,8 +18,8 @@ check_logmax (int max) { #define FULL_LEN (sizeof(ENVDIR)+NAME_MAX+1) char full_fname[FULL_LEN]; snprintf(full_fname, FULL_LEN, "%s/%s", ENVDIR, ent->d_name); - struct stat sbuf; - int r = stat(full_fname, &sbuf); + toku_struct_stat sbuf; + int r = toku_stat(full_fname, &sbuf); assert(r==0); if (verbose) printf("%s is of size %"PRId64"\n", ent->d_name, (int64_t)sbuf.st_size); diff --git a/src/tests/test_txn_abort7.c b/src/tests/test_txn_abort7.c index 2aee9d3c4cc..1eaee87b697 100644 --- a/src/tests/test_txn_abort7.c +++ b/src/tests/test_txn_abort7.c @@ -33,8 +33,8 @@ test_abort_create (void) { r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } @@ -44,8 +44,8 @@ test_abort_create (void) { r = env->close(env, 0); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r!=0); } diff --git a/src/tests/test_txn_abort8.c b/src/tests/test_txn_abort8.c index ca875650350..7b2273e329b 100644 --- a/src/tests/test_txn_abort8.c +++ b/src/tests/test_txn_abort8.c @@ -39,8 +39,8 @@ test_abort_close (void) { r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } @@ -52,8 +52,8 @@ test_abort_close (void) { r = env->close(env, 0); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r!=0); } #endif diff --git a/src/tests/test_txn_abort9.c b/src/tests/test_txn_abort9.c index de8ab2d01c8..e79d7a57c43 100644 --- a/src/tests/test_txn_abort9.c +++ b/src/tests/test_txn_abort9.c @@ -39,8 +39,8 @@ test_abort_close (void) { r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } diff --git a/src/tests/test_txn_close_open_commit.c b/src/tests/test_txn_close_open_commit.c index caf377e7f38..2c9154d4175 100644 --- a/src/tests/test_txn_close_open_commit.c +++ b/src/tests/test_txn_close_open_commit.c @@ -41,8 +41,8 @@ test_txn_close_open_commit (void) { r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } @@ -64,8 +64,8 @@ test_txn_close_open_commit (void) { r = env->close(env, 0); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } #endif diff --git a/src/tests/test_txn_commit8.c b/src/tests/test_txn_commit8.c index e2914359b50..bf188ece1f3 100644 --- a/src/tests/test_txn_commit8.c +++ b/src/tests/test_txn_commit8.c @@ -39,8 +39,8 @@ test_abort_close (void) { r = db->open(db, txn, "test.db", 0, DB_BTREE, DB_CREATE, S_IRWXU+S_IRWXG+S_IRWXO); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } @@ -52,8 +52,8 @@ test_abort_close (void) { r = env->close(env, 0); assert(r == 0); { - struct stat statbuf; - r = stat(ENVDIR "/test.db", &statbuf); + toku_struct_stat statbuf; + r = toku_stat(ENVDIR "/test.db", &statbuf); assert(r==0); } #endif diff --git a/src/ydb.c b/src/ydb.c index 3cc8702fed3..86957ffcfc9 100644 --- a/src/ydb.c +++ b/src/ydb.c @@ -359,19 +359,19 @@ static int toku_env_open(DB_ENV * env, const char *home, u_int32_t flags, int mo { BOOL made_new_home = FALSE; char* new_home = NULL; - struct stat buf; + toku_struct_stat buf; if (home[strlen(home)-1] == '\\') { new_home = toku_malloc(strlen(home)); memcpy(new_home, home, strlen(home)); new_home[strlen(home) - 1] = 0; made_new_home = TRUE; } - r = stat(made_new_home? new_home : home, &buf); + r = toku_stat(made_new_home? new_home : home, &buf); if (made_new_home) { toku_free(new_home); } if (r!=0) { - return toku_ydb_do_error(env, errno, "Error from stat(\"%s\",...)\n", home); + return toku_ydb_do_error(env, errno, "Error from toku_stat(\"%s\",...)\n", home); } } unused_flags &= ~DB_PRIVATE; @@ -2711,7 +2711,7 @@ static char *construct_full_name(const char *dir, const char *fname) { static int find_db_file(DB_ENV* dbenv, const char *fname, char** full_name_out) { u_int32_t i; int r; - struct stat statbuf; + toku_struct_stat statbuf; char* full_name; assert(full_name_out); @@ -2720,7 +2720,7 @@ static int find_db_file(DB_ENV* dbenv, const char *fname, char** full_name_out) for (i = 0; i < dbenv->i->n_data_dirs; i++) { full_name = construct_full_name(dbenv->i->data_dirs[0], fname); if (!full_name) return ENOMEM; - r = stat(full_name, &statbuf); + r = toku_stat(full_name, &statbuf); if (r == 0) goto finish; else { toku_free(full_name); @@ -2839,8 +2839,8 @@ static int toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *db openflags |= O_RDWR; { - struct stat statbuf; - if (stat(db->i->full_fname, &statbuf) == 0) { + toku_struct_stat statbuf; + if (toku_stat(db->i->full_fname, &statbuf) == 0) { /* If the database exists at the file level, and we specified no db_name, then complain here. */ if (dbname == 0 && is_db_create) { if (is_db_excl) { diff --git a/toku_include/toku_os.h b/toku_include/toku_os.h index 032cccd719a..7027208af3a 100644 --- a/toku_include/toku_os.h +++ b/toku_include/toku_os.h @@ -63,6 +63,11 @@ int toku_os_initialize_settings(int verbosity) __attribute__((__visibility__("d // int toku_os_is_absolute_name(const char* path) __attribute__((__visibility__("default"))); +// Portable linux 'stat' +int toku_stat(const char *name, toku_struct_stat *statbuf); +// Portable linux 'fstat' +int toku_fstat(int fd, toku_struct_stat *statbuf); + #if defined __cplusplus }; #endif diff --git a/toku_include/toku_portability.h b/toku_include/toku_portability.h index 0244edbb2f3..e94dcdce46f 100644 --- a/toku_include/toku_portability.h +++ b/toku_include/toku_portability.h @@ -28,6 +28,12 @@ extern "C" { #include "stdint.h" #include "inttypes.h" + +#ifndef TOKU_OFF_T_DEFINED +#define TOKU_OFF_T_DEFINED +typedef int64_t toku_off_t; +#endif + #include #include #include "unistd.h" @@ -43,6 +49,12 @@ extern "C" { #include #include + +#ifndef TOKU_OFF_T_DEFINED +#define TOKU_OFF_T_DEFINED +typedef int64_t toku_off_t; +#endif + #include #include #include @@ -67,17 +79,12 @@ extern "C" { #include "toku_os.h" #include "toku_htonl.h" -#ifndef TOKU_OFF_T_DEFINED -#define TOKU_OFF_T_DEFINED -typedef int64_t toku_off_t; -#endif - #define UU(x) x __attribute__((__unused__)) // Deprecated functions. #if !defined(TOKU_ALLOW_DEPRECATED) # if defined(__ICL) //Windows Intel Compiler -# pragma deprecated (creat, fstat, getpid, syscall, sysconf, mkdir, strdup) +# pragma deprecated (creat, fstat, stat, getpid, syscall, sysconf, mkdir, strdup) # pragma poison off_t # ifndef DONT_DEPRECATE_MALLOC # pragma deprecated (malloc, free, realloc) @@ -85,6 +92,7 @@ typedef int64_t toku_off_t; # else int creat() __attribute__((__deprecated__)); int fstat() __attribute__((__deprecated__)); +int stat() __attribute__((__deprecated__)); int getpid(void) __attribute__((__deprecated__)); long int syscall(long int __sysno, ...) __attribute__((__deprecated__)); // Sadly, dlmalloc needs sysconf, and on linux this causes trouble with -combine. So let the warnings show up under windows only. diff --git a/windows/dirs.c b/windows/dirs.c index 1ea907625fd..749a8fdbe3a 100644 --- a/windows/dirs.c +++ b/windows/dirs.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -93,3 +94,46 @@ closedir(DIR *dir) { free(dir); return r; } + +#define SUPPORT_CYGWIN_STYLE_STAT 0 +#define CYGWIN_ROOT_DIR_PREFIX "c:/cygwin" +#define CYGDRIVE_PREFIX "/cygdrive/" +int +toku_stat(const char *name, toku_struct_stat *statbuf) { + char new_name[strlen(name) + sizeof(CYGWIN_ROOT_DIR_PREFIX)]; + int bytes; +#if SUPPORT_CYGWIN_STYLE_STAT + if (name[0] == '/') { + char *cygdrive = strstr(name, CYGDRIVE_PREFIX); + if (cygdrive==name && isalpha(name[strlen(CYGDRIVE_PREFIX)])) + bytes = snprintf(new_name, sizeof(new_name), "%c:%s", name[strlen(CYGDRIVE_PREFIX)], name+strlen(CYGDRIVE_PREFIX)+1); //handle /cygdrive/DRIVELETTER + else bytes = snprintf(new_name, sizeof(new_name), "%s%s", CYGWIN_ROOT_DIR_PREFIX, name); //handle /usr/local (for example) + } + else +#endif + bytes = snprintf(new_name, sizeof(new_name), "%s", name); //default + //Verify no overflow + assert(bytes>=0); + assert((size_t)bytes < sizeof(new_name)); + int needdir = 0; + if (bytes>1 && new_name[bytes-1]=='/') { + //Strip trailing '/', but this implies it is a directory. + new_name[bytes-1] = '\0'; + needdir = 1; + } + toku_struct_stat temp; + int r = _stati64(new_name, &temp); + if (r==0 && needdir && !(temp.st_mode&_S_IFDIR)) { + r = -1; + errno = ENOENT; + } + if (r==0) *statbuf = temp; + return r; +} + +int +toku_fstat(int fd, toku_struct_stat *statbuf) { + int r = _fstati64(fd, statbuf); + return r; +} + diff --git a/windows/tests/test-ftruncate.c b/windows/tests/test-ftruncate.c index 911df07b3b3..6696637a0f3 100644 --- a/windows/tests/test-ftruncate.c +++ b/windows/tests/test-ftruncate.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -41,8 +42,8 @@ int main(void) { assert(r == sizeof junk); } - struct stat filestat; - r = fstat(fd, &filestat); + toku_struct_stat filestat; + r = toku_fstat(fd, &filestat); assert(r == 0); printf("orig size %lu\n", (unsigned long) filestat.st_size); fflush(stdout); @@ -50,7 +51,7 @@ int main(void) { r = ftruncate(fd, 0); assert(r == 0); - r = fstat(fd, &filestat); + r = toku_fstat(fd, &filestat); assert(r == 0); printf("truncated size %lu\n", (unsigned long) filestat.st_size); fflush(stdout); diff --git a/windows/tests/test-stat.c b/windows/tests/test-stat.c index 21b7da2cebd..bef9de594b8 100644 --- a/windows/tests/test-stat.c +++ b/windows/tests/test-stat.c @@ -4,30 +4,41 @@ #include #include #include +#include -void test_stat(char *dirname, int result) { +void test_stat(char *dirname, int result, int ex_errno) { int r; - struct stat s; - r = stat(dirname, &s); - printf("stat %s %d\n", dirname, r); fflush(stdout); + toku_struct_stat buf; + r = toku_stat(dirname, &buf); + printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); assert(r==result); + if (r!=0) assert(errno == ex_errno); } int main(void) { int r; - test_stat(".", 0); - test_stat("./", 0); + test_stat(".", 0, 0); + test_stat("./", 0, 0); r = system("rm -rf testdir"); assert(r==0); + test_stat("testdir", -1, ENOENT); + test_stat("testdir/", -1, ENOENT); + test_stat("testdir/foo", -1, ENOENT); + test_stat("testdir/foo/", -1, ENOENT); r = toku_os_mkdir("testdir", S_IRWXU); assert(r == 0); + test_stat("testdir/foo", -1, ENOENT); + test_stat("testdir/foo/", -1, ENOENT); + r = system("touch testdir/foo"); assert(r==0); + test_stat("testdir/foo", 0, 0); + test_stat("testdir/foo/", -1, ENOENT); - test_stat("testdir", 0); + test_stat("testdir", 0, 0); - test_stat("./testdir", 0); + test_stat("./testdir", 0, 0); + + test_stat("./testdir/", 0, 0); - test_stat("./testdir/", 0); - return 0; } diff --git a/windows/toku_os_types.h b/windows/toku_os_types.h index eec4b9f113d..e1a7dc6118f 100644 --- a/windows/toku_os_types.h +++ b/windows/toku_os_types.h @@ -7,6 +7,9 @@ extern "C" { #include #include +#include +#include + // define an OS handle typedef void *toku_os_handle_t; @@ -18,6 +21,7 @@ struct fileid { uint64_t st_ino; }; +typedef struct _stati64 toku_struct_stat; #if defined(__cplusplus) };