why iconv read more bytes than i specified - linux

I use
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
to convert UTF-16BE to GB2312.
inbytesleft is bytes number to be convert. After conversion, inbytesleft is bytes number of not converted.
After one call, I found inbytesleft is -2, according to iconv man page this function should read at most inbytesleft.
Who can tell my why and how to fix this?
code to be convert is
"保单验证"
Thanks

How are you getting the input data into your program?
I've tested the situation using this code and it seems to work:
#include <stdio.h>
#include <iconv.h>
#include <errno.h>
int main(){
char data[10] = {0x4f,0xdd,0x53,0x55,0x9a,0x8c,0x8b,0xc1, 0, 0};
char outdata[20];
char *dataptr;
char *outdataptr;
iconv_t cd;
size_t result;
size_t inbytesleft = 8;
size_t outbytesleft = 20;
int i;
cd = iconv_open("GB2312", "UTF-16BE");
dataptr = data;
outdataptr = outdata;
result = iconv(cd, &dataptr, &inbytesleft, &outdataptr, &outbytesleft);
if(result == -1)
printf("Error: %d\n", errno);
printf(" result: %zd\n", result);
printf(" inbytesleft: %zd\n", inbytesleft);
printf("outbytesleft: %zd\n", outbytesleft);
for(i = 20; i > outbytesleft; i--){
if(i != 20)
printf(",");
printf("0x%02x", *((unsigned char *)&(outdata[20-i])));
}
printf("\n");
return 0;
}
It prints
result: 0
inbytesleft: 0
outbytesleft: 12
0xb1,0xa3,0xb5,0xa5,0xd1,0xe9,0xd6,0xa4
Which appears to be correct.
The array of items in the variable data is the UTF-16BE encoding of 保单验证
If this doesn't help, could you post your code for analysis?

Related

Non collective write using in file view

When trying to write blocks to a file, with my blocks being unevenly distributed across my processes, one can use MPI_File_write_at with the good offset. As this function is not a collective operation, this works well.
Exemple :
#include <cstdio>
#include <cstdlib>
#include <string>
#include <mpi.h>
int main(int argc, char* argv[])
{
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int global = 7; // prime helps have unbalanced procs
int local = (global/size) + (global%size>rank?1:0);
int strsize = 5;
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "output.txt", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
for (int i=0; i<local; ++i)
{
size_t idx = i * size + rank;
std::string buffer = std::string(strsize, 'a' + idx);
size_t offset = buffer.size() * idx;
MPI_File_write_at(fh, offset, buffer.c_str(), buffer.size(), MPI_CHAR, MPI_STATUS_IGNORE);
}
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
However for more complexe write, particularly when writting multi dimensional data like raw images, one may want to create a view at the file with MPI_Type_create_subarray. However, when using this methods with simple MPI_File_write (which is suppose to be non collective) I run in deadlocks. Exemple :
#include <cstdio>
#include <cstdlib>
#include <string>
#include <mpi.h>
int main(int argc, char* argv[])
{
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int global = 7; // prime helps have unbalanced procs
int local = (global/size) + (global%size>rank?1:0);
int strsize = 5;
MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "output.txt", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);
for (int i=0; i<local; ++i)
{
size_t idx = i * size + rank;
std::string buffer = std::string(strsize, 'a' + idx);
int dim = 2;
int gsizes[2] = { buffer.size(), global };
int lsizes[2] = { buffer.size(), 1 };
int offset[2] = { 0, idx };
MPI_Datatype filetype;
MPI_Type_create_subarray(dim, gsizes, lsizes, offset, MPI_ORDER_C, MPI_CHAR, &filetype);
MPI_Type_commit(&filetype);
MPI_File_set_view(fh, 0, MPI_CHAR, filetype, "native", MPI_INFO_NULL);
MPI_File_write(fh, buffer.c_str(), buffer.size(), MPI_CHAR, MPI_STATUS_IGNORE);
}
MPI_File_close(&fh);
MPI_Finalize();
return 0;
}
How to avoid such a code to lock ? Keep in mind that by real code will really use the multidimensional capabilities of MPI_Type_create_subarray and cannot just use MPI_File_write_at
Also, it is difficult for me to know the maximum number of block in a process, so I'd like to avoid doing a reduce_all and then loop on the max number of block with empty writes when localnb <= id < maxnb
You don't use MPI_REDUCE when you have a variable number of blocks per node. You use MPI_SCAN or MPI_EXSCAN: MPI IO Writing a file when offset is not known
MPI_File_set_view is collective, so if 'local' is different on each processor, you'll find yourself calling a collective routine from less than all processors in the communicator. If you really really need to do so, open the file with MPI_COMM_SELF.
the MPI_SCAN approach means each process can set the file view as needed, and then blammo you can call the collective MPI_File_write_at_all (even if some processes have zero work -- they still need to participate) and take advantage of whatever clever optimizations your MPI-IO implementation provides.

Driver programming : cat command not showing output

I am new to driver programming and I have written a simple char device driver code. When I wrote it without using pointers, it crashed.
When writing to a driver using echo, it works. But when reading from it, there is no output. Someone please help. File operations part of the code is shown below. 'p' and 'q' are normal character pointers. 'max' value was set as 10. 'ptr' is of static int type initialized as '0'.
int my_open(struct inode *inode,struct file *filp)
{
printk("In open.\n");
if((filp->f_flags & O_ACCMODE) == O_WRONLY){
p = (char *)buffer;
ptr = 0;
}
else if((filp->f_flags & O_ACCMODE) == O_RDONLY)
q = (char *)buffer;
return 0;
}
int my_close(struct inode *inode,struct file *filp)
{
printk("In close.\n");
return 0;
}
ssize_t my_read(struct file *filp,char *buff,size_t count,loff_t *pos)
{
long ret;
printk("In read.\n");
ret = copy_to_user(buff,q,max);
q += max;
*pos += max;
if(ptr -= max)
return max;
else
return 0;
}
ssize_t my_write(struct file *filp,const char *buff,size_t count,loff_t *pos)
{
long ret;
printk("In write.\n");
ret = copy_from_user(p,buff,max);
p += max;
*pos += max;
ptr += max;
return max;
}
module_init(my_init);
module_exit(my_exit);
In both read and write you are not taking into account the "count" parameter, as your code seems to assume that "count>=max", that is not guaranteed. This by itself may lead to any sort of troubles in the process executing read. Also, you copy_to/from_user before checking if the current read or write position is over the buffer limit. Moreover, the assignment/test if (ptr -= max) only works if ptr is exactly equal to max, also not guaranteed it you execute the read more than once.
NOTE: since definitions of p, q, buffer, ptr and max are missing, I'll assume that they look like:
static char *p;
static char *q;
statint int ptr = 0;
static char buffer[10];
static int max=10;

How to get certificate serial number using vc++

i want to get the certificate serial number using vc++ code.
HANDLE hStoreHandle;
PCCERT_CONTEXT pCertContext=NULL;
PCERT_PUBLIC_KEY_INFO pOldPubKey = NULL;
char fResponse ='n';
hStoreHandle = CertOpenSystemStore(NULL,"MY");
while(pCertContext= CertEnumCertificatesInStore(hStoreHandle,pCertContext))
{
CString strSubVal,strResult,strInput;
BYTE *pbName=pCertContext->pCertInfo->SerialNumber.pbData;
}
i think the above code having theserial number data but i dont know how to get it in CString format.Guide me
copy paste the below code
#include <stdio.h>//yourDialog.cpp file
#include <windows.h>
#include <Wincrypt.h>
#include <iostream>
#include <conio.h>
#include <string>
using namespace std;
#pragma comment(lib, "crypt32.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH 0x00800000
PCCERT_CONTEXT pCertContext=NULL;
HANDLE hStoreHandle;
PCERT_PUBLIC_KEY_INFO pOldPubKey = NULL;
char fResponse ='n';
hStoreHandle = CertOpenSystemStore(NULL,"MY");
pCertContext= CertEnumCertificatesInStore(hStoreHandle,pCertContext);
PCERT_INFO pCertifInfo = pCertContext->pCertInfo;
BYTE* pbData = pCertifInfo->SerialNumber.pbData;
DWORD cbData = pCertifInfo->SerialNumber.cbData;
char hex_ascii[3];
CString csAscii;
csAscii.Empty();
if (cbData > 0)
{
int i;
CString cs;
for (i=0; i < cbData; i++)
{
BYTE bb = (BYTE) pbData[i];
sprintf(hex_ascii, "%02X", bb);
cs.Format("%s", hex_ascii);
csAscii = cs + csAscii ;
}
}
Not sure if you want this: the code below puts the data into a hexadecimal string (theString)
BYTE *pbName=pCertContext->pCertInfo->SerialNumber.pbData;
CString theString ;
for (int i = 0; i < pCertContext->pCertInfo->SerialNumber.cbData; i++)
{
CString hex ;
hex.Format("%02x", pbName[i]) ;
theString += hex ;
}
The code above will give you the Serial Number 'in reverse'. You can confirm this by viewing the serial number in the certificate, by using the 'certmgr.msc' tool.
To get the serial number in the 'correct' order, just change the direction of the for loop. Below is the modified version of the code given above:
BYTE *pbName=pCertContext->pCertInfo->SerialNumber.pbData;
CString theString ;
for (int i = pCertContext->pCertInfo->SerialNumber.cbData - 1; i >= 0 ; i--)
{
CString hex ;
hex.Format("%02x", pbName[i]) ;
theString += hex ;
}

Program to see the bytes from a file internally

Do you know if exist one program or method to see (secuences of)bytes from a text,html file?
Not to see characters, rather see the complete sequence of bytes.
recommendations?
yes, it is called hex editor... Hundreds of those exist out there.
Here are some: http://en.wikipedia.org/wiki/Comparison_of_hex_editors
A common hex editor allows you to view any file's byte sequence.
If you just want to see the existing bytes (without changing them) you can use a hex-dump program, which is much smaller and simpler than a hex editor. For example, here's one I wrote several years ago:
/* public domain by Jerry Coffin
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
unsigned long offset = 0;
FILE *input;
int bytes, i, j;
unsigned char buffer[16];
char outbuffer[60];
if ( argc < 2 ) {
fprintf(stderr, "\nUsage: dump filename [filename...]");
return EXIT_FAILURE;
}
for (j=1;j<argc; ++j) {
if ( NULL ==(input=fopen(argv[j], "rb")))
continue;
printf("\n%s:\n", argv[j]);
while (0 < (bytes=fread(buffer, 1, 16, input))) {
sprintf(outbuffer, "%8.8lx: ", offset+=16);
for (i=0;i<bytes;i++) {
sprintf(outbuffer+10+3*i, "%2.2X ",buffer[i]);
if (!isprint(buffer[i]))
buffer[i] = '.';
}
printf("%-60s %*.*s\n", outbuffer, bytes, bytes, buffer);
}
fclose(input);
}
return 0;
}

How can I find the size of a ELF file/image with Header information?

I need to find the size of an elf image for some computation. I have tried with the readelf utility on linux which gives the informations about the headers and section. I need to have the exact file size of the elf(on the whole).
How do I find the size of the ELF from the header information or Is there any other means to find the size of an elf without reading the full image.
The answer to the specific question is a little tricky for ELF files.
The following will compute the size of the "descriptive" information in an ELF file using the header: e_ehsize + (e_phnum * e_phentsize) + (e_shnum * e_shentsize)
The above is based on the ELF documentation.
The next piece to add to the above sum is the size in the file of the section entries. Intuitively we would like to compute this using sh_size for each of the sections in the file -- e_shnum of them. HOWEVER, this doesn't yield the correct answer due to alignment issues. If you use an ordered list of sh_offset values you can compute the exact number of bytes that the section entry occupies (I found some strange alignments where using sh_addralign isn't as useful as you would like); for the last section entry use the file header's e_shoff since the section header table is last. This worked for the couple I checked.
update.c in libelf has the details it uses when updating an elf file.
Example:
ls -l gives 126584
Calculation using the values also reported by readelf -h:
Start of section headers e_shoff 124728
Size of section headers e_shentsize 64
Number of section headers e_shnum 29
e_shoff + ( e_shentsize * e_shnum ) = 126584
This assumes that the section header table (SHT) is the last part of the ELF. This is usually the case but it could also be that the last section is the last part of the ELF. This should be checked for, but is not in this example.
Here is a working implementation in C, compile with gcc elfsize.c -o elfsize:
#include <elf.h>
#include <byteswap.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
typedef Elf32_Nhdr Elf_Nhdr;
static char *fname;
static Elf64_Ehdr ehdr;
static Elf64_Phdr *phdr;
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ELFDATANATIVE ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ELFDATANATIVE ELFDATA2MSB
#else
#error "Unknown machine endian"
#endif
static uint16_t file16_to_cpu(uint16_t val)
{
if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
val = bswap_16(val);
return val;
}
static uint32_t file32_to_cpu(uint32_t val)
{
if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
val = bswap_32(val);
return val;
}
static uint64_t file64_to_cpu(uint64_t val)
{
if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
val = bswap_64(val);
return val;
}
static long unsigned int read_elf32(int fd)
{
Elf32_Ehdr ehdr32;
ssize_t ret, i;
ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
fprintf(stderr, "Read of ELF header from %s failed: %s\n",
fname, strerror(errno));
exit(10);
}
ehdr.e_shoff = file32_to_cpu(ehdr32.e_shoff);
ehdr.e_shentsize = file16_to_cpu(ehdr32.e_shentsize);
ehdr.e_shnum = file16_to_cpu(ehdr32.e_shnum);
return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}
static long unsigned int read_elf64(int fd)
{
Elf64_Ehdr ehdr64;
ssize_t ret, i;
ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
if (ret < 0 || (size_t)ret != sizeof(ehdr)) {
fprintf(stderr, "Read of ELF header from %s failed: %s\n",
fname, strerror(errno));
exit(10);
}
ehdr.e_shoff = file64_to_cpu(ehdr64.e_shoff);
ehdr.e_shentsize = file16_to_cpu(ehdr64.e_shentsize);
ehdr.e_shnum = file16_to_cpu(ehdr64.e_shnum);
return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
}
long unsigned int get_elf_size(char *fname)
/* TODO, FIXME: This assumes that the section header table (SHT) is
the last part of the ELF. This is usually the case but
it could also be that the last section is the last part
of the ELF. This should be checked for.
*/
{
ssize_t ret;
int fd;
long unsigned int size = 0;
fd = open(fname, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Cannot open %s: %s\n",
fname, strerror(errno));
return(1);
}
ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
if (ret != EI_NIDENT) {
fprintf(stderr, "Read of e_ident from %s failed: %s\n",
fname, strerror(errno));
return(1);
}
if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
(ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
{
fprintf(stderr, "Unkown ELF data order %u\n",
ehdr.e_ident[EI_DATA]);
return(1);
}
if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
size = read_elf32(fd);
} else if(ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
size = read_elf64(fd);
} else {
fprintf(stderr, "Unknown ELF class %u\n", ehdr.e_ident[EI_CLASS]);
return(1);
}
close(fd);
return size;
}
int main(int argc, char **argv)
{
ssize_t ret;
int fd;
if (argc != 2) {
fprintf(stderr, "Usage: %s <ELF>\n", argv[0]);
return 1;
}
fname = argv[1];
long unsigned int size = get_elf_size(fname);
fprintf(stderr, "Estimated ELF size on disk: %lu bytes \n", size);
return 0;
}
Perhaps gelf could be useful.
GElf is a generic, ELF class-independent API for manipulat- ing ELF object files. GElf provides a single, common inter- face for handling 32-bit and 64-bit ELF format object files.
specifically these functions:
elf32_fsize, elf64_fsize - return the size of an object file type
Have you tried using the gnu "readelf" utility?
http://sourceware.org/binutils/docs/binutils/readelf.html
All you have to do is to sum the last section's file offset and its size.
fseek(fileHandle, elfHeader.e_shoff + (elfHeader.e_shnum-1) * elfHeader.e_shentsize, SEEK_SET);
Elf64_Shdr sectionHeader; // or Elf32_Shdr
fread(&sectionHeader, 1, elfHeader.e_shentsize, fileHandle);
int fileSize = sectionHeader.sh_offset + sectionHeader.sh_size;
elfHeader used values:
e_shoff = Section header table file offset
e_shnum = Section header table entry count
e_shentsize = Section header table entry size
sectionHeader used values:
sh_offset = Section file offset
sh_size = Section size in bytes
You can use the stat functions family (stat(), lstat(), fstat()) to get the size of any file (using the st_size member of the stat member).
Do you need something more specific?
If you really want to use the ELF structure, use the elf.h header which contains that structure:
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
ElfN_Addr e_entry;
ElfN_Off e_phoff;
ElfN_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf32_Ehdr;
It's the header of an ELF32 file (replace 32 with 64 for a 64-bit file).
e_ehsize is the size of the file in bytes.
I'll copy verbatim the comment that was posted as an edit suggestion:
This answer is incorrect. e_ehsize is merely the size of the elf header, not the elf file.

Resources