|
|
int cssclean(const char *filename) { | int cssclean(const char *filename) { |
int i; | int i; |
hash_drv_header_t header; | hash_drv_header_t header; |
struct _hash_drv_storage s; |
FILE* lockfile; |
void *offset; | void *offset; |
struct _hash_drv_map old, new; | struct _hash_drv_map old, new; |
hash_drv_spam_record_t rec; | hash_drv_spam_record_t rec; |
unsigned long filepos; | unsigned long filepos; |
char newfile[PATH_MAX]; |
char *dir = NULL; |
char *oldfile; |
char *newfile = NULL; |
char *home, *username; |
|
struct stat st; | struct stat st; |
| |
unsigned long hash_rec_max = HASH_REC_MAX; | unsigned long hash_rec_max = HASH_REC_MAX; |
|
|
if (READ_ATTRIB("HashMaxSeek")) | if (READ_ATTRIB("HashMaxSeek")) |
max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0); | max_seek = strtol(READ_ATTRIB("HashMaxSeek"), NULL, 0); |
| |
oldfile = strdup(filename); |
if (stat(filename, &st) < 0) |
if (!oldfile) |
|
return EFAILURE; | return EFAILURE; |
oldfile = dirname(oldfile); /* oldfile may not be free'd now */ |
|
snprintf(newfile, sizeof(newfile), "%s/%u.css", oldfile, (unsigned int) getpid()); |
|
| |
/* set home and username */ |
/* create a temporary file name */ |
username = strdup(oldfile); |
dir = strdup(filename); |
home = strdup(oldfile); |
if (dir == NULL) |
if (!username || !home) |
|
return EFAILURE; |
|
username = basename(username); /* username may not be free'd now */ |
|
home = dirname(home); /* home may not be free'd now */ |
|
/* make sure at least /two/dirs/to.css for sane operation */ |
|
if (!strcmp(username, home)) |
|
return EFAILURE; | return EFAILURE; |
|
newfile = tempnam(dirname(dir), "css"); |
if (stat(filename, &st) < 0) |
if (newfile == NULL) |
return EFAILURE; | return EFAILURE; |
| |
if (_hash_drv_lock_get (home, &s, username) < 0) |
lockfile = _hash_tools_lock_get (filename); |
|
if (lockfile == NULL) |
return EFAILURE; | return EFAILURE; |
| |
if (_hash_drv_open(filename, &old, 0, max_seek, | if (_hash_drv_open(filename, &old, 0, max_seek, |
max_extents, extent_size, pctincrease, flags)) | max_extents, extent_size, pctincrease, flags)) |
goto unlock; |
goto end; |
| |
if (_hash_drv_open(newfile, &new, hash_rec_max, max_seek, | if (_hash_drv_open(newfile, &new, hash_rec_max, max_seek, |
max_extents, extent_size, pctincrease, flags)) { | max_extents, extent_size, pctincrease, flags)) { |
_hash_drv_close(&old); | _hash_drv_close(&old); |
goto unlock; |
goto end; |
} | } |
|
|
|
/* preserve counters */ |
|
memcpy(new.header, old.header, sizeof(*new.header)); |
| |
if (fchown(new.fd, st.st_uid, st.st_gid) < 0) { | if (fchown(new.fd, st.st_uid, st.st_gid) < 0) { |
_hash_drv_close(&new); | _hash_drv_close(&new); |
_hash_drv_close(&old); | _hash_drv_close(&old); |
unlink(newfile); | unlink(newfile); |
goto unlock; |
goto end; |
} | } |
| |
if (fchmod(new.fd, st.st_mode) < 0) { | if (fchmod(new.fd, st.st_mode) < 0) { |
_hash_drv_close(&new); | _hash_drv_close(&new); |
_hash_drv_close(&old); | _hash_drv_close(&old); |
unlink(newfile); | unlink(newfile); |
goto unlock; |
goto end; |
} | } |
| |
filepos = sizeof(struct _hash_drv_header); | filepos = sizeof(struct _hash_drv_header); |
|
|
_hash_drv_close(&new); | _hash_drv_close(&new); |
_hash_drv_close(&old); | _hash_drv_close(&old); |
unlink(newfile); | unlink(newfile); |
goto unlock; |
goto end; |
} | } |
} | } |
filepos += sizeof(struct _hash_drv_spam_record); | filepos += sizeof(struct _hash_drv_spam_record); |
|
|
_hash_drv_close(&new); | _hash_drv_close(&new); |
_hash_drv_close(&old); | _hash_drv_close(&old); |
if (rename(newfile, filename) < 0) | if (rename(newfile, filename) < 0) |
goto unlock; |
goto end; |
rc = 0; | rc = 0; |
| |
unlock: |
end: |
_hash_drv_lock_free(&s, username); |
if (dir) |
|
free(dir); |
|
if (newfile) |
|
free(newfile); |
|
_hash_tools_lock_free(filename, lockfile); |
return rc; | return rc; |
} | } |
| |