Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
986c2f13
Commit
986c2f13
authored
Sep 23, 2008
by
Eric Wong
Committed by
Max Kellermann
Sep 23, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
directory: use enum update_return for return values
This way we avoid having to document -1, 0, 1
parent
cfc2dd3e
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
49 additions
and
72 deletions
+49
-72
directory.c
src/directory.c
+49
-72
No files found.
src/directory.c
View file @
986c2f13
...
@@ -47,9 +47,11 @@
...
@@ -47,9 +47,11 @@
#define DIRECTORY_UPDATE_EXIT_UPDATE 1
#define DIRECTORY_UPDATE_EXIT_UPDATE 1
#define DIRECTORY_UPDATE_EXIT_ERROR 2
#define DIRECTORY_UPDATE_EXIT_ERROR 2
#define DIRECTORY_RETURN_NOUPDATE 0
enum
update_return
{
#define DIRECTORY_RETURN_UPDATE 1
UPDATE_RETURN_ERROR
=
-
1
,
#define DIRECTORY_RETURN_ERROR -1
UPDATE_RETURN_NOUPDATE
=
0
,
UPDATE_RETURN_UPDATED
=
1
};
static
Directory
*
mp3rootDirectory
;
static
Directory
*
mp3rootDirectory
;
...
@@ -72,16 +74,16 @@ static void freeDirectoryList(DirectoryList * list);
...
@@ -72,16 +74,16 @@ static void freeDirectoryList(DirectoryList * list);
static
void
freeDirectory
(
Directory
*
directory
);
static
void
freeDirectory
(
Directory
*
directory
);
static
int
exploreDirectory
(
Directory
*
directory
);
static
enum
update_return
exploreDirectory
(
Directory
*
directory
);
static
int
updateDirectory
(
Directory
*
directory
);
static
enum
update_return
updateDirectory
(
Directory
*
directory
);
static
void
deleteEmptyDirectoriesInDirectory
(
Directory
*
directory
);
static
void
deleteEmptyDirectoriesInDirectory
(
Directory
*
directory
);
static
void
removeSongFromDirectory
(
Directory
*
directory
,
static
void
removeSongFromDirectory
(
Directory
*
directory
,
const
char
*
shortname
);
const
char
*
shortname
);
static
int
addSubDirectoryToDirectory
(
Directory
*
directory
,
static
enum
update_return
addSubDirectoryToDirectory
(
Directory
*
directory
,
const
char
*
shortname
,
const
char
*
shortname
,
const
char
*
name
,
struct
stat
*
st
);
const
char
*
name
,
struct
stat
*
st
);
...
@@ -93,7 +95,7 @@ static Directory *getDirectory(const char *name);
...
@@ -93,7 +95,7 @@ static Directory *getDirectory(const char *name);
static
Song
*
getSongDetails
(
const
char
*
file
,
const
char
**
shortnameRet
,
static
Song
*
getSongDetails
(
const
char
*
file
,
const
char
**
shortnameRet
,
Directory
**
directoryRet
);
Directory
**
directoryRet
);
static
int
updatePath
(
const
char
*
utf8path
);
static
enum
update_return
updatePath
(
const
char
*
utf8path
);
static
void
sortDirectory
(
Directory
*
directory
);
static
void
sortDirectory
(
Directory
*
directory
);
...
@@ -172,7 +174,7 @@ int updateInit(List * pathList)
...
@@ -172,7 +174,7 @@ int updateInit(List * pathList)
directory_updatePid
=
fork
();
directory_updatePid
=
fork
();
if
(
directory_updatePid
==
0
)
{
if
(
directory_updatePid
==
0
)
{
/* child */
/* child */
int
dbUpdated
=
0
;
enum
update_return
dbUpdated
=
UPDATE_RETURN_NOUPDATE
;
unblockSignals
();
unblockSignals
();
...
@@ -195,7 +197,7 @@ int updateInit(List * pathList)
...
@@ -195,7 +197,7 @@ int updateInit(List * pathList)
while
(
node
)
{
while
(
node
)
{
switch
(
updatePath
(
node
->
key
))
{
switch
(
updatePath
(
node
->
key
))
{
case
1
:
case
1
:
dbUpdated
=
1
;
dbUpdated
=
UPDATE_RETURN_UPDATED
;
break
;
break
;
case
0
:
case
0
:
break
;
break
;
...
@@ -205,12 +207,11 @@ int updateInit(List * pathList)
...
@@ -205,12 +207,11 @@ int updateInit(List * pathList)
node
=
node
->
nextNode
;
node
=
node
->
nextNode
;
}
}
}
else
{
}
else
{
if
((
dbUpdated
=
updateDirectory
(
mp3rootDirectory
))
<
0
)
{
if
((
dbUpdated
=
updateDirectory
(
mp3rootDirectory
))
<
0
)
exit
(
DIRECTORY_UPDATE_EXIT_ERROR
);
exit
(
DIRECTORY_UPDATE_EXIT_ERROR
);
}
}
}
if
(
!
dbUpdated
)
if
(
dbUpdated
==
UPDATE_RETURN_NOUPDATE
)
exit
(
DIRECTORY_UPDATE_EXIT_NOUPDATE
);
exit
(
DIRECTORY_UPDATE_EXIT_NOUPDATE
);
/* ignore signals since we don't want them to corrupt the db */
/* ignore signals since we don't want them to corrupt the db */
...
@@ -314,12 +315,7 @@ static void deleteEmptyDirectoriesInDirectory(Directory * directory)
...
@@ -314,12 +315,7 @@ static void deleteEmptyDirectoriesInDirectory(Directory * directory)
}
}
}
}
/* return values:
static
enum
update_return
updateInDirectory
(
Directory
*
directory
,
-1 -> error
0 -> no error, but nothing updated
1 -> no error, and stuff updated
*/
static
int
updateInDirectory
(
Directory
*
directory
,
const
char
*
shortname
,
const
char
*
name
)
const
char
*
shortname
,
const
char
*
name
)
{
{
Song
*
song
;
Song
*
song
;
...
@@ -327,17 +323,17 @@ static int updateInDirectory(Directory * directory,
...
@@ -327,17 +323,17 @@ static int updateInDirectory(Directory * directory,
struct
stat
st
;
struct
stat
st
;
if
(
myStat
(
name
,
&
st
))
if
(
myStat
(
name
,
&
st
))
return
-
1
;
return
UPDATE_RETURN_ERROR
;
if
(
S_ISREG
(
st
.
st_mode
)
&&
hasMusicSuffix
(
name
,
0
))
{
if
(
S_ISREG
(
st
.
st_mode
)
&&
hasMusicSuffix
(
name
,
0
))
{
if
(
!
(
song
=
songvec_find
(
&
directory
->
songs
,
shortname
)))
{
if
(
!
(
song
=
songvec_find
(
&
directory
->
songs
,
shortname
)))
{
addToDirectory
(
directory
,
shortname
,
name
);
addToDirectory
(
directory
,
shortname
,
name
);
return
DIRECTORY_RETURN_UPDATE
;
return
UPDATE_RETURN_UPDATED
;
}
else
if
(
st
.
st_mtime
!=
song
->
mtime
)
{
}
else
if
(
st
.
st_mtime
!=
song
->
mtime
)
{
LOG
(
"updating %s
\n
"
,
name
);
LOG
(
"updating %s
\n
"
,
name
);
if
(
updateSongInfo
(
song
)
<
0
)
if
(
updateSongInfo
(
song
)
<
0
)
removeSongFromDirectory
(
directory
,
shortname
);
removeSongFromDirectory
(
directory
,
shortname
);
return
1
;
return
UPDATE_RETURN_UPDATED
;
}
}
}
else
if
(
S_ISDIR
(
st
.
st_mode
))
{
}
else
if
(
S_ISDIR
(
st
.
st_mode
))
{
if
(
findInList
if
(
findInList
...
@@ -350,7 +346,7 @@ static int updateInDirectory(Directory * directory,
...
@@ -350,7 +346,7 @@ static int updateInDirectory(Directory * directory,
}
}
}
}
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
}
}
/* we don't look at hidden files nor files with newlines in them */
/* we don't look at hidden files nor files with newlines in them */
...
@@ -359,18 +355,14 @@ static int skip_path(const char *path)
...
@@ -359,18 +355,14 @@ static int skip_path(const char *path)
return
(
path
[
0
]
==
'.'
||
strchr
(
path
,
'\n'
))
?
1
:
0
;
return
(
path
[
0
]
==
'.'
||
strchr
(
path
,
'\n'
))
?
1
:
0
;
}
}
/* return values:
static
enum
update_return
-1 -> error
removeDeletedFromDirectory
(
char
*
path_max_tmp
,
Directory
*
directory
)
0 -> no error, but nothing removed
1 -> no error, and stuff removed
*/
static
int
removeDeletedFromDirectory
(
char
*
path_max_tmp
,
Directory
*
directory
)
{
{
const
char
*
dirname
=
(
directory
&&
directory
->
path
)
?
const
char
*
dirname
=
(
directory
&&
directory
->
path
)
?
directory
->
path
:
NULL
;
directory
->
path
:
NULL
;
ListNode
*
node
,
*
tmpNode
;
ListNode
*
node
,
*
tmpNode
;
DirectoryList
*
subdirs
=
directory
->
subDirectories
;
DirectoryList
*
subdirs
=
directory
->
subDirectories
;
int
ret
=
0
;
enum
update_return
ret
=
UPDATE_RETURN_NOUPDATE
;
int
i
;
int
i
;
struct
songvec
*
sv
=
&
directory
->
songs
;
struct
songvec
*
sv
=
&
directory
->
songs
;
...
@@ -387,7 +379,7 @@ static int removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
...
@@ -387,7 +379,7 @@ static int removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
if
(
!
isDir
(
path_max_tmp
))
{
if
(
!
isDir
(
path_max_tmp
))
{
LOG
(
"removing directory: %s
\n
"
,
path_max_tmp
);
LOG
(
"removing directory: %s
\n
"
,
path_max_tmp
);
deleteFromList
(
subdirs
,
node
->
key
);
deleteFromList
(
subdirs
,
node
->
key
);
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
}
}
}
}
node
=
tmpNode
;
node
=
tmpNode
;
...
@@ -405,7 +397,7 @@ static int removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
...
@@ -405,7 +397,7 @@ static int removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
if
(
!
isFile
(
path_max_tmp
,
NULL
))
{
if
(
!
isFile
(
path_max_tmp
,
NULL
))
{
removeSongFromDirectory
(
directory
,
song
->
url
);
removeSongFromDirectory
(
directory
,
song
->
url
);
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
}
}
}
}
...
@@ -477,12 +469,7 @@ static Directory *addParentPathToDB(const char *utf8path, const char **shortname
...
@@ -477,12 +469,7 @@ static Directory *addParentPathToDB(const char *utf8path, const char **shortname
return
(
Directory
*
)
parentDirectory
;
return
(
Directory
*
)
parentDirectory
;
}
}
/* return values:
static
enum
update_return
updatePath
(
const
char
*
utf8path
)
-1 -> error
0 -> no error, but nothing updated
1 -> no error, and stuff updated
*/
static
int
updatePath
(
const
char
*
utf8path
)
{
{
Directory
*
directory
;
Directory
*
directory
;
Directory
*
parentDirectory
;
Directory
*
parentDirectory
;
...
@@ -490,11 +477,11 @@ static int updatePath(const char *utf8path)
...
@@ -490,11 +477,11 @@ static int updatePath(const char *utf8path)
const
char
*
shortname
;
const
char
*
shortname
;
char
*
path
=
sanitizePathDup
(
utf8path
);
char
*
path
=
sanitizePathDup
(
utf8path
);
time_t
mtime
;
time_t
mtime
;
int
ret
=
0
;
enum
update_return
ret
=
UPDATE_RETURN_NOUPDATE
;
char
path_max_tmp
[
MPD_PATH_MAX
];
char
path_max_tmp
[
MPD_PATH_MAX
];
if
(
NULL
==
path
)
if
(
NULL
==
path
)
return
-
1
;
return
UPDATE_RETURN_ERROR
;
/* if path is in the DB try to update it, or else delete it */
/* if path is in the DB try to update it, or else delete it */
if
((
directory
=
getDirectoryDetails
(
path
,
&
shortname
)))
{
if
((
directory
=
getDirectoryDetails
(
path
,
&
shortname
)))
{
...
@@ -509,21 +496,21 @@ static int updatePath(const char *utf8path)
...
@@ -509,21 +496,21 @@ static int updatePath(const char *utf8path)
/* we don't want to delete the root directory */
/* we don't want to delete the root directory */
else
if
(
directory
==
mp3rootDirectory
)
{
else
if
(
directory
==
mp3rootDirectory
)
{
free
(
path
);
free
(
path
);
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
}
}
/* if updateDirectory fails, means we should delete it */
/* if updateDirectory fails, means we should delete it */
else
{
else
{
LOG
(
"removing directory: %s
\n
"
,
path
);
LOG
(
"removing directory: %s
\n
"
,
path
);
deleteFromList
(
parentDirectory
->
subDirectories
,
deleteFromList
(
parentDirectory
->
subDirectories
,
shortname
);
shortname
);
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
/* don't return, path maybe a song now */
/* don't return, path maybe a song now */
}
}
}
else
if
((
song
=
getSongDetails
(
path
,
&
shortname
,
&
parentDirectory
)))
{
}
else
if
((
song
=
getSongDetails
(
path
,
&
shortname
,
&
parentDirectory
)))
{
if
(
!
parentDirectory
->
stat
if
(
!
parentDirectory
->
stat
&&
statDirectory
(
parentDirectory
)
<
0
)
{
&&
statDirectory
(
parentDirectory
)
<
0
)
{
free
(
path
);
free
(
path
);
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
}
}
/* if this song update is successfull, we are done */
/* if this song update is successfull, we are done */
else
if
(
0
==
inodeFoundInParent
(
parentDirectory
->
parent
,
else
if
(
0
==
inodeFoundInParent
(
parentDirectory
->
parent
,
...
@@ -533,19 +520,19 @@ static int updatePath(const char *utf8path)
...
@@ -533,19 +520,19 @@ static int updatePath(const char *utf8path)
isMusic
(
get_song_url
(
path_max_tmp
,
song
),
&
mtime
,
0
))
{
isMusic
(
get_song_url
(
path_max_tmp
,
song
),
&
mtime
,
0
))
{
free
(
path
);
free
(
path
);
if
(
song
->
mtime
==
mtime
)
if
(
song
->
mtime
==
mtime
)
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
else
if
(
updateSongInfo
(
song
)
==
0
)
else
if
(
updateSongInfo
(
song
)
==
0
)
return
1
;
return
UPDATE_RETURN_UPDATED
;
else
{
else
{
removeSongFromDirectory
(
parentDirectory
,
removeSongFromDirectory
(
parentDirectory
,
shortname
);
shortname
);
return
1
;
return
UPDATE_RETURN_UPDATED
;
}
}
}
}
/* if updateDirectory fails, means we should delete it */
/* if updateDirectory fails, means we should delete it */
else
{
else
{
removeSongFromDirectory
(
parentDirectory
,
shortname
);
removeSongFromDirectory
(
parentDirectory
,
shortname
);
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
/* don't return, path maybe a directory now */
/* don't return, path maybe a directory now */
}
}
}
}
...
@@ -563,7 +550,7 @@ static int updatePath(const char *utf8path)
...
@@ -563,7 +550,7 @@ static int updatePath(const char *utf8path)
parentDirectory
->
device
)
parentDirectory
->
device
)
&&
addToDirectory
(
parentDirectory
,
shortname
,
path
)
&&
addToDirectory
(
parentDirectory
,
shortname
,
path
)
>
0
)
{
>
0
)
{
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
}
}
}
}
...
@@ -580,32 +567,27 @@ static const char *opendir_path(char *path_max_tmp, const char *dirname)
...
@@ -580,32 +567,27 @@ static const char *opendir_path(char *path_max_tmp, const char *dirname)
return
musicDir
;
return
musicDir
;
}
}
/* return values:
static
enum
update_return
updateDirectory
(
Directory
*
directory
)
-1 -> error
0 -> no error, but nothing updated
1 -> no error, and stuff updated
*/
static
int
updateDirectory
(
Directory
*
directory
)
{
{
DIR
*
dir
;
DIR
*
dir
;
const
char
*
dirname
=
getDirectoryPath
(
directory
);
const
char
*
dirname
=
getDirectoryPath
(
directory
);
struct
dirent
*
ent
;
struct
dirent
*
ent
;
char
path_max_tmp
[
MPD_PATH_MAX
];
char
path_max_tmp
[
MPD_PATH_MAX
];
int
ret
=
0
;
enum
update_return
ret
=
UPDATE_RETURN_NOUPDATE
;
if
(
!
directory
->
stat
&&
statDirectory
(
directory
)
<
0
)
if
(
!
directory
->
stat
&&
statDirectory
(
directory
)
<
0
)
return
-
1
;
return
UPDATE_RETURN_ERROR
;
else
if
(
inodeFoundInParent
(
directory
->
parent
,
else
if
(
inodeFoundInParent
(
directory
->
parent
,
directory
->
inode
,
directory
->
inode
,
directory
->
device
))
directory
->
device
))
return
-
1
;
return
UPDATE_RETURN_ERROR
;
dir
=
opendir
(
opendir_path
(
path_max_tmp
,
dirname
));
dir
=
opendir
(
opendir_path
(
path_max_tmp
,
dirname
));
if
(
!
dir
)
if
(
!
dir
)
return
-
1
;
return
UPDATE_RETURN_ERROR
;
if
(
removeDeletedFromDirectory
(
path_max_tmp
,
directory
)
>
0
)
if
(
removeDeletedFromDirectory
(
path_max_tmp
,
directory
)
>
0
)
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
while
((
ent
=
readdir
(
dir
)))
{
while
((
ent
=
readdir
(
dir
)))
{
char
*
utf8
;
char
*
utf8
;
...
@@ -620,7 +602,7 @@ static int updateDirectory(Directory * directory)
...
@@ -620,7 +602,7 @@ static int updateDirectory(Directory * directory)
utf8
=
pfx_dir
(
path_max_tmp
,
utf8
,
strlen
(
utf8
),
utf8
=
pfx_dir
(
path_max_tmp
,
utf8
,
strlen
(
utf8
),
dirname
,
strlen
(
dirname
));
dirname
,
strlen
(
dirname
));
if
(
updateInDirectory
(
directory
,
utf8
,
path_max_tmp
)
>
0
)
if
(
updateInDirectory
(
directory
,
utf8
,
path_max_tmp
)
>
0
)
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
}
}
closedir
(
dir
);
closedir
(
dir
);
...
@@ -628,24 +610,19 @@ static int updateDirectory(Directory * directory)
...
@@ -628,24 +610,19 @@ static int updateDirectory(Directory * directory)
return
ret
;
return
ret
;
}
}
/* return values:
static
enum
update_return
exploreDirectory
(
Directory
*
directory
)
-1 -> error
0 -> no error, but nothing found
1 -> no error, and stuff found
*/
static
int
exploreDirectory
(
Directory
*
directory
)
{
{
DIR
*
dir
;
DIR
*
dir
;
const
char
*
dirname
=
getDirectoryPath
(
directory
);
const
char
*
dirname
=
getDirectoryPath
(
directory
);
struct
dirent
*
ent
;
struct
dirent
*
ent
;
char
path_max_tmp
[
MPD_PATH_MAX
];
char
path_max_tmp
[
MPD_PATH_MAX
];
int
ret
=
0
;
enum
update_return
ret
=
UPDATE_RETURN_NOUPDATE
;
DEBUG
(
"explore: attempting to opendir: %s
\n
"
,
dirname
);
DEBUG
(
"explore: attempting to opendir: %s
\n
"
,
dirname
);
dir
=
opendir
(
opendir_path
(
path_max_tmp
,
dirname
));
dir
=
opendir
(
opendir_path
(
path_max_tmp
,
dirname
));
if
(
!
dir
)
if
(
!
dir
)
return
-
1
;
return
UPDATE_RETURN_ERROR
;
DEBUG
(
"explore: %s
\n
"
,
dirname
);
DEBUG
(
"explore: %s
\n
"
,
dirname
);
...
@@ -664,7 +641,7 @@ static int exploreDirectory(Directory * directory)
...
@@ -664,7 +641,7 @@ static int exploreDirectory(Directory * directory)
utf8
=
pfx_dir
(
path_max_tmp
,
utf8
,
strlen
(
utf8
),
utf8
=
pfx_dir
(
path_max_tmp
,
utf8
,
strlen
(
utf8
),
dirname
,
strlen
(
dirname
));
dirname
,
strlen
(
dirname
));
if
(
addToDirectory
(
directory
,
utf8
,
path_max_tmp
)
>
0
)
if
(
addToDirectory
(
directory
,
utf8
,
path_max_tmp
)
>
0
)
ret
=
1
;
ret
=
UPDATE_RETURN_UPDATED
;
}
}
closedir
(
dir
);
closedir
(
dir
);
...
@@ -699,26 +676,26 @@ static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device)
...
@@ -699,26 +676,26 @@ static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device)
return
0
;
return
0
;
}
}
static
int
addSubDirectoryToDirectory
(
Directory
*
directory
,
static
enum
update_return
addSubDirectoryToDirectory
(
Directory
*
directory
,
const
char
*
shortname
,
const
char
*
shortname
,
const
char
*
name
,
struct
stat
*
st
)
const
char
*
name
,
struct
stat
*
st
)
{
{
Directory
*
subDirectory
;
Directory
*
subDirectory
;
if
(
inodeFoundInParent
(
directory
,
st
->
st_ino
,
st
->
st_dev
))
if
(
inodeFoundInParent
(
directory
,
st
->
st_ino
,
st
->
st_dev
))
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
subDirectory
=
newDirectory
(
name
,
directory
);
subDirectory
=
newDirectory
(
name
,
directory
);
directory_set_stat
(
subDirectory
,
st
);
directory_set_stat
(
subDirectory
,
st
);
if
(
exploreDirectory
(
subDirectory
)
<
1
)
{
if
(
exploreDirectory
(
subDirectory
)
<
1
)
{
freeDirectory
(
subDirectory
);
freeDirectory
(
subDirectory
);
return
0
;
return
UPDATE_RETURN_NOUPDATE
;
}
}
insertInList
(
directory
->
subDirectories
,
shortname
,
subDirectory
);
insertInList
(
directory
->
subDirectories
,
shortname
,
subDirectory
);
return
1
;
return
UPDATE_RETURN_UPDATED
;
}
}
static
int
addToDirectory
(
Directory
*
directory
,
static
int
addToDirectory
(
Directory
*
directory
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment