fadwa dhifi
fadwa dhifi

Reputation: 47

Write in the end of a file on ubuntu server using ssh.net

I want to add some lines to \etc\ssh\sshd_config using ssh.net, I have tried this method SFTPCLient.WriteAllLines(string path, string[] content) but it adds the content at the beginning of the file after deleting the same number of lines. In the documentation I've found this It is not first truncated to zero bytes. what does it mean? I've tried also this method public abstract void Write(byte[] buffer, int offset, int count); with another file, because I didn't want to risque deleting other lines, BUT it doesn't work, can anyone explain the values that the offset and the count must take?

string[] config = {"Match user Fadwa", "ChrootDirectory /fadwa/dhifi/test",
    "ForceCommand internal-sftp -d /fadwa"};

byte[] bconfig = config.SelectMany(s =>Encoding.UTF8.GetBytes(s + 
    Environment.NewLine)).ToArray();
Renci.SshNet.Sftp.SftpFileStream stream = sftpClient.OpenWrite("/sftp/dhifi/test.txt");
if (stream.CanWrite)
{
    stream.Write(bconfig,0,bconfig.Length);
}
else Console.WriteLine("Can't Write right now ! "); 

Else, any other solution is welcome, thanks in advance!

Upvotes: 1

Views: 951

Answers (1)

Lance U. Matthews
Lance U. Matthews

Reputation: 16612

SftpClient.OpenWrite() creates a Stream positioned at the beginning of the file. "It is not first truncated to zero bytes" means that Stream will not be writing into what is effectively an empty file, but instead overwriting the existing bytes of the file. Thus, if the existing file is longer than the content parameter of SftpFileStream.Write(), the resulting file will consist of content followed by the remainder of the existing file, which is exactly what you observed.

Looking at the documentation I see a few solutions:

  • SftpClient.AppendAllLines():

    sftpClient.AppendAllLines("/sftp/dhifi/test.txt", config);
    
  • SftpClient.AppendText():

    using (StreamWriter writer = sftpClient.AppendText("/sftp/dhifi/test.txt"))
        foreach (string line in config)
            writer.WriteLine(line);
    
  • Since you want to start writing at the end of the file, instead of SftpClient.OpenWrite() you can call SftpClient.Open(), which allows you to specify a FileMode of Append:

    using (SftpFileStream stream = sftpClient.Open("/sftp/dhifi/test.txt", FileMode.Open | FileMode.Append))
        stream.Write(bconfig, 0, bconfig.Length);
    

    I don't believe your check of CanWrite is necessary because the Stream should fail to open in the first place if FileAccess.Write could not be granted.

    If FileMode.Append for some reason doesn't work with SSH.NET (and it looks like it does since that's what AppendText() uses) you could instead use @jdweng's suggestion and seek to the end of the file before writing to it:

    using (SftpFileStream stream = sftpClient.OpenWrite("/sftp/dhifi/test.txt"))
    {
        stream.Seek(0, SeekOrigin.End);
        stream.Write(bconfig, 0, bconfig.Length);
    }
    

As an aside, another way to inject NewLines between your config lines would be...

byte[] bconfig = Encoding.UTF8.GetBytes(
    string.Join(Environment.NewLine, config)
);

That's a little shorter and more efficient since it reduces the number of intermediate strings and byte[]s.

Upvotes: 1

Related Questions