Commit 9f6142d7 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

[PATCH] remove umsdos from tree

UMSDOS has been non-function since early 2.5 and would need a major rewrite
to be resurrected (which I don't hope anyone plans as it's a really
horrible hack)

From: Adrian Bunk <bunk@stusta.de>

With umsdos gone, there's no longer a MAINTAINERS entry required.
Signed-off-by: default avatarAdrian Bunk <bunk@stusta.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f5dbb2b7
...@@ -42,8 +42,6 @@ udf.txt ...@@ -42,8 +42,6 @@ udf.txt
- info and mount options for the UDF filesystem. - info and mount options for the UDF filesystem.
ufs.txt ufs.txt
- info on the ufs filesystem. - info on the ufs filesystem.
umsdos.txt
- info on the umsdos extensions to the msdos filesystem.
vfat.txt vfat.txt
- info on using the VFAT filesystem used in Windows NT and Windows 95 - info on using the VFAT filesystem used in Windows NT and Windows 95
vfs.txt vfs.txt
......
Firstly, let me say that UMSDOS is going through some major code changes,
and has some KNOWN BUGS (and quite a few unknown :-). Please read
fs/umsdos/README-WIP.txt for more information on current status. Thanks.
----------------------------------------------------------------------------
Very short explanation for the impatient!
Umsdos is a file system driver that run on top the MSDOS fs driver.
It is written by Jacques Gelinas (jacques@solucorp.qc.ca)
and is currently maintained by Matija Nalis (mnalis@jagor.srce.hr)
Umsdos is not a file system per se, but a twist to make a boring
one into a useful one.
It gives you:
long file names
Permissions and owners
Links
Special files (devices, pipes...)
All that is needed to be a linux root fs.
There is plenty of documentation on it in the source. A formatted document
made from those comments is available from
sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos.
You mount a DOS partition like this:
mount -t umsdos /dev/hda3 /mnt
^
---------|
All options are passed to the msdos drivers. Option like uid,gid etc are
given to msdos.
The default behavior of Umsdos is to do the same thing as the msdos driver
mostly passing commands to it without much processing. Again, this is
the default. After doing the mount on a DOS partition, nothing special
happens. This is why all mount options are passed to the msdos fs driver.
Umsdos uses a special DOS file --linux-.--- to store the information
which can't be handled by the normal MS-DOS filesystem. This is the trick.
--linux-.--- is optional. There is one per directory.
**** If --linux-.--- is missing, then Umsdos process the directory the
same way the msdos driver does. Short file names, no goodies, default
owner and permissions. So each directory may have or not this
--linux-.---
Now, how to get those --linux-.---.
\begin joke_section
Well send me a directory content
and I will send you one customised for you.
$5 per directory. Add any applicable taxes.
\end joke_section
A utility umssync creates those. The kernel maintains them. It is available
from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz.
A compiled version is available in umsdos_progs-0.7.bin.tar.gz.
So in our example, after mounting mnt, we do
umssync .
This will promote this directory (a recursive option is available) to full
umsdos capabilities (long name, etc.). However, an "ls -l" before and after
won't show much difference. The files which were there are still there, but
now you can do all this:
chmod 644 *
chown you.your_group *
ls >THIS_IS.A.VERY.LONG.NAME
ln -s toto tata
ls -l
Once a directory is promoted, all subdirectories created will inherit that
promotion.
What happens if you boot DOS and create files in those promoted directories ?
Umsdos won't notice new files, but will signal removed files (it won't crash).
Using umssync in /etc/rc will make sure the DOS directory is in sync with
the --linux-.---.
It is a good idea to put the following command in your RC file just
after the "mount -a":
mount -a
/sbin/umssync -i+ -c+ -r99 /umsdos_mount_point
(You put one for each umsdos mount point in the fstab)
This will ensure nice operation. A umsdos.fsck is in the making,
so you will be allowed to manage umsdos partitions in the same way
other filesystems are, using the generic fsck front end.
Hope this helps!
...@@ -2244,13 +2244,6 @@ L: linux_udf@hpesjro.fc.hp.com ...@@ -2244,13 +2244,6 @@ L: linux_udf@hpesjro.fc.hp.com
W: http://linux-udf.sourceforge.net W: http://linux-udf.sourceforge.net
S: Maintained S: Maintained
UMSDOS FILESYSTEM
P: Matija Nalis
M: Matija Nalis <mnalis-umsdos@voyager.hr>
L: linux-kernel@vger.kernel.org
W: http://linux.voyager.hr/umsdos/
S: Maintained
UNIFORM CDROM DRIVER UNIFORM CDROM DRIVER
P: Jens Axboe P: Jens Axboe
M: axboe@suse.de M: axboe@suse.de
......
...@@ -578,9 +578,8 @@ config FAT_FS ...@@ -578,9 +578,8 @@ config FAT_FS
tristate tristate
select NLS select NLS
help help
If you want to use one of the FAT-based file systems (the MS-DOS, If you want to use one of the FAT-based file systems (the MS-DOS and
VFAT (Windows 95) and UMSDOS (used to run Linux on top of an VFAT (Windows 95) file systems), then you must say Y or M here
ordinary DOS partition) file systems), then you must say Y or M here
to include FAT support. You will then be able to mount partitions or to include FAT support. You will then be able to mount partitions or
diskettes with FAT-based file systems and transparently access the diskettes with FAT-based file systems and transparently access the
files on them, i.e. MSDOS files will look and behave just like all files on them, i.e. MSDOS files will look and behave just like all
...@@ -612,9 +611,6 @@ config FAT_FS ...@@ -612,9 +611,6 @@ config FAT_FS
fat. Note that if you compile the FAT support as a module, you fat. Note that if you compile the FAT support as a module, you
cannot compile any of the FAT-based file systems into the kernel cannot compile any of the FAT-based file systems into the kernel
-- they will have to be modules as well. -- they will have to be modules as well.
The file system of your root partition (the one containing the
directory /) cannot be a module, so don't say M here if you intend
to use UMSDOS as your root file system.
config MSDOS_FS config MSDOS_FS
tristate "MSDOS fs support" tristate "MSDOS fs support"
...@@ -631,10 +627,6 @@ config MSDOS_FS ...@@ -631,10 +627,6 @@ config MSDOS_FS
transparent, i.e. the MSDOS files look and behave just like all transparent, i.e. the MSDOS files look and behave just like all
other Unix files. other Unix files.
If you want to use UMSDOS, the Unix-like file system on top of a
DOS file system, which allows you to run Linux from within a DOS
partition without repartitioning, you'll have to say Y or M here.
If you have Windows 95 or Windows NT installed on your MSDOS If you have Windows 95 or Windows NT installed on your MSDOS
partitions, you should use the VFAT file system (say Y to "VFAT fs partitions, you should use the VFAT file system (say Y to "VFAT fs
support" below), or you will not be able to see the long filenames support" below), or you will not be able to see the long filenames
...@@ -654,11 +646,6 @@ config VFAT_FS ...@@ -654,11 +646,6 @@ config VFAT_FS
used by Windows 95, Windows 98, Windows NT 4.0, and the Unix used by Windows 95, Windows 98, Windows NT 4.0, and the Unix
programs from the mtools package. programs from the mtools package.
You cannot use the VFAT file system for your Linux root partition
(the one containing the directory /); use UMSDOS instead if you
want to run Linux from within a DOS partition (i.e. say Y to
"Unix like fs on top of std MSDOS fs", below).
The VFAT support enlarges your kernel by about 10 KB and it only The VFAT support enlarges your kernel by about 10 KB and it only
works if you said Y to the "DOS FAT fs support" above. Please read works if you said Y to the "DOS FAT fs support" above. Please read
the file <file:Documentation/filesystems/vfat.txt> for details. If the file <file:Documentation/filesystems/vfat.txt> for details. If
...@@ -689,35 +676,6 @@ config FAT_DEFAULT_IOCHARSET ...@@ -689,35 +676,6 @@ config FAT_DEFAULT_IOCHARSET
If unsure, you shouldn't set "utf8" here. If unsure, you shouldn't set "utf8" here.
See <file:Documentation/filesystems/vfat.txt> for more information. See <file:Documentation/filesystems/vfat.txt> for more information.
config UMSDOS_FS
#dep_tristate ' UMSDOS: Unix-like file system on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
# UMSDOS is temprory broken
bool
help
Say Y here if you want to run Linux from within an existing DOS
partition of your hard drive. The advantage of this is that you can
get away without repartitioning your hard drive (which often implies
backing everything up and restoring afterwards) and hence you're
able to quickly try out Linux or show it to your friends; the
disadvantage is that Linux becomes susceptible to DOS viruses and
that UMSDOS is somewhat slower than ext2fs. Another use of UMSDOS
is to write files with long unix filenames to MSDOS floppies; it
also allows Unix-style soft-links and owner/permissions of files on
MSDOS floppies. You will need a program called umssync in order to
make use of UMSDOS; read
<file:Documentation/filesystems/umsdos.txt>.
To get utilities for initializing/checking UMSDOS file system, or
latest patches and/or information, visit the UMSDOS home page at
<http://www.voyager.hr/~mnalis/umsdos/>.
This option enlarges your kernel by about 28 KB and it only works if
you said Y to both "DOS FAT fs support" and "MSDOS fs support"
above. To compile this as a module, choose M here: the module will be
called umsdos. Note that the file system of your root partition
(the one containing the directory /) cannot be a module, so saying M
could be dangerous. If unsure, say N.
config NTFS_FS config NTFS_FS
tristate "NTFS file system support" tristate "NTFS file system support"
select NLS select NLS
......
...@@ -57,7 +57,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ ...@@ -57,7 +57,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
obj-$(CONFIG_CODA_FS) += coda/ obj-$(CONFIG_CODA_FS) += coda/
obj-$(CONFIG_MINIX_FS) += minix/ obj-$(CONFIG_MINIX_FS) += minix/
obj-$(CONFIG_FAT_FS) += fat/ obj-$(CONFIG_FAT_FS) += fat/
obj-$(CONFIG_UMSDOS_FS) += umsdos/
obj-$(CONFIG_MSDOS_FS) += msdos/ obj-$(CONFIG_MSDOS_FS) += msdos/
obj-$(CONFIG_VFAT_FS) += vfat/ obj-$(CONFIG_VFAT_FS) += vfat/
obj-$(CONFIG_BFS_FS) += bfs/ obj-$(CONFIG_BFS_FS) += bfs/
......
#
# Makefile for the umsdos Unix-like filesystem routines.
#
obj-$(CONFIG_UMSDOS) += umsdos.o
umsdos-objs := dir.o inode.o ioctl.o mangle.o namei.o rdir.o emd.o
p:
proto *.c >/usr/include/linux/umsdos_fs.p
doc:
nadoc -i -p umsdos.doc - /tmp/umsdos.mpg
Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing
(started by Peter T. Waltenberg <peterw@karaka.chch.cri.nz>)
(Final conversion to dentries Bill Hawes <whawes@star.net>)
There is no warning any more.
Both read-only and read-write stuff is fixed, both in
msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
will compile and work on 2.2.x+ kernels and glibc based systems, as well as
kernel patches and other umsdos related information may be found at
http://linux.voyager.hr/umsdos/
Information below is getting outdated slowly -- I'll fix it one day when I
get enough time - there are more important things to fix right now.
Legend: those lines marked with '+' on the beggining of line indicates it
passed all of my tests, and performed perfect in all of them.
Current status (010125) - UMSDOS 0.86j:
(1) pure MSDOS (no --linux-.--- EMD file):
READ:
+ readdir - works
+ lookup - works
+ read file - works
WRITE:
+ creat file - works
+ unlink file - works
+ write file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
+ rename dir (same dir) - works
+ rename dir (dif. dir) - works
+ mkdir - works
+ rmdir - works
(2) umsdos (with --linux-.--- EMD file):
READ:
+ readdir - works
+ lookup - works
+ permissions/owners stuff - works
+ long file names - works
+ read file - works
+ switching MSDOS/UMSDOS - works
+ switching UMSDOS/MSDOS - works
- pseudo root things - works mostly. See notes below.
+ resolve symlink - works
+ dereference symlink - works
+ dangling symlink - works
+ hard links - works
+ special files (block/char devices, FIFOs, sockets...) - works
+ various umsdos ioctls - works
WRITE:
+ create symlink - works
+ create hardlink - works
+ create file - works
+ create special file - works
+ write to file - works
+ rename file (same dir) - works
+ rename file (dif. dir) - works
+ rename hardlink (same dir) - works
- rename hardlink (dif. dir) - works, but see notes below.
+ rename symlink (same dir) - works
+ rename symlink (dif. dir) - works
+ rename dir (same dir) - works
+ rename dir (dif. dir) - works
+ unlink file - works
+ notify_change (chown,perms) - works
+ notify_change for hardlinks - works
+ unlink hardlink - works
+ mkdir - works
+ rmdir - works
+ umssyncing (many ioctls) - works
- CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank
Gockel <gockel@sent13.uni-duisburg.de> to use it even under umsdosfs, but I
have no way of testing it -- please let me know if there are problems specific
to umsdos (for instance, it works under msdosfs, but not under umsdosfs).
Some current notes:
Note: creating and using pseudo-hardlinks is always non-perfect, especially
in filesystems that might be externally modified like umsdos. There is
example is specs file about it. Specifically, moving directory which
contains hardlinks will break them.
Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
See http://linux.voyager.hr/umsdos/hlbug.html for more info and upgrade
procedure if you used broken versions...
------------------------------------------------------------------------------
Some general notes:
Good idea when running development kernels is to have SysRq support compiled
in kernel, and use Sync/Emergency-remount-RO if you bump into problems (like
not being able to umount(2) umsdosfs, and because of it root partition also,
or panics which force you to reboot etc.)
I'm unfortunately somewhat out of time to read linux-kernel@vger, but I do
check for messages having "UMSDOS" in the subject, and read them. I might
miss some in all that volume, though. I should reply to any direct e-mail
in few days. If I don't, probably I never got your message.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* linux/fs/umsdos/rdir.c
*
* Written 1994 by Jacques Gelinas
*
* Extended MS-DOS directory pure MS-DOS handling functions
* (For directory without EMD file).
*/
#include <linux/time.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/limits.h>
#include <linux/umsdos_fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>
extern struct dentry *saved_root;
extern struct inode *pseudo_root;
extern struct dentry_operations umsdos_dentry_operations;
struct RDIR_FILLDIR {
void *dirbuf;
filldir_t filldir;
int real_root;
};
static int rdir_filldir ( void *buf,
const char *name,
int name_len,
loff_t offset,
ino_t ino,
unsigned int d_type)
{
int ret = 0;
struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf;
if (d->real_root) {
PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
/* real root of a pseudo_rooted partition */
if (name_len != UMSDOS_PSDROOT_LEN
|| memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) {
/* So it is not the /linux directory */
if (name_len == 2 && name[0] == '.' && name[1] == '.') {
/* Make sure the .. entry points back to the pseudo_root */
ino = pseudo_root->i_ino;
}
ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
}
} else {
/* Any DOS directory */
ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
}
return ret;
}
static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir)
{
struct inode *dir = filp->f_dentry->d_inode;
struct RDIR_FILLDIR bufk;
int ret;
lock_kernel();
bufk.filldir = filldir;
bufk.dirbuf = dirbuf;
bufk.real_root = pseudo_root && (dir == saved_root->d_inode);
ret = fat_readdir (filp, &bufk, rdir_filldir);
unlock_kernel();
return ret;
}
/*
* Lookup into a non promoted directory.
* If the result is a directory, make sure we find out if it is
* a promoted one or not (calling umsdos_setup_dir_inode(inode)).
*/
/* #Specification: pseudo root / DOS/..
* In the real root directory (c:\), the directory ..
* is the pseudo root (c:\linux).
*/
struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo)
{
struct dentry *ret;
if (saved_root && dir == saved_root->d_inode && !nopseudo &&
dentry->d_name.len == UMSDOS_PSDROOT_LEN &&
memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) {
/* #Specification: pseudo root / DOS/linux
* Even in the real root directory (c:\), the directory
* /linux won't show
*/
ret = ERR_PTR(-ENOENT);
goto out;
}
ret = msdos_lookup (dir, dentry, NULL);
if (ret) {
printk(KERN_WARNING
"umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
PTR_ERR(ret));
goto out;
}
if (dentry->d_inode) {
/* We must install the proper function table
* depending on whether this is an MS-DOS or
* a UMSDOS directory
*/
Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name));
/* only patch if needed (because we get called even for lookup
(not only rlookup) stuff sometimes, like in umsdos_covered() */
if (UMSDOS_I(dentry->d_inode)->i_patched == 0)
umsdos_patch_dentry_inode(dentry, 0);
}
out:
/* always install our dentry ops ... */
dentry->d_op = &umsdos_dentry_operations;
return ret;
}
struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
return umsdos_rlookup_x (dir, dentry, 0);
}
/* #Specification: dual mode / rmdir in a DOS directory
* In a DOS (not EMD in it) directory, we use a reverse strategy
* compared with a UMSDOS directory. We assume that a subdirectory
* of a DOS directory is also a DOS directory. This is not always
* true (umssync may be used anywhere), but makes sense.
*
* So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
* then we check if it is a Umsdos directory. We check if it is
* really empty (only . .. and --linux-.--- in it). If it is true
* we remove the EMD and do a msdos_rmdir() again.
*
* In a Umsdos directory, we assume all subdirectories are also
* Umsdos directories, so we check the EMD file first.
*/
/* #Specification: pseudo root / rmdir /DOS
* The pseudo sub-directory /DOS can't be removed!
* This is done even if the pseudo root is not a Umsdos
* directory anymore (very unlikely), but an accident (under
* MS-DOS) is always possible.
*
* EPERM is returned.
*/
static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
{
int ret, empty;
ret = -EPERM;
if (umsdos_is_pseudodos (dir, dentry))
goto out;
ret = -EBUSY;
if (!d_unhashed(dentry))
goto out;
ret = msdos_rmdir (dir, dentry);
if (ret != -ENOTEMPTY)
goto out;
empty = umsdos_isempty (dentry);
if (empty == 1) {
struct dentry *demd;
/* We have to remove the EMD file. */
demd = umsdos_get_emd_dentry(dentry);
ret = PTR_ERR(demd);
if (!IS_ERR(demd)) {
ret = 0;
if (demd->d_inode)
ret = msdos_unlink (dentry->d_inode, demd);
if (!ret)
d_delete(demd);
dput(demd);
}
}
if (ret)
goto out;
/* now retry the original ... */
ret = msdos_rmdir (dir, dentry);
out:
return ret;
}
/* #Specification: dual mode / introduction
* One goal of UMSDOS is to allow a practical and simple coexistence
* between MS-DOS and Linux in a single partition. Using the EMD file
* in each directory, UMSDOS adds Unix semantics and capabilities to
* a normal DOS filesystem. To help and simplify coexistence, here is
* the logic related to the EMD file.
*
* If it is missing, then the directory is managed by the MS-DOS driver.
* The names are limited to DOS limits (8.3). No links, no device special
* and pipe and so on.
*
* If it is there, it is the directory. If it is there but empty, then
* the directory looks empty. The utility umssync allows synchronisation
* of the real DOS directory and the EMD.
*
* Whenever umssync is applied to a directory without EMD, one is
* created on the fly. The directory is promoted to full Unix semantics.
* Of course, the ls command will show exactly the same content as before
* the umssync session.
*
* It is believed that the user/admin will promote directories to Unix
* semantics as needed.
*
* The strategy to implement this is to use two function table (struct
* inode_operations). One for true UMSDOS directory and one for directory
* with missing EMD.
*
* Functions related to the DOS semantic (but aware of UMSDOS) generally
* have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
* from the one with full UMSDOS semantics.
*/
struct file_operations umsdos_rdir_operations =
{
.read = generic_read_dir,
.readdir = UMSDOS_rreaddir,
.ioctl = UMSDOS_ioctl_dir,
};
struct inode_operations umsdos_rdir_inode_operations =
{
.create = msdos_create,
.lookup = UMSDOS_rlookup,
.unlink = msdos_unlink,
.mkdir = msdos_mkdir,
.rmdir = UMSDOS_rrmdir,
.rename = msdos_rename,
.setattr = UMSDOS_notify_change,
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef UMSDOS_FS_I_H
#define UMSDOS_FS_I_H
#ifndef _LINUX_TYPES_H
#include <linux/types.h>
#endif
#include <linux/msdos_fs_i.h>
#include <linux/pipe_fs_i.h>
/* #Specification: strategy / in memory inode
* Here is the information specific to the inode of the UMSDOS file
* system. This information is added to the end of the standard struct
* inode. Each file system has its own extension to struct inode,
* so do the umsdos file system.
*
* The strategy is to have the umsdos_inode_info as a superset of
* the msdos_inode_info, since most of the time the job is done
* by the msdos fs code.
*
* So we duplicate the msdos_inode_info, and add our own info at the
* end.
*
* The offset in this EMD file of the entry: pos
*
* For directory, we have dir_locking_info to help synchronise
* file creation and file lookup. See also msdos_fs_i.h for more
* information about msdos_inode_info.
*
* Special file and fifo do have an inode which correspond to an
* empty MSDOS file.
*
* symlink are processed mostly like regular file. The content is the
* link.
*
* The UMSDOS specific extension is placed after the union.
*/
struct dir_locking_info {
wait_queue_head_t p;
short int looking; /* How many process doing a lookup */
short int creating; /* Is there any creation going on here
* Only one at a time, although one
* may recursively lock, so it is a counter
*/
long pid; /* pid of the process owning the creation
* lock */
};
struct umsdos_inode_info {
struct msdos_inode_info msdos_info;
struct dir_locking_info dir_info;
int i_patched; /* Inode has been patched */
int i_is_hlink; /* Resolved hardlink inode? */
off_t pos; /* Entry offset in the emd_owner file */
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment