Skip to content

Commit 3ff90be

Browse files
committed
fix some bugs
1 parent fe08f98 commit 3ff90be

File tree

5 files changed

+179
-626
lines changed

5 files changed

+179
-626
lines changed

Diff for: main.c

+166-142
Original file line numberDiff line numberDiff line change
@@ -1,185 +1,209 @@
11
#include "main.h"
2-
#include <time.h>
3-
#include <stdio.h>
2+
#include <dirent.h>
43
#include <locale.h>
5-
#include <string.h>
4+
#include <stdio.h>
65
#include <stdlib.h>
7-
#include <dirent.h>
8-
#include <unistd.h>
6+
#include <string.h>
97
#include <sys/inotify.h>
8+
#include <time.h>
9+
#include <unistd.h>
1010

11-
static void add_watch(const char *dpath);
12-
static void get_time(char *dest, size_t size);
13-
static void work(struct inotify_event *event);
11+
static void add_watch (const char *dpath);
12+
static void get_time (char *dest, size_t size);
13+
static void work (struct inotify_event *event);
1414

15-
int ifd;
16-
char *wdns[WATCH_SIZE];
15+
int inotify;
16+
char *entries[WATCH_SIZE];
1717

1818
int
19-
main(int argc, char **argv)
19+
main (int argc, char **argv)
2020
{
21-
CHECK(argc == 2, "must give a path");
22-
char *path = argv[1];
23-
size_t plen = strnlen(path, NAME_SIZE);
24-
path[plen - 1] == '/' ? path[plen - 1] = 0 : 0;
25-
26-
ifd = inotify_init();
27-
setlocale(LC_ALL, "en_US.UTF-8");
28-
CHECK(ifd >= 0, "inotify init failed");
29-
30-
ssize_t nread;
31-
char buf[BUFF_SIZE];
32-
struct inotify_event *event;
33-
34-
/* watch dirs recursively */
35-
add_watch(path);
36-
37-
for (;;) {
38-
nread = read(ifd, buf, BUFF_SIZE);
39-
CHECK(nread > 0, "read from inotify instance failed");
40-
41-
for (char *ptr = buf; ptr < buf + nread;) {
42-
event = (struct inotify_event *)ptr;
43-
inotify_add_watch(ifd, wdns[event->wd], IN_ONLYDIR);
44-
work(event);
45-
inotify_add_watch(ifd, wdns[event->wd], MASK);
46-
ptr += sizeof(struct inotify_event) + event->len;
21+
setlocale (LC_ALL, "en_US.UTF-8");
22+
CHECK (argc == 2, "must specify a listening path");
23+
24+
char *path = argv[1];
25+
size_t plen = strlen (path);
26+
(path[plen - 1] == '/') ? path[plen - 1] = '\0' : 0;
27+
28+
inotify = inotify_init ();
29+
CHECK (inotify >= 0, "inotify init failed");
30+
31+
ssize_t nread;
32+
char buff[BUFF_SIZE];
33+
struct inotify_event *event;
34+
35+
/* watch dirs recursively */
36+
add_watch (path);
37+
38+
for (;;)
39+
{
40+
nread = read (inotify, buff, BUFF_SIZE);
41+
CHECK (nread > 0, "read from inotify instance failed");
42+
43+
for (char *ptr = buff; ptr < buff + nread;)
44+
{
45+
event = (struct inotify_event *)ptr;
46+
/* inotify_rm_watch (inotify, event->wd); */
47+
inotify_add_watch (inotify, entries[event->wd], IN_ONLYDIR);
48+
work (event);
49+
inotify_add_watch (inotify, entries[event->wd], MASK);
50+
ptr += sizeof (struct inotify_event) + event->len;
4751
}
4852
}
4953

50-
for (int i = 0; i < WATCH_SIZE; i++)
51-
free(wdns[i]);
54+
for (int i = 0; i < WATCH_SIZE; i++)
55+
free (entries[i]);
5256
}
5357

5458
static void
55-
add_watch(const char *dpath)
59+
add_watch (const char *dpath)
5660
{
57-
DIR *dir = opendir(dpath);
58-
CHECK(dir != NULL, "open dir failed");
59-
60-
struct dirent *item;
61-
char npath[NAME_SIZE];
62-
size_t len = strnlen(dpath, NAME_SIZE);
63-
64-
for (item = readdir(dir); item; item = readdir(dir))
65-
if (item->d_type == DT_DIR) {
66-
if (!strncmp(item->d_name, ".", NAME_SIZE)) { /* watch self */
67-
int wd = inotify_add_watch(ifd, dpath, MASK);
68-
CHECK(wd > 0, "watch subdir failed");
69-
printf("watching: %s\n", dpath);
70-
71-
/* save full path */
72-
char *str = (char *)malloc(len + 1);
73-
strncpy(str, dpath, len);
74-
wdns[wd] = str;
75-
str[len] = 0;
76-
77-
continue;
78-
}
79-
80-
if (!strncmp(item->d_name, "..", NAME_SIZE)) /* skip parent dir */
81-
continue;
82-
83-
/* build full child dir path */
84-
size_t len2 = strnlen(item->d_name, NAME_SIZE);
85-
CHECK(len + len2 < NAME_SIZE - 2, "dirname is too long");
86-
87-
/* need `/` and `NULL` */
88-
npath[len] = '/';
89-
npath[len + len2 + 1] = 0;
90-
strncpy(npath, dpath, len);
91-
strncpy(npath + len + 1, item->d_name, len2);
92-
93-
add_watch(npath);
94-
}
95-
96-
closedir(dir);
61+
DIR *dir = opendir (dpath);
62+
CHECK (dir != NULL, "open dir failed");
63+
64+
struct dirent *item;
65+
char subdir[NAME_SIZE];
66+
size_t len = strlen (dpath);
67+
68+
for (item = readdir (dir); item; item = readdir (dir))
69+
if (item->d_type == DT_DIR)
70+
{
71+
if (strcmp (item->d_name, ".") == 0)
72+
{
73+
/* watch self */
74+
int wd = inotify_add_watch (inotify, dpath, MASK);
75+
CHECK (wd > 0, "watch subdir failed");
76+
printf ("watching: %s\n", dpath);
77+
78+
/* save full path */
79+
char *str = (char *)malloc (len + 1);
80+
CHECK (strcpy (str, dpath) == str, "copy path failed");
81+
entries[wd] = str;
82+
83+
continue;
84+
}
85+
86+
if (strcmp (item->d_name, "..") == 0)
87+
/* skip parent dir */
88+
continue;
89+
90+
/* build the full path of subdir */
91+
size_t item_len = strlen (item->d_name);
92+
memcpy (subdir, dpath, len);
93+
subdir[len] = '/';
94+
memcpy (subdir + len + 1, item->d_name, item_len + 1);
95+
96+
add_watch (subdir);
97+
}
98+
99+
closedir (dir);
97100
}
98101

99102
static void
100-
get_time(char *dest, size_t size)
103+
get_time (char *dest, size_t size)
101104
{
102-
time_t raw;
103-
time(&raw);
105+
time_t raw;
106+
time (&raw);
104107

105-
struct tm *tm = localtime(&raw);
106-
size_t ret = strftime(dest, size, "%Y-%m-%d %H:%M:%S", tm);
107-
CHECK(ret > 0, "strftime called failed");
108+
struct tm *tm = localtime (&raw);
109+
size_t ret = strftime (dest, size, "%Y-%m-%d %H:%M:%S", tm);
110+
CHECK (ret > 0, "strftime failed");
108111
}
109112

110113
static void
111-
work(struct inotify_event *event)
114+
work (struct inotify_event *event)
112115
{
113-
printf("\nfile event: %s/%s\n", wdns[event->wd], event->name);
116+
/* ignore files whose name start with `.` */
117+
if (event->name[0] == '.')
118+
return;
119+
120+
printf ("\nfile event: %s/%s\n", entries[event->wd], event->name);
114121

115-
size_t len = strnlen(wdns[event->wd], NAME_SIZE);
116-
/* do not use event->len directly */
117-
size_t len2 = strnlen(event->name, event->len);
118-
CHECK(len + len2 < NAME_SIZE - 2, "filename is too long");
122+
size_t len = strlen (entries[event->wd]);
123+
/* do not use event->len directly */
124+
size_t len2 = strlen (event->name);
119125

120-
/* check if it is an md file */
121-
if (strncmp(event->name + len2 - 3, ".md", 3)) {
122-
printf(" not markdown file: %s\n", event->name);
123-
return;
126+
/* check whether it's a markdown file */
127+
if (strcmp (event->name + len2 - 3, ".md") != 0)
128+
{
129+
printf (" not markdown file: %s\n", event->name);
130+
return;
124131
}
125132

126-
/* need `/` and `NULL` */
127-
char fpath[NAME_SIZE];
128-
fpath[len] = '/';
129-
fpath[len + len2 + 1] = 0;
130-
strncpy(fpath, wdns[event->wd], len);
131-
strncpy(fpath + len + 1, event->name, len2);
133+
char file_path[NAME_SIZE];
134+
memcpy (file_path, entries[event->wd], len);
135+
file_path[len] = '/';
136+
memcpy (file_path + len + 1, event->name, len2 + 1);
137+
138+
/* write delay */
139+
struct timespec ts;
140+
ts.tv_sec = 0;
141+
ts.tv_nsec = WRITE_DELAY;
142+
nanosleep (&ts, NULL);
143+
144+
FILE *fs = fopen (file_path, "r+");
145+
CHECK (fs != NULL, "open target file failed");
146+
147+
size_t line_len;
148+
char line_buff[LINE_SIZE];
149+
int front = 0, nline = 1;
150+
151+
for (;;)
152+
{
153+
if (fgets (line_buff, LINE_SIZE, fs) == NULL)
154+
{
155+
/* reach the end of the file*/
156+
printf (" there is no front-matter\n");
157+
goto end;
158+
}
132159

133-
FILE *fs = fopen(fpath, "r+");
134-
CHECK(fs != NULL, "open target file failed");
160+
/* save lbuf size */
161+
line_len = strnlen (line_buff, LINE_SIZE);
135162

136-
size_t llen;
137-
char lbuf[LINE_SIZE];
138-
int front = 0, nline = 1;
163+
/* find front-matter */
164+
if (nline && !strncmp (line_buff, "---", 3))
165+
front++;
139166

140-
for (;;) {
141-
if (fgets(lbuf, LINE_SIZE, fs) == NULL) { /* reach the end of the file*/
142-
printf(" there is no front-matter\n");
143-
goto end;
167+
if (front > 1)
168+
{
169+
/* can not find `updated` field */
170+
printf (" there is no updated field\n");
171+
return;
144172
}
145173

146-
llen = strnlen(lbuf, LINE_SIZE); /* save lbuf size */
147-
148-
if (nline && !strncmp(lbuf, "---", 3)) /* find front-matter */
149-
front++;
150-
if (front > 1) { /* can not find `updated` field */
151-
printf(" there is no updated field\n");
152-
goto end;
153-
}
154-
if (nline && !strncmp(lbuf, "updated", 7)) /* a potential problem */
155-
break;
174+
/* there is a potential problem */
175+
if (nline && !strncmp (line_buff, "updated", 7))
176+
break;
156177

157-
nline = lbuf[llen - 1] == '\n';
178+
nline = line_buff[line_len - 1] == '\n';
158179
}
159180

160-
/* try to update time */
161-
char tbuf[24];
162-
get_time(tbuf, 24);
163-
printf(" try to update\n");
164-
fseek(fs, -llen + 9, SEEK_CUR);
165-
166-
/* check if there is enough sapce */
167-
size_t space = 0;
168-
for (unsigned i = 9; i < llen; i++) {
169-
if (lbuf[i] == '\n' || lbuf[i] == 0)
170-
break;
171-
space++;
181+
/* try to update time */
182+
char time_buff[24];
183+
get_time (time_buff, 24);
184+
printf (" try to update\n");
185+
fseek (fs, -line_len + 9, SEEK_CUR);
186+
187+
/* check whether there is enough sapce */
188+
size_t space = 0;
189+
for (unsigned i = 9; i < line_len; i++)
190+
{
191+
if (line_buff[i] == '\n' || line_buff[i] == 0)
192+
break;
193+
space++;
172194
}
173-
if (space < 19) {
174-
printf(" there is no enough sapce to overwrite\n");
175-
goto end;
195+
196+
if (space < 19)
197+
{
198+
printf (" there is no enough sapce to overwrite\n");
199+
goto end;
176200
}
177201

178-
/* try to overwrite time */
179-
printf(" new time: %s\n", tbuf);
180-
CHECK(fputs(tbuf, fs) != EOF, "write target file failed");
181-
printf(" update successfully!\n");
202+
/* try to overwrite time */
203+
printf (" new time: %s\n", time_buff);
204+
CHECK (fputs (time_buff, fs) != EOF, "write target file failed");
205+
printf (" update successfully!\n");
182206

183207
end:
184-
fclose(fs);
208+
fclose (fs);
185209
}

Diff for: main.h

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
#ifndef MAIN_H
22
#define MAIN_H
33

4-
#define NAME_SIZE 256
5-
#define LINE_SIZE 1024
6-
#define BUFF_SIZE 4096
4+
/* bytes */
5+
#define NAME_SIZE 256
6+
#define LINE_SIZE 1024
7+
#define BUFF_SIZE 4096
78
#define WATCH_SIZE 4096
89

10+
/* nanosecs */
11+
#define WRITE_DELAY 500000
12+
913
#define MASK IN_CLOSE_WRITE
1014

11-
#define CHECK(expr, msg) \
12-
if (!(expr)) { \
13-
fprintf(stderr, "error on line: %d\nexpr: %s\nmsg : %s\n", __LINE__, \
14-
#expr, msg); \
15-
exit(0); \
15+
#define CHECK(expr, msg) \
16+
if (!(expr)) \
17+
{ \
18+
fprintf (stderr, "error on line: %d\nexpr: %s\nmsg : %s\n", __LINE__, \
19+
#expr, msg); \
20+
exit (0); \
1621
}
1722

1823
#endif

0 commit comments

Comments
 (0)