Skip to content

Commit

Permalink
Add ability to calculate MD5 or SHA1 digests in --ls
Browse files Browse the repository at this point in the history
Relates to #4
  • Loading branch information
maxsatula committed Mar 31, 2016
1 parent e1c0554 commit 3ddab89
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 24 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2016-01-01 Max Satula <[email protected]>

* Add ability to calculate MD5 or SHA1 digests in --ls

2015-12-31 Max Satula <[email protected]>

* Improve and optimize wildcard filtering for --ls
Expand Down
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ocp <future-version>

* added --sysdba and --sysoper options to connect to Oracle accordingly
* added --md5 and --sha1 options to calculate file hashes

----------------------------------------------------------------------------

Expand Down
34 changes: 28 additions & 6 deletions src/install.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ CREATE OR REPLACE\n\
TYPE t_ocp_file AS OBJECT (\n\
file_name VARCHAR2(200),\n\
bytes NUMBER,\n\
last_modified DATE);" },
last_modified DATE,\n\
digest RAW(20));" },
{ "\
CREATE OR REPLACE\n\
TYPE t_ocp_file_list IS TABLE OF t_ocp_file" },
Expand All @@ -46,6 +47,11 @@ CREATE OR REPLACE\n\
AS\n\
import java.io.File;\n\
import java.io.FilenameFilter;\n\
import java.io.FileInputStream;\n\
import java.io.FileNotFoundException;\n\
import java.io.IOException;\n\
import java.security.MessageDigest;\n\
import java.security.NoSuchAlgorithmException;\n\
import java.sql.Connection;\n\
import java.sql.SQLException;\n\
import java.sql.Timestamp;\n\
Expand Down Expand Up @@ -276,8 +282,8 @@ public class Globs {\n\
\n\
public class j_ocp_DirList\n\
{\n\
public static ARRAY getList(String directory, String pattern)\n\
throws SQLException\n\
public static ARRAY getList(String directory, String pattern, String hashAlgorithm)\n\
throws SQLException, NoSuchAlgorithmException\n\
{\n\
Connection conn = new OracleDriver().defaultConnection();\n\
ArrayDescriptor arrayDescriptor = new ArrayDescriptor(\"T_OCP_FILE_LIST\", conn);\n\
Expand All @@ -299,14 +305,30 @@ public class j_ocp_DirList\n\
} else {\n\
files = path.listFiles();\n\
}\n\
Object[][] result = new Object[files.length][3];\n\
Object[][] result = new Object[files.length][4];\n\
for (int i = 0; i < files.length; i++)\n\
{\n\
result[i][0] = files[i].getName();\n\
try\n\
{\n\
result[i][1] = new Long(files[i].length());\n\
result[i][2] = new Timestamp(files[i].lastModified());\n\
if (hashAlgorithm != null) {\n\
try {\n\
FileInputStream inputStream = new FileInputStream(files[i]);\n\
MessageDigest digest = MessageDigest.getInstance(hashAlgorithm);\n\
byte[] bytesBuffer = new byte[65536];\n\
int bytesRead = -1;\n\
\n\
while ((bytesRead = inputStream.read(bytesBuffer)) != -1) {\n\
digest.update(bytesBuffer, 0, bytesRead);\n\
}\n\
\n\
result[i][3] = digest.digest();\n\
}\n\
catch (FileNotFoundException e) {}\n\
catch (IOException e) {}\n\
}\n\
}\n\
catch ( java.security.AccessControlException e ) {}\n\
}\n\
Expand All @@ -315,10 +337,10 @@ public class j_ocp_DirList\n\
}" },
{ "\
CREATE OR REPLACE\n\
FUNCTION f_ocp_dir_list(p_directory IN VARCHAR2, p_pattern IN VARCHAR2)\n\
FUNCTION f_ocp_dir_list(p_directory IN VARCHAR2, p_pattern IN VARCHAR2, p_hashalgorithm IN VARCHAR2)\n\
RETURN t_ocp_file_list\n\
AS LANGUAGE JAVA\n\
NAME 'j_ocp_DirList.getList( java.lang.String, java.lang.String ) return oracle.sql.ARRAY';" },
NAME 'j_ocp_DirList.getList( java.lang.String, java.lang.String, java.lang.String ) return oracle.sql.ARRAY';" },
{ 0 }
};

Expand Down
82 changes: 66 additions & 16 deletions src/ls.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,29 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#endif

#include <stdio.h>
#include <string.h>
#include <oci.h>
#include "oracle.h"
#include "ocp.h"

void Ls(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, const char* patterns, int patternLength)
void Ls(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, const char* patterns, int patternLength, enum HASH_ALGORITHM hashAlgorithm)
{
sword ociResult;
char vFileName[MAX_FMT_SIZE];
char vHashAlgorithm[8];
ub8 vBytes;
char vLastModified[7];
int i;
unsigned char vDigest[20];
int hashLength;
int i, j;
long long totalBytes;
int foundKnownSize, foundUnknownSize;

struct BINDVARIABLE oraBindsLs[] =
{
{ 0, SQLT_CHR, ":patterns", patterns, patternLength },
{ 0, SQLT_STR, ":directory", pDirectory, ORA_IDENTIFIER_SIZE + 1 },
{ 0, SQLT_CHR, ":patterns", patterns, patternLength },
{ 0, SQLT_STR, ":hash_algorithm", vHashAlgorithm, sizeof(vHashAlgorithm) },
{ 0, SQLT_STR, ":directory", pDirectory, ORA_IDENTIFIER_SIZE + 1 },
{ 0 }
};

Expand All @@ -48,34 +53,76 @@ void Ls(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, const char* patter
{ 0, SQLT_STR, vFileName, sizeof(vFileName)-1, 0 },
{ 0, SQLT_INT, &vBytes, sizeof(vBytes), 0 },
{ 0, SQLT_DAT, vLastModified, sizeof(vLastModified), 0 },
{ 0, SQLT_BIN, vDigest, sizeof(vDigest), 0 },
{ 0 }
};

struct ORACLESTATEMENT oraStmtLs = {
"\
SELECT t.file_name,\
t.bytes,\
t.last_modified\
t.last_modified,\
t.digest\
FROM all_directories d,\
TABLE(f_ocp_dir_list(d.directory_path, :patterns)) t\
TABLE(f_ocp_dir_list(d.directory_path, :patterns, :hash_algorithm)) t\
WHERE d.directory_name = :directory",
0, oraBindsLs, oraDefinesLs };

switch (hashAlgorithm)
{
case HASH_MD5:
strcpy(vHashAlgorithm, "MD5");
hashLength = 16;
break;
case HASH_SHA1:
strcpy(vHashAlgorithm, "SHA1");
hashLength = 20;
break;
case HASH_NONE:
vHashAlgorithm[0] = '\0';
break;
}
SetSessionAction(oraAllInOne, "LS");
PrepareStmtAndBind(oraAllInOne, &oraStmtLs);

printf("Contents of %s directory\n\
if (hashAlgorithm != HASH_NONE)
{
printf("Contents of %s directory\n\
%-40s %s hash\n\
---------------------------------------- ",
pDirectory, "File Name", vHashAlgorithm);
for (j = 0; j < hashLength*2; j++)
printf("-");
printf("\n");
}
else
{
printf("Contents of %s directory\n\
%-40s %-12s %s\n\
---------------------------------------- ------------ -------------------\n",
pDirectory, "File Name", " Size", "Last Modified");
pDirectory, "File Name", " Size", "Last Modified");
}

i = 0;
totalBytes = 0;
foundKnownSize = foundUnknownSize = 0;
ociResult = ExecuteStmt(oraAllInOne);
while (ociResult == OCI_SUCCESS)
{
if (oraStmtLs.oraDefines[1].indp != -1 &&
if (hashAlgorithm != HASH_NONE)
{
printf("%-40s ",
vFileName);
if (oraStmtLs.oraDefines[3].indp != -1)
{
for (j = 0; j < hashLength; j++)
{
printf("%02x", vDigest[j]);
}
}
printf("\n");
}
else if (oraStmtLs.oraDefines[1].indp != -1 &&
oraStmtLs.oraDefines[2].indp != -1)
{
printf("%-40s %12lld %02d/%02d/%d %02d:%02d:%02d\n",
Expand Down Expand Up @@ -104,13 +151,16 @@ SELECT t.file_name,\
if (ociResult != OCI_NO_DATA)
ExitWithError(oraAllInOne, 4, ERROR_OCI, "Failed to list files in oracle directory\n");

if (i)
printf("---------------------------------------- ------------ -------------------\n");
printf("%5d File(s)", i);
if (!foundKnownSize && foundUnknownSize)
printf("\n");
else
printf(" %39lld%s\n", totalBytes, foundUnknownSize ? "+" : "");
if (hashAlgorithm == HASH_NONE)
{
if (i)
printf("---------------------------------------- ------------ -------------------\n");
printf("%5d File(s)", i);
if (!foundKnownSize && foundUnknownSize)
printf("\n");
else
printf(" %39lld%s\n", totalBytes, foundUnknownSize ? "+" : "");
}

ReleaseStmt(oraAllInOne);
SetSessionAction(oraAllInOne, 0);
Expand Down
18 changes: 17 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct PROGRAM_OPTIONS
enum TRANSFER_MODE transferMode;
const char* connectionString;
ub4 adminMode;
enum HASH_ALGORITHM hashAlgorithm;

int isStdUsed;
int numberOfOracleSessions;
Expand Down Expand Up @@ -165,6 +166,13 @@ int main(int argc, const char *argv[])
POPT_TABLEEND
};

struct poptOption lsOptions[] =
{
{ "md5", '\0', POPT_ARG_VAL, &programOptions.hashAlgorithm, HASH_MD5, "Calculate MD5 on listed files" },
{ "sha1", '\0', POPT_ARG_VAL, &programOptions.hashAlgorithm, HASH_SHA1, "Calculate SHA1 on listed files" },
POPT_TABLEEND
};

struct poptOption objOptions[] =
{
{ "install", '\0', POPT_ARG_NONE, 0, ACTION_INSTALL, "Install objects" },
Expand All @@ -181,6 +189,7 @@ int main(int argc, const char *argv[])
{ "sysoper", '\0', POPT_ARG_VAL, &programOptions.adminMode, OCI_SYSOPER, "Connect as SYSOPER" },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, transferModeOptions, 0, "Transfer options:" },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, compressionOptions, 0, "Compression options:" },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, lsOptions, 0, "File list options:" },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, objOptions, 0, "Database objects for --ls support:" },
POPT_AUTOHELP
POPT_TABLEEND
Expand All @@ -197,6 +206,7 @@ int main(int argc, const char *argv[])
programOptions.isStdUsed = 0;
programOptions.numberOfOracleSessions = 1;
programOptions.adminMode = OCI_DEFAULT;
programOptions.hashAlgorithm = 0;

poptcon = poptGetContext(NULL, argc, argv, options, 0);
while ((rc = poptGetNextOpt(poptcon)) >= 0)
Expand Down Expand Up @@ -257,6 +267,12 @@ int main(int argc, const char *argv[])
ExitWithUsage(&poptcon);
}

if (programOptions.hashAlgorithm && programOptions.programAction != ACTION_LS)
{
fprintf(stderr, "Hashing option can only be specified for list mode\n");
ExitWithUsage(&poptcon);
}

programOptions.connectionString = poptGetArg(poptcon);
if (!programOptions.connectionString)
{
Expand Down Expand Up @@ -480,7 +496,7 @@ int main(int argc, const char *argv[])
break;
case ACTION_LS:
TryDirectory(&oraAllInOne, vDirectory);
Ls(&oraAllInOne, vDirectory, filePatterns, filePatternPtr - filePatterns);
Ls(&oraAllInOne, vDirectory, filePatterns, filePatternPtr - filePatterns, programOptions.hashAlgorithm);
break;
case ACTION_RM:
TryDirectory(&oraAllInOne, vDirectory);
Expand Down
4 changes: 3 additions & 1 deletion src/ocp.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct ORACLEFILEATTR
ub8 length;
};

enum HASH_ALGORITHM { HASH_NONE, HASH_MD5, HASH_SHA1 };

void GetOracleFileAttr(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, char* pFileName, struct ORACLEFILEATTR *oraFileAttr);
void TryDirectory(struct ORACLEALLINONE *oraAllInOne, char* pDirectory);

Expand All @@ -53,7 +55,7 @@ void UploadFileWithCompression(struct ORACLEALLINONE *oraAllInOne, char* pDirect
int isKeepPartial, int isResume);

void LsDir(struct ORACLEALLINONE *oraAllInOne);
void Ls(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, const char* patterns, int patternLength);
void Ls(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, const char* patterns, int patternLength, enum HASH_ALGORITHM hashAlgorithm);
void Rm(struct ORACLEALLINONE *oraAllInOne, char* pDirectory, char* pFileName);

void InstallObjects(struct ORACLEALLINONE* oraAllInOne);
Expand Down

0 comments on commit 3ddab89

Please sign in to comment.