mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Removes support to symlink to dirs in Windows. They are different than symlinks to files.
This commit is contained in:
parent
6da21cdbd9
commit
3cd7b4ee03
8 changed files with 68 additions and 48 deletions
6
HISTORY
6
HISTORY
|
|
@ -10,9 +10,9 @@ SnapRAID HISTORY
|
|||
* Added a new -i, --import option to automatically import deleted files
|
||||
when fixing.
|
||||
* Added support also for hardlinks and empty directories.
|
||||
* Added support to save symlinks in Windows. Note that only the symlink
|
||||
is saved and not the linked file or directory.
|
||||
Junctions are still not supported.
|
||||
* Added support to save symlinks to files in Windows. Note that only the
|
||||
symlink is saved and not the linked file.
|
||||
Symlinks to dirs and junctions are still not supported.
|
||||
* Files without read permission generates now an error instead of a warning.
|
||||
You now must explicitely exclude them in the configuration file with
|
||||
exclusion rules.
|
||||
|
|
|
|||
4
check.c
4
check.c
|
|
@ -1109,7 +1109,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (link_is_hardlink(link)) {
|
||||
if (link_flag_has(link, FILE_IS_HARDLINK)) {
|
||||
/* stat the link */
|
||||
pathprint(path, sizeof(path), "%s%s", disk->dir, link->sub);
|
||||
ret = stat(path, &st);
|
||||
|
|
@ -1196,7 +1196,7 @@ static int state_check_process(struct snapraid_state* state, int check, int fix,
|
|||
}
|
||||
|
||||
/* create it */
|
||||
if (link_is_hardlink(link)) {
|
||||
if (link_flag_has(link, FILE_IS_HARDLINK)) {
|
||||
ret = hardlink(pathto, path);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Error writing hardlink '%s'. %s.\n", path, strerror(errno));
|
||||
|
|
|
|||
4
elem.c
4
elem.c
|
|
@ -391,14 +391,14 @@ int file_path_compare(const void* void_arg, const void* void_data)
|
|||
return strcmp(arg, file->sub);
|
||||
}
|
||||
|
||||
struct snapraid_link* link_alloc(const char* sub, const char* linkto, int is_hardlink)
|
||||
struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag)
|
||||
{
|
||||
struct snapraid_link* link;
|
||||
|
||||
link = malloc_nofail(sizeof(struct snapraid_link));
|
||||
pathcpy(link->sub, sizeof(link->sub), sub);
|
||||
pathcpy(link->linkto, sizeof(link->linkto), linkto);
|
||||
link->flag = is_hardlink != 0 ? FILE_IS_HARDLINK : 0;
|
||||
link->flag = link_flag;
|
||||
|
||||
return link;
|
||||
}
|
||||
|
|
|
|||
32
elem.h
32
elem.h
|
|
@ -135,12 +135,17 @@ struct snapraid_block {
|
|||
*/
|
||||
#define BLOCK_EMPTY 0
|
||||
|
||||
#define FILE_IS_PRESENT 1 /**< If it's seen as present. */
|
||||
#define FILE_IS_EXCLUDED 2 /**< If it's an excluded file from the processing. */
|
||||
#define FILE_IS_LARGER 4 /**< If a larger file was already detected. Just to avoid to report it more times. */
|
||||
#define FILE_IS_DAMAGED 8 /**< If a fix was attempted but it failed. */
|
||||
#define FILE_IS_FIXED 16 /**< If a fix was done. */
|
||||
#define FILE_IS_HARDLINK 32 /**< If it's an hardlink. */
|
||||
#define FILE_IS_PRESENT 0x01 /**< If it's seen as present. */
|
||||
#define FILE_IS_EXCLUDED 0x02 /**< If it's an excluded file from the processing. */
|
||||
#define FILE_IS_LARGER 0x04 /**< If a larger file was already detected. Just to avoid to report it more times. */
|
||||
#define FILE_IS_DAMAGED 0x08 /**< If a fix was attempted but it failed. */
|
||||
#define FILE_IS_FIXED 0x10 /**< If a fix was done. */
|
||||
|
||||
#define FILE_IS_HARDLINK 0x100 /**< If it's an hardlink. */
|
||||
#define FILE_IS_SYMLINK 0x200 /**< If it's a file symlink. */
|
||||
#define FILE_IS_SYMDIR 0x400 /**< If it's a dir symlink for Windows. Not yet supported. */
|
||||
#define FILE_IS_JUNCTION 0x800 /**< If it's a junction for Windows. Not yet supported. */
|
||||
#define FILE_IS_LINK_MASK 0xF00 /**< Mask for link type. */
|
||||
|
||||
/**
|
||||
* Value used to mark files without the nanoseconds value.
|
||||
|
|
@ -515,18 +520,21 @@ static inline void link_flag_clear(struct snapraid_link* link, unsigned mask)
|
|||
link->flag &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the link is a hardlink. Otherwise it's a symbolic link.
|
||||
*/
|
||||
static inline int link_is_hardlink(struct snapraid_link* link)
|
||||
static inline void link_flag_let(struct snapraid_link* link, unsigned flag, unsigned mask)
|
||||
{
|
||||
return link_flag_has(link, FILE_IS_HARDLINK);
|
||||
link->flag &= ~mask;
|
||||
link->flag |= flag & mask;
|
||||
}
|
||||
|
||||
static inline unsigned link_flag_get(struct snapraid_link* link, unsigned mask)
|
||||
{
|
||||
return link->flag & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a link.
|
||||
*/
|
||||
struct snapraid_link* link_alloc(const char* name, const char* link, int is_hardlink);
|
||||
struct snapraid_link* link_alloc(const char* name, const char* link, unsigned link_flag);
|
||||
|
||||
/**
|
||||
* Deallocates a link.
|
||||
|
|
|
|||
18
mingw.c
18
mingw.c
|
|
@ -330,8 +330,13 @@ static void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE
|
|||
st->st_desc = "reparse-point-nfs";
|
||||
break;
|
||||
case IO_REPARSE_TAG_SYMLINK :
|
||||
st->st_mode = S_IFLNK;
|
||||
st->st_desc = "reparse-point-symlink";
|
||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
||||
st->st_mode = S_IFLNKDIR;
|
||||
st->st_desc = "reparse-point-symlink-dir";
|
||||
} else {
|
||||
st->st_mode = S_IFLNK;
|
||||
st->st_desc = "reparse-point-symlink-file";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
st->st_mode = S_IFCHR;
|
||||
|
|
@ -418,8 +423,13 @@ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_s
|
|||
st->st_desc = "reparse-point-nfs";
|
||||
break;
|
||||
case IO_REPARSE_TAG_SYMLINK :
|
||||
st->st_mode = S_IFLNK;
|
||||
st->st_desc = "reparse-point-symlink";
|
||||
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
|
||||
st->st_mode = S_IFLNKDIR;
|
||||
st->st_desc = "reparse-point-symlink-dir";
|
||||
} else {
|
||||
st->st_mode = S_IFLNK;
|
||||
st->st_desc = "reparse-point-symlink-file";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
st->st_mode = S_IFCHR;
|
||||
|
|
|
|||
7
mingw.h
7
mingw.h
|
|
@ -58,8 +58,13 @@
|
|||
#define dirent_lstat windows_dirent_lstat
|
||||
#define stat_desc windows_stat_desc
|
||||
#define sleep windows_sleep
|
||||
#define S_IFLNK 0x7000 /* 4==DIR, 8==REG */
|
||||
/* 4==DIR, 5,6,7=free, 8==REG */
|
||||
#define S_IFLNK 0x5000 /* Symbolic link to file */
|
||||
#define S_ISLNK(m) (((m) & _S_IFMT) == S_IFLNK)
|
||||
#define S_IFLNKDIR 0x6000 /* Symbolic link to directory */
|
||||
#define S_ISLNKDIR(m) (((m) & _S_IFMT) == S_IFLNKDIR)
|
||||
#define S_IFJUN 0x6000 /* Junction */
|
||||
#define S_ISJUN(m) (((m) & _S_IFMT) == S_IFJUN)
|
||||
#define readlink windows_readlink
|
||||
#define symlink windows_symlink
|
||||
#define link windows_link
|
||||
|
|
|
|||
22
scan.c
22
scan.c
|
|
@ -71,7 +71,7 @@ static void scan_link_insert(struct snapraid_state* state, struct snapraid_disk*
|
|||
/**
|
||||
* Processes a symbolic link.
|
||||
*/
|
||||
static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state, int output, struct snapraid_disk* disk, const char* sub, const char* linkto, int is_hardlink)
|
||||
static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state, int output, struct snapraid_disk* disk, const char* sub, const char* linkto, unsigned link_flag)
|
||||
{
|
||||
struct snapraid_link* link;
|
||||
|
||||
|
|
@ -80,10 +80,7 @@ static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
if (link) {
|
||||
/* check if multiple files have the same name */
|
||||
if (link_flag_has(link, FILE_IS_PRESENT)) {
|
||||
if (link_is_hardlink(link))
|
||||
fprintf(stderr, "Internal inconsistency for hardlink '%s%s'\n", disk->dir, sub);
|
||||
else
|
||||
fprintf(stderr, "Internal inconsistency for symlink '%s%s'\n", disk->dir, sub);
|
||||
fprintf(stderr, "Internal inconsistency for link '%s%s'\n", disk->dir, sub);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +88,7 @@ static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
link_flag_set(link, FILE_IS_PRESENT);
|
||||
|
||||
/* check if the link is not changed and it's of the same kind */
|
||||
if (strcmp(link->linkto, linkto) == 0 && is_hardlink == link_is_hardlink(link)) {
|
||||
if (strcmp(link->linkto, linkto) == 0 && link_flag == link_flag_get(link, FILE_IS_LINK_MASK)) {
|
||||
/* it's equal */
|
||||
++scan->count_equal;
|
||||
|
||||
|
|
@ -116,10 +113,7 @@ static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
|
||||
/* update it */
|
||||
pathcpy(link->linkto, sizeof(link->linkto), linkto);
|
||||
if (is_hardlink)
|
||||
link_flag_set(link, FILE_IS_HARDLINK);
|
||||
else
|
||||
link_flag_clear(link, FILE_IS_HARDLINK);
|
||||
link_flag_let(link, link_flag, FILE_IS_LINK_MASK);
|
||||
|
||||
/* nothing more to do */
|
||||
return;
|
||||
|
|
@ -140,7 +134,7 @@ static void scan_link(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
}
|
||||
|
||||
/* insert it */
|
||||
link = link_alloc(sub, linkto, is_hardlink);
|
||||
link = link_alloc(sub, linkto, link_flag);
|
||||
|
||||
/* mark it as present */
|
||||
link_flag_set(link, FILE_IS_PRESENT);
|
||||
|
|
@ -290,7 +284,7 @@ static void scan_file(struct snapraid_scan* scan, struct snapraid_state* state,
|
|||
if (file_flag_has(file, FILE_IS_PRESENT)) {
|
||||
if (st->st_nlink > 1) {
|
||||
/* it's a hardlink */
|
||||
scan_link(scan, state, output, disk, sub, file->sub, 1);
|
||||
scan_link(scan, state, output, disk, sub, file->sub, FILE_IS_HARDLINK);
|
||||
return;
|
||||
} else {
|
||||
fprintf(stderr, "Internal inode '%"PRIu64"' inconsistency for file '%s%s'\n", (uint64_t)st->st_ino, disk->dir, sub);
|
||||
|
|
@ -500,7 +494,7 @@ static void scan_emptydir(struct snapraid_scan* scan, struct snapraid_state* sta
|
|||
if (dir) {
|
||||
/* check if multiple files have the same name */
|
||||
if (dir_flag_has(dir, FILE_IS_PRESENT)) {
|
||||
fprintf(stderr, "Internal inconsistency for symdir '%s%s'\n", disk->dir, sub);
|
||||
fprintf(stderr, "Internal inconsistency for dir '%s%s'\n", disk->dir, sub);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -655,7 +649,7 @@ static int scan_dir(struct snapraid_scan* scan, struct snapraid_state* state, in
|
|||
subnew[ret] = 0;
|
||||
|
||||
/* process as a symbolic link */
|
||||
scan_link(scan, state, output, disk, sub_next, subnew, 0);
|
||||
scan_link(scan, state, output, disk, sub_next, subnew, FILE_IS_SYMLINK);
|
||||
processed = 1;
|
||||
} else {
|
||||
if (state->verbose) {
|
||||
|
|
|
|||
23
state.c
23
state.c
|
|
@ -713,16 +713,16 @@ void state_read(struct snapraid_state* state)
|
|||
unsigned line;
|
||||
unsigned count_file;
|
||||
unsigned count_block;
|
||||
unsigned count_symlink;
|
||||
unsigned count_hardlink;
|
||||
unsigned count_symlink;
|
||||
unsigned count_dir;
|
||||
tommy_node* node;
|
||||
oathash_t hash;
|
||||
|
||||
count_file = 0;
|
||||
count_block = 0;
|
||||
count_symlink = 0;
|
||||
count_hardlink = 0;
|
||||
count_symlink = 0;
|
||||
count_dir = 0;
|
||||
hash = 0;
|
||||
|
||||
|
|
@ -1168,7 +1168,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* allocate the link as symbolic link */
|
||||
link = link_alloc(sub, linkto, 0);
|
||||
link = link_alloc(sub, linkto, FILE_IS_SYMLINK);
|
||||
|
||||
/* insert the link in the link containers */
|
||||
tommy_hashdyn_insert(&disk->linkset, &link->nodeset, link, link_name_hash(link->sub));
|
||||
|
|
@ -1253,7 +1253,7 @@ void state_read(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* allocate the link as hard link */
|
||||
link = link_alloc(sub, linkto, 1);
|
||||
link = link_alloc(sub, linkto, FILE_IS_HARDLINK);
|
||||
|
||||
/* insert the link in the link containers */
|
||||
tommy_hashdyn_insert(&disk->linkset, &link->nodeset, link, link_name_hash(link->sub));
|
||||
|
|
@ -1455,8 +1455,8 @@ void state_read(struct snapraid_state* state)
|
|||
if (state->verbose) {
|
||||
printf("\tfile %u\n", count_file);
|
||||
printf("\tblock %u\n", count_block);
|
||||
printf("\tsymlink %u\n", count_symlink);
|
||||
printf("\thardlink %u\n", count_hardlink);
|
||||
printf("\tsymlink %u\n", count_symlink);
|
||||
printf("\temptydir %u\n", count_dir);
|
||||
}
|
||||
}
|
||||
|
|
@ -1466,8 +1466,8 @@ void state_write(struct snapraid_state* state)
|
|||
STREAM* f;
|
||||
unsigned count_file;
|
||||
unsigned count_block;
|
||||
unsigned count_symlink;
|
||||
unsigned count_hardlink;
|
||||
unsigned count_symlink;
|
||||
unsigned count_dir;
|
||||
unsigned count_content;
|
||||
tommy_node* i;
|
||||
|
|
@ -1476,8 +1476,8 @@ void state_write(struct snapraid_state* state)
|
|||
|
||||
count_file = 0;
|
||||
count_block = 0;
|
||||
count_symlink = 0;
|
||||
count_hardlink = 0;
|
||||
count_symlink = 0;
|
||||
count_dir = 0;
|
||||
hash = 0;
|
||||
|
||||
|
|
@ -1649,14 +1649,17 @@ void state_write(struct snapraid_state* state)
|
|||
for(j=disk->linklist;j!=0;j=j->next) {
|
||||
struct snapraid_link* link = j->data;
|
||||
|
||||
if (link_is_hardlink(link)) {
|
||||
switch (link_flag_get(link, FILE_IS_LINK_MASK)) {
|
||||
case FILE_IS_HARDLINK :
|
||||
sputsl("hardlink ", f);
|
||||
hash = oathash8(hash, 'a');
|
||||
++count_hardlink;
|
||||
} else {
|
||||
break;
|
||||
case FILE_IS_SYMLINK :
|
||||
sputsl("symlink ", f);
|
||||
hash = oathash8(hash, 's');
|
||||
++count_symlink;
|
||||
break;
|
||||
}
|
||||
|
||||
sputs(disk->name, f);
|
||||
|
|
@ -1785,8 +1788,8 @@ void state_write(struct snapraid_state* state)
|
|||
if (state->verbose) {
|
||||
printf("\tfile %u\n", count_file);
|
||||
printf("\tblock %u\n", count_block);
|
||||
printf("\tsymlink %u\n", count_symlink);
|
||||
printf("\thardlink %u\n", count_hardlink);
|
||||
printf("\tsymlink %u\n", count_symlink);
|
||||
printf("\temptydir %u\n", count_dir);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue