Archived Forum Post

Index of archived forum posts

Question:

write file with control chars

Jul 04 '17 at 12:04

I'm using a raspberry pi to store some files. I used Chilkat SSH/SCP lib and is working. I also have a C++ program that generate a file using ascii (0-256) chars. If I write the file to my local disk with fwrite it will write correctly but if I try to append to a file using SCP it will only write some parts. I think that is because of the control chars (0-31).

In the source.cpp:

while (!feof(filename))
{
size_t read = fread(&buf, 1, max_array, filename);
                    for (unsigned long long i = 0; i < read; i++)
                    {
                        char rdn = GetRandom_Soft();
                        num[i] = rdn;
                        buf[i] = buf[i] + rdn;
                    }
                    fwrite(&num, sizeof(char), read, filename2);
                    s7c.WriteKey((char *)rasp_file.c_str(), buf);
}

Then I have a func "s7c.WriteKey" with Chilkat lib:

int s7c_SFTP::WriteKey(char * filename, char * c)
{
    if (s7c_SFTP::bloked) return -1;
if (!s7c_SFTP::scp.UploadString(filename, c, "ansi"))
{
    cout << "[ERROR] Erro sending to device!" << endl;
    return -2;
}
return 0;
}

And "GetRandom_Soft":

char otp_samega7cattac::GetRandom_Soft()
{
    return rand() % 256;
}

Result: For example you have a input of a 1Mb file so the file genareted localy will have the same size and he have so that part works, but the file generated in the raspberry will be smaller and the size isn't the same every time I run the program, so I think that is because when I sum what I read with the random number if is between 0 and 31 the lib dont write it.

Original file (61 bytes):

abcdefghijklmnopqrstuvyxwzABCDEFGHIJKLMNOPQRSTUVYXWZ123456789

Local File (work! 61 bytes):

.覦 {5・&」jN)sエxG悵コrp焏Ь断・ムイノη`WP>・|auロ・lツn

Raspberry (nope, 20 bytes) #1 try:

ÿ’_dN'–^N%eÖµ€%¤ŸAÞ

Raspberry (almost, 58 bytes) #2 try:

vI³áœ€Ot×¼˜ã%»n%4>´F´@™U̦ܱÑÔÔ³«¥”ó[Ó»¦
(l¡øS¦G

Can exist some kind of chars this textbox don't acept so I put the sizes!

Now I have sure the problem are the control chars!!!

I made a test. If the sum of the random char and the buffer is lower then 31 I especify the buf[i] = 'a'; And the sizes matches!!!

But I have no idea how to write control chars in the raspberry pi because I need all chars (0-255).


Answer

When you call UploadString in C/C++, you're passing a "const char *" to it. This is a null-terminated sequence of bytes, and Chilkat needs to interpret the bytes according to some character encoding. The default is ANSI, but could be utf-8 if you call scp.put_Utf8(true);

ANSI, for the USA, Western Europe, etc. is generally Windows-1252 (or iso-8859-1). If you look at a chart for the byte-value to character mappings (for example 0x20 is the SPACE char), there are code points (i.e. bytes) that represent no character at all. These are dropped.

If you want to truly send bytes (any value 0-255), then you should instead call UploadBinary. In this case, you cannot send a 0x00 byte because you're passing a null-terminated "string" in C++. (I say "string" because C/C++ is a programming language where, originally, the character encoding of the "string" was implicitly assumed to be us-ascii.) In reality, when dealing with "const char *" in C/C++, one doesn't have full information. One must take care to note whether the bytes are utf-8, iso-8859-1, or perhaps some other multibyte encoding for another language such as Russian, Greek, Hebrew, etc..

The UploadBinary method accepts 2 args: bool UploadBinary(const char *remotePath, CkByteData &binData);

Do this:

CkByteData bData;
bData.append2(c,(unsigned long)strlen(c));
bool success = scp.UploadBinary(filename,bData);