1 /* cache.c: cache management
3 * Copyright (C) 2006 Lars Hjemli
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
11 const int NOLOCK
= -1;
13 char *cache_safe_filename(const char *unsafe
)
15 static char buf
[4][PATH_MAX
];
24 while(unsafe
&& (c
= *unsafe
++) != 0) {
25 if (c
== '/' || c
== ' ' || c
== '&' || c
== '|' ||
26 c
== '>' || c
== '<' || c
== '.')
34 int cache_exist(struct cacheitem
*item
)
36 if (stat(item
->name
, &item
->st
)) {
37 item
->st
.st_mtime
= 0;
43 int cache_create_dirs()
47 path
= fmt("%s", cgit_cache_root
);
48 if (mkdir(path
, S_IRWXU
) && errno
!=EEXIST
)
54 path
= fmt("%s/%s", cgit_cache_root
,
55 cache_safe_filename(cgit_repo
->url
));
57 if (mkdir(path
, S_IRWXU
) && errno
!=EEXIST
)
61 path
= fmt("%s/%s/%s", cgit_cache_root
,
62 cache_safe_filename(cgit_repo
->url
),
64 if (mkdir(path
, S_IRWXU
) && errno
!=EEXIST
)
70 int cache_refill_overdue(const char *lockfile
)
74 if (stat(lockfile
, &st
))
77 return (time(NULL
) - st
.st_mtime
> cgit_cache_max_create_time
);
80 int cache_lock(struct cacheitem
*item
)
83 char *lockfile
= xstrdup(fmt("%s.lock", item
->name
));
86 if (++i
> cgit_max_lock_attempts
)
87 die("cache_lock: unable to lock %s: %s",
88 item
->name
, strerror(errno
));
90 item
->fd
= open(lockfile
, O_WRONLY
|O_CREAT
|O_EXCL
, S_IRUSR
|S_IWUSR
);
92 if (item
->fd
== NOLOCK
&& errno
== ENOENT
&& cache_create_dirs())
95 if (item
->fd
== NOLOCK
&& errno
== EEXIST
&&
96 cache_refill_overdue(lockfile
) && !unlink(lockfile
))
100 return (item
->fd
> 0);
103 int cache_unlock(struct cacheitem
*item
)
106 return (rename(fmt("%s.lock", item
->name
), item
->name
) == 0);
109 int cache_cancel_lock(struct cacheitem
*item
)
111 return (unlink(fmt("%s.lock", item
->name
)) == 0);
114 int cache_expired(struct cacheitem
*item
)
118 return item
->st
.st_mtime
+ item
->ttl
* 60 < time(NULL
);