レポジトリ種類: Mercurial
#include <unistd.h>
#include <dirent.h>
#include "common.h"
#include "delpass.h"
int delcnt(const char *str, char delimiter) {
int count = 0;
while (*str) {
if (*str == delimiter) {
count++;
}
str++;
}
return count;
}
char **explode(const char *str, char delimiter, int *numtokens) {
int count = delcnt(str, delimiter) + 1;
*numtokens = count;
char **tokens = malloc(count * sizeof(char *));
if (tokens == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
char *strcopy = strdup(str);
if (strcopy == NULL) {
perror("strdup");
exit(EXIT_FAILURE);
}
char *token = strtok(strcopy, &delimiter);
int i = 0;
while (token != NULL) {
tokens[i] = strdup(token);
if (tokens[i] == NULL) {
perror("strdup");
exit(EXIT_FAILURE);
}
i++;
token = strtok(NULL, &delimiter);
}
free(strcopy);
return tokens;
}
void freetokens(char **tokens, int numtokens) {
for (int i = 0; i < numtokens; i++) {
free(tokens[i]);
}
free(tokens);
}
int delpass(char *file, int force) {
// パスを準備
char pwfile[512];
char *basedir = getbasedir(1);
char *ext = ".gpg";
int alllen = snprintf(NULL, 0, "%s%s%s", basedir, file, ext) + 1;
char *gpgpathchk = malloc(alllen);
if (gpgpathchk == NULL) {
if (strncmp(lang, "en", 2) == 0)
perror("Failed to allocate memory");
else perror("メモリを割当に失敗");
return -1;
}
// ファイルが既に存在するかどうか確認
snprintf(gpgpathchk, alllen, "%s%s%s", basedir, file, ext);
if (access(gpgpathchk, F_OK) != 0) {
if (strncmp(lang, "en", 2) == 0)
perror("Password does not exist");
else perror("パスワードが存在しません");
free(gpgpathchk);
return -1;
}
free(gpgpathchk);
int needed = snprintf( pwfile, sizeof(pwfile), "%s%s%s", basedir, file, ext);
if (needed >= (int)sizeof(pwfile)) {
if (strncmp(lang, "en", 2) == 0)
perror("Error: Path is too long");
else perror("エラー:パスが長すぎる");
return -1;
}
// 削除を確認する
if (force == 0) { // パスワードの変更の場合、確認は不要
if (strncmp(lang, "en", 2) == 0)
printf("Are you sure you want to delete the password '%s'? (y/N): ", file);
else
printf("パスワード「%s」を本当に削除する事が宜しいでしょうか? (y/N): ", file);
int confirm = getchar();
if (confirm != 'y' && confirm != 'Y') {
if (strncmp(lang, "en", 2) == 0) puts("Not deleted");
else puts("削除しませんでした");
return -1;
}
int ch;
while ((ch = getchar()) != '\n' && ch != EOF);
}
if (unlink(pwfile) == -1) {
if (strncmp(lang, "en", 2) == 0)
perror("Password cannot be deleted");
else perror("パスワードを削除出来ませんでした");
return -1;
}
// 空のディレクトリの場合
int numt;
char **tokens = explode(file, '/', &numt);
char passpath[1024];
snprintf(passpath, sizeof(passpath), "%s%s", basedir, tokens[0]);
char *ls = strrchr(basedir, '/');
if (ls != NULL) {
*ls = '\0';
}
for (int i = 1; i < numt; i++) {
if (i == (numt-1)) continue;
strncat(passpath, "/", sizeof(passpath) - strlen(passpath) - 1);
strncat(passpath, tokens[i], sizeof(passpath) - strlen(passpath) - 1);
}
for (int i = numt - 1; i >= 0; i--) {
// ~/.local/share/sp を削除したら危険
if (strncmp(passpath, basedir, sizeof(passpath)) == 0) {
break;
}
// ディレクトリが空じゃない場合、削除を止める
if (rmdir(passpath) == -1) {
break;
}
char *last_slash = strrchr(passpath, '/');
if (last_slash != NULL) {
*last_slash = '\0';
}
}
freetokens(tokens, numt);
// sp -e の場合、「パスワードを削除しました」って要らない
if (force == 1) return 0;
if (strncmp(lang, "en", 2) == 0) puts("The password got deleted");
else puts("パスワードを削除しました");
return 0;
}