Removes support to symlink to dirs in Windows. They are different than symlinks to files.

This commit is contained in:
Andrea Mazzoleni 2013-02-28 21:56:02 +01:00
parent 6da21cdbd9
commit 3cd7b4ee03
8 changed files with 68 additions and 48 deletions

View file

@ -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.

View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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
View file

@ -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
View file

@ -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);
}