Browse Source

Added files, time-related tests still failing

master
suhrke 5 years ago
parent
commit
a1970a8f2b
  1. 4
      .gitignore
  2. 3
      .gitmodules
  3. 22
      Makefile
  4. 88
      src/Bitmap.hpp
  5. 201
      src/FileAttributes.cpp
  6. 199
      src/FileAttributes.hpp
  7. 1
      test/Catch
  8. 189
      test/catch.cpp

4
.gitignore vendored

@ -24,7 +24,11 @@ @@ -24,7 +24,11 @@
*.lib
# Executables
catch
*.exe
*.out
*.app
# Tool-generated files
tags

3
.gitmodules vendored

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
[submodule "test/Catch"]
path = test/Catch
url = https://github.com/philsquared/Catch.git

22
Makefile

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
EX=
TESTEX=catch
CC=g++
SRCDIR=src
TESTDIR=test
CFLAGS=-std=c++11 -I"$(SRCDIR)" -I"$(TESTDIR)/Catch/single_include"
all: test
test: FileAttributes.o catch.o
$(CC) $^ $(CFLAGS) -o $(TESTEX)
cp $(TESTEX) .git/hooks/pre-commit
catch.o: $(TESTDIR)/catch.cpp
$(CC) -c $^ $(CFLAGS)
FileAttributes.o: $(SRCDIR)/FileAttributes.cpp
$(CC) -c $^ $(CFLAGS)
clean:
rm *.o $(TESTEX) $(EX)

88
src/Bitmap.hpp

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
/*
* =====================================================================================
*
* Filename: Bitmap.h
*
* Description: Bitmap structs and defines
*
* Version: 1.0
* Created: 07/26/2017 09:38:18 PM
* Revision: none
* Compiler: gcc
*
* Author: suhrke@teknik.io
*
* =====================================================================================
*/
#ifndef BITMAP_H
#define BITMAP_H
#include <cstdint>
#define BI_RGB 0 //bitmap value for uncompressed color data
#define CHAR_BM 19778
//Padding specific to compiler - must account for padded bfType
// and little-endian order when overlaying struct on buffer
typedef struct OverlayBitmapFileHeader {
uint16_t bfType = CHAR_BM; //filetype, must be 'BM'
uint8_t bfSize0;
uint8_t bfSize1;
uint8_t bfSize2;
uint8_t bfSize3;
uint16_t bfReserved1 = 0;
uint16_t bfReserved2 = 0;
uint8_t bfOffBits0;
uint8_t bfOffBits1;
uint8_t bfOffBits2;
uint8_t bfOffBits3;
} OverlayBitmapFileHeader;
typedef struct BITMAPFILEHEADER {
uint16_t bfType = CHAR_BM;//filetype, must be 'BM'
uint32_t bfSize; //size in bytes of bitmap file
uint16_t bfReserved1 = 0; //unused, except to keep alignment
uint16_t bfReserved2 = 0; //unused, except to keep alignment
uint32_t bfOffBits; //offset in bytes from beginning of
// BITMAPFILEHEADER to the bitmap bits
} BITMAPFILEHEADER;
typedef struct BITMAPINFOHEADER {
uint32_t biSize; //# of bytes in struct
int32_t biWidth; //width of bitmap in pixels
int32_t biHeight; //height of bitmap in pixels
uint16_t biPlanes = 1; //# of planes for target device
uint16_t biBitCount; //bitmap, bits per pixel
uint32_t biCompression; //bitmap, type of compression
uint32_t biSizeImage; //size of image, in bytes
// 0 if BI_RGB
int32_t biXPelsPerMeter; //horizontal resolution of target device
int32_t biYPelsPerMeter; //vertical resolution of target device
uint32_t biClrUsed; //# of color indices in color table
// if 0, bitmap uses max # of colors that
// correspond to biBitCount
uint32_t biClrImportant; //# of color indices required for displaying bitmap
} BITMAPINFOHEADER;
typedef struct RGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved = 0;
} RGBQUAD;
typedef struct BITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
#endif //BITMAP_H

201
src/FileAttributes.cpp

@ -0,0 +1,201 @@ @@ -0,0 +1,201 @@
/*
* =====================================================================================
*
* Filename: FileAttributes.cpp
*
* Description: OS-agnostic, immutable file attribute storage created from stat
* struct or from data from roughly equivalent Windows types
*
* Version: 1.0
* Created: 08/01/2017 09:56:21 AM
* Revision: none
* Compiler: gcc
*
* Author: suhrke@teknik.io
*
* =====================================================================================
*/
#include <sstream>
#include "FileAttributes.hpp"
/*-----------------------------------------------------------------------------
* PUBLIC
*-----------------------------------------------------------------------------*/
// Construct from Windows types (typecast to portable versions)
FileAttributes::FileAttributes(FileTimePortable created,
FileTimePortable accessed,
FileTimePortable modified,
uint32_t size,
uint32_t attributes
) {
ctime_ = fileTimeToPosixTime(created);
atime_ = fileTimeToPosixTime(accessed);
mtime_ = fileTimeToPosixTime(modified);
//preserve value through unsigned to signed type
std::stringstream ss;
ss << size;
ss >> size_;
mode_ = modeFromFileAttributes(attributes);
windowsAttributes_ = attributes;
hasWindowsAttributes_ = true;
uid_ = UID_USER;
gid_ = GID_USER;
}
FileAttributes::FileAttributes(const uint32_t &mode,
const int16_t &uid,
const int16_t &gid,
const int64_t &size,
const time_t &atime,
const time_t &mtime,
const time_t &ctime
) {
mode_ = mode;
uid_ = uid;
gid_ = gid;
size_ = size;
atime_ = atime;
mtime_ = mtime;
ctime_ = ctime;
windowsAttributes_ = 0;
hasWindowsAttributes_ = false;
}
uint32_t
FileAttributes::getWindowsAttributes()
{
uint32_t windowsAttributes = 0;
if ( hasWindowsAttributes_ ) {
windowsAttributes = windowsAttributes_;
}
else {
uint32_t readAccess =
mode_ & ( POSIX_RUSR | POSIX_RGRP | POSIX_ROTH );
uint32_t writeAccess =
mode_ & ( POSIX_WUSR | POSIX_WGRP | POSIX_WOTH );
uint32_t executeAccess =
mode_ & ( POSIX_XUSR | POSIX_XGRP | POSIX_XOTH );
if ( readAccess != 0 && writeAccess == 0 && executeAccess == 0 ) {
windowsAttributes = WIN_READONLY;
}
else {
windowsAttributes = WIN_NORMAL;
}
}
return windowsAttributes;
}
FileTimePortable
FileAttributes::getCreatedTime()
{
return posixTimeToFileTime(ctime_);
}
FileTimePortable
FileAttributes::getAccessedTime()
{
return posixTimeToFileTime(atime_);
}
FileTimePortable
FileAttributes::getModifiedTime()
{
return posixTimeToFileTime(mtime_);
}
// Get Posix File Attributes (returns by ref)
// The missing attributes should be grabbed through syscalls
void
FileAttributes::getStat(uint32_t &mode,
int16_t &uid,
int16_t &gid,
int64_t &size,
time_t &atime,
time_t &mtime,
time_t &ctime
) {
mode = mode_;
uid = uid_;
gid = gid_;
size = size_;
atime = atime_;
mtime = mtime_;
ctime = ctime_;
}
/*-----------------------------------------------------------------------------
* PROTECTED
*-----------------------------------------------------------------------------*/
time_t
FileAttributes::fileTimeToPosixTime(FileTimePortable windowsTime)
{
uint64_t ticks = windowsTime.dwHighDateTime;
ticks = ticks << 32;
ticks |= windowsTime.dwLowDateTime;
return (time_t)( ticks / WINDOWS_TICK - SEC_TO_UNIX_EPOCH);
}
FileTimePortable
FileAttributes::posixTimeToFileTime(time_t posixTime)
{
uint64_t winTime = ((uint64_t)posixTime + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK;
FileTimePortable fileTime;
uint32_t highBytes = winTime >> 32;
fileTime.dwHighDateTime = highBytes;
fileTime.dwLowDateTime = winTime; // just 32 lower bits
return fileTime;
}
/*-----------------------------------------------------------------------------
* PRIVATE
*-----------------------------------------------------------------------------*/
uint32_t
FileAttributes::modeFromFileAttributes(uint32_t windowsFileAttributes)
{
uint32_t readAll = POSIX_RUSR | POSIX_RGRP | POSIX_ROTH;
uint32_t executeAll = POSIX_XUSR | POSIX_XGRP | POSIX_XOTH;
uint32_t mode; //bitvector
if( mode_ & WIN_READONLY ) {
mode |= readAll;
}
else {
// 755
mode |= readAll | executeAll | POSIX_WUSR;
}
}

199
src/FileAttributes.hpp

@ -0,0 +1,199 @@ @@ -0,0 +1,199 @@
/*
* =====================================================================================
*
* Filename: FileAttributes.h
*
* Description: OS-agnostic, immutable file attribute storage created from stat
* struct or from data from Windows GetFileAttributes
*
* Version: 1.0
* Created: 08/01/2017 08:53:17 AM
* Revision: none
* Compiler: gcc
*
* Author: suhrke@teknik.io
*
* =====================================================================================
*/
#ifndef PORTLIBCPP_FILE_ATTRIBUTES_HPP
#define PORTLIBCPP_FILE_ATTRIBUTES_HPP
#include <cstdint>
#include <ctime>
#define UID_USER 1000 // also often 100
#define UID_ROOT 0
#define GID_USER 1000 // also often 100
#define GID_ROOT 0
#define WINDOWS_TICK 10000000
#define SEC_TO_UNIX_EPOCH 11644473600LL
// Windows File Attributes (Bit Flags)
#define WIN_READONLY 1
#define WIN_HIDDEN 2 //by file name in *NIX
#define WIN_DIRECTORY 16
#define WIN_ARCHIVE 32
#define WIN_DEVICE 64 //reserved, bit should remain unset
#define WIN_NORMAL 128 //only valid when bit is only one set
#define WIN_COMPRESSED 2048
#define WIN_SYSTEM 4 //unused
#define WIN_TEMPORARY 256 //unused
#define WIN_SPARSE_FILE 512 //unused
#define WIN_REPARSE_POINT 1024 //unused
#define WIN_OFFLINE 4096 //unused
#define WIN_NOT_INDEXED 8192 //unused
#define WIN_INTEGRITY_STREAM 32768 //unused
#define WIN_VIRTUAL 65536 //unused
#define WIN_NO_SCRUB 131072 //unused
#define WIN_RECALL_ON_OPEN 262144 //unused
#define WIN_RECALL_ON_DATA_ACCESS 4194304 //unused
#define POSIX_RWXU 0x0000700
#define POSIX_RUSR 0x0000400
#define POSIX_WUSR 0x0000200
#define POSIX_XUSR 0x0000100
#define POSIX_RWXG 0x0000070
#define POSIX_RGRP 0x0000040
#define POSIX_WGRP 0x0000020
#define POSIX_XGRP 0x0000010
#define POSIX_RWXO 0x0000007
#define POSIX_ROTH 0x0000004
#define POSIX_WOTH 0x0000002
#define POSIX_XOTH 0x0000001
#define POSIX_SGID 0x0004000
#define POSIX_SUID 0x0002000
#define POSIX_SVTX 0x0001000
typedef struct FileTimePortable {
uint32_t dwLowDateTime;
uint32_t dwHighDateTime;
} FileTimePortable;
class FileAttributes
{
public:
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: Windows data constructor
* Description: Construct FileAttributes from FILETIME structs and a
* 32-bit attribute bitvector
* Note: should typecast each FILETIME to FileTimePortable and
* primitive types as necessary
*
*--------------------------------------------------------------------------------------
*/
FileAttributes(FileTimePortable created,
FileTimePortable accessed,
FileTimePortable modified,
uint32_t size,
uint32_t attributes);
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: Posix stat constructor
* Description: Construct FileAttributes from data from a stat struct
* Note: Type sizes in stat can vary. FileAttributes stores
* data such that the largest possible type from stat fits.
* Typecast as necessary.
*
*--------------------------------------------------------------------------------------
*/
FileAttributes(const uint32_t &mode,
const int16_t &uid,
const int16_t &gid,
const int64_t &size,
const time_t &atime,
const time_t &mtime,
const time_t &ctime);
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: getWindowsAttributes
* Description: Get bitvector containing file attributes
* Returns: uint32_t, attributes, guaranteed to be a 32-bit type
*--------------------------------------------------------------------------------------
*/
uint32_t getWindowsAttributes();
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: getCreatedTime
* Description: Get the Windows-compatible time the file was created
*--------------------------------------------------------------------------------------
*/
FileTimePortable getCreatedTime();
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: getAccessedTime
* Description: Get the Window-compatible time the file was accessed
*--------------------------------------------------------------------------------------
*/
FileTimePortable getAccessedTime();
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: getModifiedTime
* Description: Get the Window-compatible time the file was modified
*--------------------------------------------------------------------------------------
*/
FileTimePortable getModifiedTime();
// Get Posix File Attributes (returns by ref)
// The missing attributes should be grabbed through syscalls
/*
*--------------------------------------------------------------------------------------
* Class: FileAttributes
* Method: FileAttributes :: getStat
* Description: Get the POSIX-compatible stat struct data
* Parameters: Various values returned by reference
* Note: If FileAttributes was created with Windows data, mode
* will be 0755 if WIN_NORMAL or 0111 if WIN_READONLY,
* and uid and gid will be set to 0
*--------------------------------------------------------------------------------------
*/
void getStat(uint32_t &mode,
int16_t &uid,
int16_t &gid,
int64_t &size,
time_t &atime,
time_t &mtime,
time_t &ctime);
protected:
time_t fileTimeToPosixTime(FileTimePortable windowsTime);
FileTimePortable posixTimeToFileTime(time_t posixTime);
private:
// Convert Windows file attributes as closely as possible
uint32_t modeFromFileAttributes(uint32_t windowsFileAttributes);
uint32_t mode_;
int16_t uid_;
int16_t gid_;
int64_t size_;
time_t atime_;
time_t mtime_;
time_t ctime_;
// May contain additional flags not used by POSIX
uint32_t windowsAttributes_;
bool hasWindowsAttributes_;
};
#endif //PORTLIBCPP_FILE_ATTRIBUTES_HPP

1
test/Catch

@ -0,0 +1 @@ @@ -0,0 +1 @@
Subproject commit ec2074e55808d83117f70c633eb9ae47b433dd0d

189
test/catch.cpp

@ -0,0 +1,189 @@ @@ -0,0 +1,189 @@
/*
* =====================================================================================
*
* Filename: catch.cpp
*
* Description: Unit Tests using the Catch framework
*
* Version: 1.0
* Created: 08/01/2017 13:49:04 PM
* Revision: none
* Compiler: gcc
*
* Author: suhrke@teknik.io
*
* =====================================================================================
*/
#ifndef CATCH_CONFIG_MAIN
#define CATCH_CONFIG_MAIN
#include <cstdint>
#include "catch.hpp"
#include "FileAttributes.hpp"
#define LOW_DATE_TIME 3544886784
#define HIGH_DATE_TIME 30608146
#define CTIME 1501629833
#define ATIME 1501629886
#define MTIME 1501629889
TEST_CASE( "Instantiates from Windows data", "[FileAttributes]" ) {
// Mock up FILETIME struct data
FileTimePortable c;
c.dwLowDateTime = LOW_DATE_TIME;
c.dwHighDateTime = HIGH_DATE_TIME;
FileTimePortable a;
a.dwLowDateTime = LOW_DATE_TIME;
a.dwHighDateTime = HIGH_DATE_TIME + 1;
FileTimePortable m;
m.dwLowDateTime = LOW_DATE_TIME;
m.dwHighDateTime = HIGH_DATE_TIME + 2;
// Mock up other data
uint32_t attr = WIN_NORMAL;
uint32_t sz = 12341234;
// Instantiate object
FileAttributes fa(c, a, m, sz, attr);
SECTION( "Gets portable stat data" ) {
uint32_t mode;
int16_t uid;
int16_t gid;
int64_t size;
time_t atime;
time_t mtime;
time_t ctime;
fa.getStat(mode, uid, gid, size, atime, mtime, ctime);
SECTION( "Mode converted as closely as possible" ) {
REQUIRE( mode == 0x00000755 );
}
SECTION( "Default values are used for uid and gid" ) {
REQUIRE( uid == UID_USER );
REQUIRE( gid == GID_USER );
}
SECTION( "Size converts despite differently-signed types" ) {
REQUIRE( size == 12341234 );
}
SECTION( "FILETIME converts to time_t accurately" ) {
REQUIRE( ctime == 0);
REQUIRE( atime == 0);
REQUIRE( mtime == 0);
}
}
SECTION( "Windows -> POSIX -> Windows time works" ) {
FileTimePortable created = fa.getCreatedTime();
REQUIRE( created.dwLowDateTime == LOW_DATE_TIME );
REQUIRE( created.dwHighDateTime == HIGH_DATE_TIME );
FileTimePortable accessed = fa.getAccessedTime();
REQUIRE( accessed.dwLowDateTime == LOW_DATE_TIME );
REQUIRE( accessed.dwHighDateTime == HIGH_DATE_TIME + 1 );
FileTimePortable modified = fa.getModifiedTime();
REQUIRE( modified.dwLowDateTime == LOW_DATE_TIME );
REQUIRE( modified.dwHighDateTime == HIGH_DATE_TIME + 2 );
}
SECTION( "All Windows file attribute data is preserved in Win-Win" ) {
}
}
TEST_CASE( "READONLY translates from Windows to Linux", "[FileAttributes]" ) {
// Mock up FILETIME struct data (we dont care about what these are here)
FileTimePortable c;
FileTimePortable a;
FileTimePortable m;
// Mock up other data
uint32_t attr = WIN_READONLY;
uint32_t sz = 12341234;
// Instantiate object
FileAttributes fa(c, a, m, sz, attr);
uint32_t mode;
int16_t uid;
int16_t gid;
int64_t size;
time_t atime;
time_t mtime;
time_t ctime;
fa.getStat(mode, uid, gid, size, atime, mtime, ctime);
REQUIRE( mode == 0x00000444 );
}
TEST_CASE( "Instantiates from Linux data", "[FileAttributes]" ) {
// Mock up stat struct data
uint32_t md = 0x00000444;
uint16_t u = 1001;
uint16_t g = 1;
int64_t sz = 12341234;
time_t access = ATIME;
time_t modify = MTIME;
time_t create = CTIME;
// Instantiate object
FileAttributes fa(md, u, g, sz, access, modify, create);
SECTION( "Gets portable stat data" ) {
uint32_t mode;
int16_t uid;
int16_t gid;
int64_t size;
time_t atime;
time_t mtime;
time_t ctime;
fa.getStat(mode, uid, gid, size, atime, mtime, ctime);
REQUIRE( mode == 0x00000444 );
REQUIRE( uid == 1001 );
REQUIRE( gid == 1 );
}
SECTION( "Read-only permissions translate to Windows" ) {
uint32_t attributes = fa.getWindowsAttributes();
uint32_t readOnlyBits = attributes & WIN_READONLY;
REQUIRE( readOnlyBits != 0 );
}
SECTION( "Converts creation time to FILETIME successfully" ) {
FileTimePortable cFileTime = fa.getCreatedTime();
REQUIRE( cFileTime.dwLowDateTime == 0);
REQUIRE( cFileTime.dwHighDateTime == 0 );
}
SECTION( "Converts accessed time to FILETIME successfully" ) {
FileTimePortable aFileTime = fa.getAccessedTime();
REQUIRE( aFileTime.dwLowDateTime == 0);
REQUIRE( aFileTime.dwHighDateTime == 0 );
}
SECTION( "Converts modified time to FILETIME successfully" ) {
FileTimePortable mFileTime = fa.getModifiedTime();
REQUIRE( mFileTime.dwLowDateTime == 0);
REQUIRE( mFileTime.dwHighDateTime == 0 );
}
}
#endif //CATCH_CONFIG_MAIN
Loading…
Cancel
Save