[GRASS-dev] How to get data from a location where the user does not own any mapset?

Is it possible to access data through GRASS modules in a location
where the user does not own any mapset? Each GRASS module calls first
G_gisinit() which checks if current mapset returned by G_mapset() is
owned by current user. If it is not, it ends with fatal error. How to
get around this for locations where the user does not own any mapset?

Radim

Radim Blazek wrote:

Is it possible to access data through GRASS modules in a location
where the user does not own any mapset? Each GRASS module calls first
G_gisinit() which checks if current mapset returned by G_mapset() is
owned by current user. If it is not, it ends with fatal error. How to
get around this for locations where the user does not own any mapset?

In general, you can only access data in the current location. For most
modules, it's meaningless to access data from a different location as
the projection will be wrong. A handful of modules (e.g. r.proj,
v.proj) support accessing data from a different location, and in such
cases there's no need for the user to own the source mapset, or even
to own any mapset in the source location.

Since r54264, it is possible to bypass the ownership check by setting
GRASS_SKIP_MAPSET_OWNER_CHECK to any non-empty string. This was added
mostly for accessing VFAT/NTFS-format external drives or network
shares where the ownership checks don't behave correctly. It should
not be used on multi-user systems, nor set by programs..

But other than that, you cannot make a mapset the current mapset (i.e.
the one you can modify) unless you own it. You can access data from
any mapset for which you have the relevant filesystem permissions
(i.e. read permission for files, execute permission for the ancestor
directories, read permission for any directories which need to be
enumerated).

Originally this restriction was related to locking (the lock file was
created in the user's home directory, so being able to set the current
mapset to a directory which you didn't own meant that you could have
multiple sessions modifying a mapset concurrently).

That's no longer an issue (the lock file is created in the mapset
directory). Howver, the other issue is that allowing someone other
than the owner to modify the directory can result in problems for its
owner.

Creating a new map typically creates a subdirectory of cell_misc for
that map, and some files within it (e.g. a "null" file). Any new files
and subdirectories will be owned by their creator (not the mapset's
owner) and will have permissions determined by the current umask. The
result is that there's no guarantee that tha mapset's owner will be
able to delete (or even access) such files or directories.

In short, it's a safety mechanism against people trying to share
directories by making them group-writeable without fully understanding
the implications.

--
Glynn Clements <glynn@gclements.plus.com>

Thanks for the extensive explanation, Glynn.

On Tue, Sep 22, 2015 at 5:18 PM, Glynn Clements
<glynn@gclements.plus.com> wrote:

Radim Blazek wrote:

Is it possible to access data through GRASS modules in a location
where the user does not own any mapset? Each GRASS module calls first
G_gisinit() which checks if current mapset returned by G_mapset() is
owned by current user. If it is not, it ends with fatal error. How to
get around this for locations where the user does not own any mapset?

In general, you can only access data in the current location. For most
modules, it's meaningless to access data from a different location as
the projection will be wrong. A handful of modules (e.g. r.proj,
v.proj) support accessing data from a different location, and in such
cases there's no need for the user to own the source mapset, or even
to own any mapset in the source location.

Since r54264, it is possible to bypass the ownership check by setting
GRASS_SKIP_MAPSET_OWNER_CHECK to any non-empty string. This was added
mostly for accessing VFAT/NTFS-format external drives or network
shares where the ownership checks don't behave correctly. It should
not be used on multi-user systems, nor set by programs..

Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
not be set by programs for read only access?

But other than that, you cannot make a mapset the current mapset (i.e.
the one you can modify) unless you own it. You can access data from
any mapset for which you have the relevant filesystem permissions
(i.e. read permission for files, execute permission for the ancestor
directories, read permission for any directories which need to be
enumerated).

Originally this restriction was related to locking (the lock file was
created in the user's home directory, so being able to set the current
mapset to a directory which you didn't own meant that you coGRASS_SKIP_MAPSET_OWNER_CHECKuld have
multiple sessions modifying a mapset concurrently).

That's no longer an issue (the lock file is created in the mapset
directory). Howver, the other issue is that allowing someone other
than the owner to modify the directory can result in problems for its
owner.

Creating a new map typically creates a subdirectory of cell_misc for
that map, and some files within it (e.g. a "null" file). Any new files
and subdirectories will be owned by their creator (not the mapset's
owner) and will have permissions determined by the current umask. The
result is that there's no guarantee that tha mapset's owner will be
able to delete (or even access) such files or directories.

In short, it's a safety mechanism against people trying to share
directories by making them group-writeable without fully understanding
the implications.

I am only interested in read only access. The purpose is to be able to
read and display data in QGIS. I believe that read only access to a
location where the user does not own any mapset is a legal
requirement, isn't it?

Radim

Radim Blazek wrote:

Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
not be set by programs for read only access?

If you only need to read a mapset, you shouldn't need to make it the
current mapset, nor should you try.

Making a mapset the current mapset means that any change to e.g. the
WIND or VAR files will modify the files in that mapset. Creating
temporary files will create them in that mapset. And so on.

Also, using g.mapset to make a mapset the current mapset will try to
write the .gislock file there, and will fail if that file exists and
the creator is still alive.

Needless to say, any operation which attempts to write to the mapset
will fail if the filesystem permissions don't allow the operation. An
environment variable won't change that.

And if a session is using a mapset as its current mapset, the contents
of the WIND and VAR files in that mapset can change at any time.

> In short, it's a safety mechanism against people trying to share
> directories by making them group-writeable without fully understanding
> the implications.

I am only interested in read only access. The purpose is to be able to
read and display data in QGIS. I believe that read only access to a
location where the user does not own any mapset is a legal
requirement, isn't it?

Many GRASS library functions assume the existence of a current mapset
which can be modified. The few modules which access a location other
than the one containing the current mapset use G_create_alt_env() and
G_switch_env() to temporarily select the "other" location while
performing specific (read-only) operations, then switch back
afterwards.

This is something of a kludge, and probably somewhat error-prone, but
it's all we have.

There have been some discussions on cleaning this up, but they never
really got anywhere.

For now, even accessing data in other mapsets in the same location
relies on a certain amount of luck. Changes to the cell/fcell files
are atomic; changes to other files aren't (at least, not by design;
changes to cellhd files end up being atomic purely by virtue of the
fact that cellhd files are typically smaller than the stdio buffer).

--
Glynn Clements <glynn@gclements.plus.com>

On Sun, Sep 27, 2015 at 9:14 PM, Glynn Clements
<glynn@gclements.plus.com> wrote:

Radim Blazek wrote:

Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
not be set by programs for read only access?

If you only need to read a mapset, you shouldn't need to make it the
current mapset, nor should you try.

The mapset I need to read from does not have to be current, but one
mapset must be current and G_gisinit() checks if user is owner of
current mapset. If the user is not owner of any mapset in the
location, what can be set as current mapset?

Radim

Making a mapset the current mapset means that any change to e.g. the
WIND or VAR files will modify the files in that mapset. Creating
temporary files will create them in that mapset. And so on.

Also, using g.mapset to make a mapset the current mapset will try to
write the .gislock file there, and will fail if that file exists and
the creator is still alive.

Needless to say, any operation which attempts to write to the mapset
will fail if the filesystem permissions don't allow the operation. An
environment variable won't change that.

And if a session is using a mapset as its current mapset, the contents
of the WIND and VAR files in that mapset can change at any time.

> In short, it's a safety mechanism against people trying to share
> directories by making them group-writeable without fully understanding
> the implications.

I am only interested in read only access. The purpose is to be able to
read and display data in QGIS. I believe that read only access to a
location where the user does not own any mapset is a legal
requirement, isn't it?

Many GRASS library functions assume the existence of a current mapset
which can be modified. The few modules which access a location other
than the one containing the current mapset use G_create_alt_env() and
G_switch_env() to temporarily select the "other" location while
performing specific (read-only) operations, then switch back
afterwards.

This is something of a kludge, and probably somewhat error-prone, but
it's all we have.

There have been some discussions on cleaning this up, but they never
really got anywhere.

For now, even accessing data in other mapsets in the same location
relies on a certain amount of luck. Changes to the cell/fcell files
are atomic; changes to other files aren't (at least, not by design;
changes to cellhd files end up being atomic purely by virtue of the
fact that cellhd files are typically smaller than the stdio buffer).

--
Glynn Clements <glynn@gclements.plus.com>

On 29/09/15 21:59, Radim Blazek wrote:

On Sun, Sep 27, 2015 at 9:14 PM, Glynn Clements
<glynn@gclements.plus.com> wrote:

Radim Blazek wrote:

Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
not be set by programs for read only access?

If you only need to read a mapset, you shouldn't need to make it the
current mapset, nor should you try.

The mapset I need to read from does not have to be current, but one
mapset must be current and G_gisinit() checks if user is owner of
current mapset. If the user is not owner of any mapset in the
location, what can be set as current mapset?

Can't you just create a temporary mapset and erase it at the end ?

Moritz

On Tue, Sep 29, 2015 at 10:56 PM, Moritz Lennert
<mlennert@club.worldonline.be> wrote:

Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
not be set by programs for read only access?

If you only need to read a mapset, you shouldn't need to make it the
current mapset, nor should you try.

The mapset I need to read from does not have to be current, but one
mapset must be current and G_gisinit() checks if user is owner of
current mapset. If the user is not owner of any mapset in the
location, what can be set as current mapset?

Can't you just create a temporary mapset and erase it at the end ?

The user does not have necessarily write access for the location.

Radim

Radim Blazek wrote:

>> Perfect, that is what I need. Why GRASS_SKIP_MAPSET_OWNER_CHECK should
>> not be set by programs for read only access?
>
> If you only need to read a mapset, you shouldn't need to make it the
> current mapset, nor should you try.

The mapset I need to read from does not have to be current, but one
mapset must be current and G_gisinit() checks if user is owner of
current mapset. If the user is not owner of any mapset in the
location, what can be set as current mapset?

Use a mapset which the user does own, or create one, and use
G_switch_env() to select a different location and mapset temporarily.
Be sure to switch it back before performing any operation which may
write to the "current" mapset (modifying WIND/VAR, creating maps, or
creating temporary files).

--
Glynn Clements <glynn@gclements.plus.com>