Add support for writing to the offset file.
[easyotp.git] / libotp.c
blobd9b26d824891ef7a95618229ed66d7b3e0106a49
1 /** Practical One-time Pad Library
3 * Created:20080514
4 * By Jeff Connelly
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sysexits.h>
10 #include <string.h>
12 #define MARKER_TO "to:"
13 #define MARKER_BEGIN "--EMOTP_BEGIN--"
14 #define MARKER_END "--EMOTP_END--"
16 #define OFFSET_FILE_EXTENSION ".off"
17 #define OFFSET_SIZE 11 /* strlen("4294967296") + 1 */
19 /** Packaged up encrypted message, ready for transport. */
20 typedef struct _PACKAGE {
21 unsigned long offset;
22 char *pad_name;
23 char *cipher_text;
24 } PACKAGE;
26 typedef struct _PAD {
27 char *local_filename;
28 char *name;
29 FILE *fp;
30 struct _PAD *next;
31 /* Use read_offset() and write_offset() to access offset. */
32 } PAD;
34 PAD *pads = NULL;
36 /** Show a list of all loaded pads. */
37 void show_pads()
39 PAD *p;
41 for (p = pads; p; p = p->next) {
42 printf("Pad: %s: %s\n", p->name, p->local_filename);
46 /** Open a companion offset file for given pad. Caller must close.
48 * @param mode Either "rt" or "wt", for reading or writing.
50 FILE *open_offset_file(PAD *p, char *mode)
52 FILE *ofp;
53 char *offset_filename;
54 size_t filename_length;
56 /* Offset is stored in a separate file; pad plus OFFSET_FILE_NAME_EXTENSION. */
57 filename_length = strlen(p->local_filename) + strlen(OFFSET_FILE_EXTENSION) + 1;
58 offset_filename = malloc(filename_length);
59 if (!offset_filename) {
60 perror("malloc");
61 exit(EX_UNAVAILABLE);
63 snprintf(offset_filename, filename_length, "%s" OFFSET_FILE_EXTENSION, p->local_filename);
65 /* Read offset from file. */
66 ofp = fopen(offset_filename, mode);
67 if (!ofp) {
68 fprintf(stderr, "opening offset file %s failed\n", offset_filename);
69 perror("fopen");
70 free(offset_filename);
71 exit(EX_IOERR);
73 free(offset_filename);
75 return ofp;
78 /** Read the pad offset of a given pad. */
79 unsigned long read_offset(PAD *p)
81 FILE *ofp;
82 char buffer[OFFSET_SIZE];
83 unsigned long offset;
85 ofp = open_offset_file(p, "rt");
87 memset(buffer, 0, OFFSET_SIZE);
88 if (fread(buffer, 1, OFFSET_SIZE - 1, ofp) < 1) {
89 fprintf(stderr, "could not read offset file for %s\n", p->local_filename);
90 exit(EX_IOERR);
93 if (fclose(ofp) != 0) {
94 fprintf(stderr, "error closing offset file for reading for %s\n", p->local_filename);
95 perror("fclose");
96 exit(EX_IOERR);
99 /* We finally got it! */
100 offset = atol(buffer);
102 return offset;
105 /** Write the pad offset to the given pad. */
106 void write_offset(PAD *p, unsigned long offset)
108 FILE *ofp;
109 char buffer[OFFSET_SIZE];
111 ofp = open_offset_file(p, "wt");
113 memset(buffer, 0, OFFSET_SIZE);
114 snprintf(buffer, OFFSET_SIZE - 1, "%ld", offset);
115 printf("buffer=%s\n", buffer);
116 if (fwrite(buffer, strlen(buffer), 1, ofp) != 1) {
117 fprintf(stderr, "write error saving offset %ld for %s\n", offset, p->local_filename);
118 exit(EX_IOERR);
122 if (fclose(ofp) != 0) {
123 fprintf(stderr, "error closing offset file for writing for %s\n", p->local_filename);
124 perror("fclose");
125 exit(EX_IOERR);
129 /** Load a pad file from disk, adding to 'pads' global. */
130 void load_pad(char *local_filename)
132 FILE *fp;
133 PAD *new_pad;
135 fp = fopen("/Volumes/Not Backed Up/otp/otp-dazzlement", "rb");
136 if (!fp) {
137 perror("fopen");
138 exit(EXIT_FAILURE);
141 new_pad = malloc(sizeof(PAD));
142 if (!new_pad) {
143 perror("malloc");
144 exit(EX_UNAVAILABLE);
147 new_pad->local_filename = strdup(local_filename);
148 new_pad->name = strdup("dc"); /* TODO */
149 new_pad->fp = fp;
150 new_pad->next = NULL;
152 /* Add to linked list. */
153 if (!pads) {
154 pads = new_pad;
155 } else {
156 PAD *p, *tail;
158 /* Find tail */
159 for (p = pads; p; p = p->next)
160 tail = p;
161 tail->next = new_pad;
165 /** Close all pads and free allocated memory. */
166 void free_pads()
168 PAD *p, *next;
170 for (p = pads; p; p = next) {
171 free(p->name);
172 free(p->local_filename);
173 fclose(p->fp);
174 next = p->next;
175 free(p);
179 int main()
181 load_pad("/Volumes/Not Backed Up/otp/otp-dazzlement");
182 load_pad("/Volumes/Not Backed Up/otp/otp-dazzlement");
183 load_pad("/Volumes/Not Backed Up/otp/otp-dazzlement");
185 printf("offset=%ld\n", read_offset(pads));
186 write_offset(pads, 1213475);
187 printf("offset=%ld\n", read_offset(pads));
189 show_pads();
190 free_pads();
192 return 0;