-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathappend-brr.c
More file actions
146 lines (131 loc) · 3.15 KB
/
append-brr.c
File metadata and controls
146 lines (131 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
* Synopsis:
* Atomic append of a blob request record to a file.,
* Usage:
* append-brr \
* /path/to/file
* start_request_time \
* transport \
* verb \
* algorithm:digest \
* chat_history \
* blob_size \
* wall_duration \
* Exit Status:
* 0 ok, blob request record appended to file
* 1 unexpected error
* Blame:
* jmscott@setspace.com
* setspace@gmail.com
* Note:
* No syntax checking is done on the fields of the blob request record.
* Only field sizes are checked. In particular, use _is_udig() in common.c
*
* O_CREAT must be an option on the file open, otherwise rolling the file
* is problemmatic. For example, without O_CREAT, the following
* trivial roll will fail for each append()
*
* mv pdf.log pdf-$(date +'%a').log
* # window when an error in append-brr could occur
*
* since pdf.log disappears briefly.
*
* Consider replacing write() with writev().
*/
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include "jmscott/libjmscott.h"
char *jmscott_progname = "append-brr";
static char usage[] =
"append-brr " \
"<path/to/file> " \
"<start_time> " \
"<transport> " \
"<verb> " \
"<udig> " \
"<chat_history> " \
"<blob_size> " \
"<wall_duration>"
;
#define MAX_BRR 419 // no newline or null
static void
die2(char *msg1, char *msg2)
{
jmscott_die2(1, msg1, msg2);
/*NOTREACHED*/
}
/*
* Build the brr record from a command line argument.
* Update the pointer to the position in the buffer.
*
* Note:
* Need to be more strict about correctness of brr fields.
* For example, a char set per arg would be easy to add.
*/
static void
arg2brr(char *name, char *arg, int size, char **brr)
{
char *tgt, *src;
int n;
n = 0;
src = arg;
tgt = *brr;
while (*src && n++ < size)
*tgt++ = *src++;
if (n == size && *src)
die2("arg too big for brr field", name);
*tgt++ = '\t';
*brr = tgt;
}
static int
_open(char *path)
{
int fd = jmscott_open(path,
O_WRONLY | O_APPEND | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP
);
if (fd < 0)
die2("open(append) failed", strerror(errno));
return fd;
}
static void
_write(int fd, char *buf, size_t nbytes)
{
if (jmscott_write(fd, buf, nbytes) < 0)
die2("write(brr) failed", strerror(errno));
}
static void
_close(int fd)
{
if (jmscott_close(fd))
die2("close(brr) failed", strerror(errno));
}
int
main(int argc, char **argv)
{
// room for brr + newline + null
char brr[MAX_BRR + 1], *b; // brr+newline
char *path;
int fd;
if (argc != 9)
jmscott_die_argc(1, argc, 9, usage);
path = argv[1];
/*
* Build the blob request record from command line arguments
*/
b = brr;
arg2brr("start time", argv[2], 10+1+8+1+9+1+6, &b);
arg2brr("transport", argv[3], 8+1+128, &b);
arg2brr("verb", argv[4], 8, &b);
arg2brr("udig", argv[5], 8+1+128, &b);
arg2brr("chat history", argv[6], 8, &b);
arg2brr("blob size", argv[7], 20, &b);
arg2brr("wall duration", argv[8], 10+1+9, &b);
b[-1] = '\n'; // zap trailing tab
fd = _open(path);
// atomically write exactly the number bytes in the blob request record
_write(fd, brr, b - brr);
_close(fd);
_exit(0);
}