Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sesman.ini FuseMountNameColonCharReplacement option #3382

Merged
merged 1 commit into from
Jan 9, 2025

Conversation

Bad-ptr
Copy link
Contributor

@Bad-ptr Bad-ptr commented Jan 6, 2025

The colon(:) in file paths is not supported on all OSes, on others need quoting/escaping, not all software treat colons in paths adequately.
The patch modifies default behaviour by stripping colon from redirected drive mount points(which emerges from windows clients with shared drive connected), but provides config option to customize the replacement(including reverting to "good old" colons in drive names).

@matt335672
Copy link
Member

Hi @Bad-ptr

I can see what you're doing, and I think it's a good idea.

A couple of initial thoughts, prior to a full review.

  1. If FuseMountNameColonCharReplacement isn't set at all, you must preserve existing behaviour. This is so users don't have to change their configs on a minor version upgrade.
  2. You don't need a char * for the config value - just a char will do. This will avoid messing about with memory allocation for this value.
  3. Changing the signature of xfuse_create_share() violates the principle of least surprise, particularly if we later on modify the calling function to do something with the name we pass in. I suggest you copy this value locally if you need to.
  4. _fuse_mount_name_colon_char_replace() doesn't consider array element 0 for replacement. There's nothing in the spec which suggests a client couldn't send a colon in this position.

@Bad-ptr
Copy link
Contributor Author

Bad-ptr commented Jan 7, 2025

If FuseMountNameColonCharReplacement isn't set at all, you must preserve existing behaviour. This is so users don't have to change their configs on a minor version upgrade.
You don't need a char * for the config value - just a char will do. This will avoid messing about with memory allocation for this value.
Changing the signature of xfuse_create_share() violates the principle of least surprise, particularly if we later on modify the calling function to do something with the name we pass in. I suggest you copy this value locally if you need to.
_fuse_mount_name_colon_char_replace() doesn't consider array element 0 for replacement. There's nothing in the spec which suggests a client couldn't send a colon in this position.

Done

Another idea is to make this option a string of pairs of chars -- the first char in pair is what to replace, the second is the replacement and the last unpaired character will be replaced by null character.

static inline char* _fuse_mount_name_colon_char_replace(const char *dirname, size_t dirnamelen)
  {
     char *newdirname = (char*)dirname;
     if (g_cfg->fuse_mount_name_colon_char_replacement && dirnamelen > 1)
      {
         char *replacepair = NULL;
          char toreplace, replaceto;
  
          newdirname = g_strdup(dirname);

          for (size_t i = dirnamelen-1; i >= 0; --i) {
             replacepair = g_cfg->fuse_mount_name_colon_char_replacement;
              while('\0' != *replacepair) {
                toreplace = replacepair[0];
                replaceto = replacepair[1];
  
                if (toreplace == newdirname[i]) {
                  newdirname[i] = replaceto;
                  break;
                }
  
                replacepair += 2;
              }
          }
      }
      return newdirname;
  }

Copy link
Member

@matt335672 matt335672 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that - looks pretty good. A few comments below. Feel free to come back to me with requests, or if you don't agree with anything I've said.

else if (g_strcasecmp(name, "FuseMountNameColonCharReplacement") == 0)
{
size_t vallen = g_strlen(value);
if (vallen < 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll possibly have seen this from the CI, and I apologise for not mentioning i earlier, but this project uses opening-brace-on-new-line, e.g.:-

    if (something)
    {
    }

See https://github.com/neutrinolabs/xrdp/wiki/Coding-Style

@@ -299,6 +316,7 @@ new_config(void)
/* Do all the allocations at the beginning, then check them together */
struct config_chansrv *cfg = g_new0(struct config_chansrv, 1);
char *fuse_mount_name = g_strdup(DEFAULT_FUSE_MOUNT_NAME);
char fuse_mount_name_colon_char_replacement = DEFAULT_FUSE_MOUNT_NAME_COLON_CHAR_REPLACEMENT;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this variable.

@@ -315,6 +333,7 @@ new_config(void)
cfg->restrict_outbound_clipboard = DEFAULT_RESTRICT_OUTBOUND_CLIPBOARD;
cfg->restrict_inbound_clipboard = DEFAULT_RESTRICT_INBOUND_CLIPBOARD;
cfg->fuse_mount_name = fuse_mount_name;
cfg->fuse_mount_name_colon_char_replacement = fuse_mount_name_colon_char_replacement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment. Just use DEFAULT_FUSE_MOUNT_NAME_COLON_CHAR_REPLACEMENT here.


/* Local utility functions */

static inline char* _fuse_mount_name_colon_char_replace(const char *dirname,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style: Function name is on new-line (e.g.):-

static inline char*
_fuse_mount_name_colon_char_replace(. . .

static inline char* _fuse_mount_name_colon_char_replace(const char *dirname,
size_t dirnamelen)
{
char *newdirname = (char*)dirname;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding style: Replace char* with char *

if (g_cfg->fuse_mount_name_colon_char_replacement != ':' && dirnamelen > 0)
{
newdirname = g_strdup(dirname);
for (size_t i = dirnamelen-1; i >= 0; --i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awkward - this loop won't terminate as size_t is always unsigned. Also, g_strdup() may return null.

You could use g_strrchr() for this, which avoids having to pass the length in. The string is going to be pretty short, and this function is called a very few times so we're not gaining anything from passing the length in.

xinode = xfs_add_entry(g_xfs, FUSE_ROOT_ID, dirname, (0777 | S_IFDIR));
char *newdirname = _fuse_mount_name_colon_char_replace(dirname, dirnamelen);
xinode = xfs_add_entry(g_xfs, FUSE_ROOT_ID, newdirname, (0777 | S_IFDIR));
if (newdirname != dirname)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice way to add the free! Suggest a comment somewhere to explain this a bit more.

@Bad-ptr
Copy link
Contributor Author

Bad-ptr commented Jan 8, 2025

Updated

@matt335672 matt335672 merged commit 99b6aaf into neutrinolabs:devel Jan 9, 2025
14 checks passed
@matt335672
Copy link
Member

Thanks for your contribution @Bad-ptr

@matt335672
Copy link
Member

@metalefty - worth a backport to v0.10?

@metalefty
Copy link
Member

@matt335672 Yes, let's backport.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants