Difference between structures ttysize and winsize? - linux

I have following code to get width and height of screen in Linux.
#ifdef TIOCGSIZE
struct ttysize ts;
ioctl(STDIN_FILENO, TIOCGSIZE, &ts);
cols = ts.ts_cols;
lines = ts.ts_lines;
#elif defined(TIOCGWINSZ)
struct winsize ts;
ioctl(STDIN_FILENO, TIOCGWINSZ, &ts);
cols = ts.ws_col;
lines = ts.ws_row;
#endif /* TIOCGSIZE */
What is difference between ttysize and winsize?

The ttysize was the original implementation for SunOS 3.0 (February 1986), and soon after made obsolete by winsize, which adds the size of the window in pixels. Here's
what the definitions look like in <sys/ttycom.h> from SunOS 4:
/*
* Window/terminal size structure.
* This information is stored by the kernel
* in order to provide a consistent interface,
* but is not used by the kernel.
*
* Type must be "unsigned short" so that types.h not required.
*/
struct winsize {
unsigned short ws_row; /* rows, in characters */
unsigned short ws_col; /* columns, in characters */
unsigned short ws_xpixel; /* horizontal size, pixels - not used */
unsigned short ws_ypixel; /* vertical size, pixels - not used */
};
#define TIOCGWINSZ _IOR(t, 104, struct winsize) /* get window size */
#define TIOCSWINSZ _IOW(t, 103, struct winsize) /* set window size */
/*
* Sun version of same.
*/
struct ttysize {
int ts_lines; /* number of lines on terminal */
int ts_cols; /* number of columns on terminal */
};
#define TIOCSSIZE _IOW(t,37,struct ttysize)/* set tty size */
#define TIOCGSIZE _IOR(t,38,struct ttysize)/* get tty size */
The data types are different (an integer would waste memory), and the fields have different names.
The ttysize structure has long been obsolete: if either is provided by the system, winsize is supported. That wasn't true when porting ncurses to SCO OpenServer in 1997, as noted in this chunk from lib_setup.c:
/*
* SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
* Solaris, IRIX) define TIOCGWINSZ and struct winsize.
*/
#ifdef TIOCGSIZE
# define IOCTL_WINSIZE TIOCGSIZE
# define STRUCT_WINSIZE struct ttysize
# define WINSIZE_ROWS(n) (int)n.ts_lines
# define WINSIZE_COLS(n) (int)n.ts_cols
#else
# ifdef TIOCGWINSZ
# define IOCTL_WINSIZE TIOCGWINSZ
# define STRUCT_WINSIZE struct winsize
# define WINSIZE_ROWS(n) (int)n.ws_row
# define WINSIZE_COLS(n) (int)n.ws_col
# endif
#endif
You might notice that Linux is not mentioned in the comment. According to comments in asm-sparc64/ioctls.h, the ioctl for ttysize was unsupported as of 2.6.16:
/* Note that all the ioctls that are not available in Linux have a
* double underscore on the front to: a) avoid some programs to
* think we support some ioctls under Linux (autoconfiguration stuff)
*/
...
#define TIOCCONS _IO('t', 36)
#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
#define TIOCGSOFTCAR _IOR('t', 100, int)
#define TIOCSSOFTCAR _IOW('t', 101, int)
#define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */
#define TIOCSWINSZ _IOW('t', 103, struct winsize)
#define TIOCGWINSZ _IOR('t', 104, struct winsize)
A much earlier comment in 1995 added the definitions (without the double-underscore). Possibly a few programs used that with Linux, although winsize was well established on most platforms before Linux was begun. A little more digging finds that the double-underscore was introduced in 1996 (patch-2.1.9 linux/include/asm-sparc/ioctls.h). Given that, very few programs would have used it with Linux.
Further reading:
Garbage-collect struct ttysize (OpenBSD mailing list)
/dev/console MKS manual page

They have the same function (at least in this case - maybe one structure has an additional field not used here).
Historically some (mainly older) Linux versions have different definitions of the IOCTL codes. Therefore some Linux versions have only TIOCGSIZE defined (using a ttysize structure) and some Linux versions have only TIOCGWINSZ defined.
Using the "#ifdef" construction the program can be compiled for both Linux versions.
Newer Linux versions should have both IOCTLs defined.

Related

How to evaluate the flags field of mtd_info_user?

The MTD driver placed inside the Linux kernel source has a definition as below.
struct mtd_info_user {
__u8 type;
__u32 flags;
__u32 size; /* Total size of the MTD */
__u32 erasesize;
__u32 writesize;
__u32 oobsize; /* Amount of OOB data per block (e.g. 16) */
__u64 padding; /* Old obsolete field; do not use */
};
I'm trying to understand what the flags field stands for. My ultimate purpose is to find a way to check if the external MTD device is healthy. I thought that the flags field can represent the actual status of the device.
Inside the mtdchar_open(..) function from mtdchar.c source code, there is a comparison as below.
/* You can't open it RW if it's not a writeable device */
if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
ret = -EACCES;
goto out1;
}
So, I guess the flags field can be evaluated by using the macros from the mtd-abi.h header.
#define MTD_ABSENT 0
#define MTD_RAM 1
#define MTD_ROM 2
#define MTD_NORFLASH 3
#define MTD_NANDFLASH 4 /* SLC NAND */
#define MTD_DATAFLASH 6
#define MTD_UBIVOLUME 7
#define MTD_MLCNANDFLASH 8 /* MLC NAND (including TLC) */
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
The problem is about why some of those definitions are declared like normal integers, e.g. MTD_ABSENT.

Where do we define the type of structure returned by the kernel when using the "perf_event_open" system call using mmap?

I'm trying to use the syscall perf_event_open to get some performance data from the system.
I am currently working on periodic data retrieval using shared memory with a ring buffer.
But I can't find what structure is returned in each section of the ring buffer. The manual page enumerate all possibilities, but that's all.
I can't figure out which member of the perf_event_attr structure to fill in to control what type of structure will be returned to the ring buffer.
If you have some informations about that, I'll be happy to read it !
The https://github.com/torvalds/linux/blob/master/tools/perf/design.txt documentation has description of mmaped ring, and perf script / perf script -D can decode ring data when it is saved as perf.data file. Some parts of the doc are outdated, but it is still useful for perf_event_open syscall description.
First mmap page is metadata page, rest 2^n pages are filled with events where every event has header struct perf_event_header of 8 bytes.
Like stated, asynchronous events, like counter overflow or PROT_EXEC
mmap tracking are logged into a ring-buffer. This ring-buffer is
created and accessed through mmap().
The mmap size should be 1+2^n pages, where the first page is a
meta-data page (struct perf_event_mmap_page) that contains various
bits of information such as where the ring-buffer head is.
/*
* Structure of the page that can be mapped via mmap
*/
struct perf_event_mmap_page {
__u32 version; /* version number of this structure */
__u32 compat_version; /* lowest version this is compat with */
...
}
The following 2^n pages are the ring-buffer which contains events of the form:
#define PERF_RECORD_MISC_KERNEL (1 << 0)
#define PERF_RECORD_MISC_USER (1 << 1)
#define PERF_RECORD_MISC_OVERFLOW (1 << 2)
struct perf_event_header {
__u32 type;
__u16 misc;
__u16 size;
};
enum perf_event_type
The design.txt doc has incorrect values for enum perf_event_type, check actual perf_events kernel subsystem source codes - https://github.com/torvalds/linux/blob/master/include/uapi/linux/perf_event.h#L707. That uapi/linux/perf_event.h file also has some struct hints in comments, like
* #
* # The RAW record below is opaque data wrt the ABI
* #
* # That is, the ABI doesn't make any promises wrt to
* # the stability of its content, it may vary depending
* # on event, hardware, kernel version and phase of
* # the moon.
* #
* # In other words, PERF_SAMPLE_RAW contents are not an ABI.
* #
*
* { u32 size;
* char data[size];}&& PERF_SAMPLE_RAW
*...
* { u64 size;
* char data[size];
* u64 dyn_size; } && PERF_SAMPLE_STACK_USER
*...
PERF_RECORD_SAMPLE = 9,

What is the `flags` field for in canfd_frame in SocketCAN?

A non-FD ("legacy") CAN frame has the following format in SocketCAN:
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length in byte (0 .. 8) */
__u8 __pad; /* padding */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[8] __attribute__((aligned(8)));
};
The frame ID, length, and data all have clear places, plus some padding we don't worry about. For a CAN-FD frame, though, there is an extra field:
struct canfd_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 len; /* frame payload length in byte (0 .. 64) */
__u8 flags; /* additional flags for CAN FD */
__u8 __res0; /* reserved / padding */
__u8 __res1; /* reserved / padding */
__u8 data[64] __attribute__((aligned(8)));
};
The flags field looks useful, but I have found no documentation as to what it actually holds. Is it internal (i.e. set by the kernel)? What are the possible flags, and what do they mean?
Thank you!
I found a bit of information here:
http://elixir.free-electrons.com/linux/latest/source/include/uapi/linux/can.h#L112
/*
* defined bits for canfd_frame.flags
*
* The use of struct canfd_frame implies the Extended Data Length (EDL) bit to
* be set in the CAN frame bitstream on the wire. The EDL bit switch turns
* the CAN controllers bitstream processor into the CAN FD mode which creates
* two new options within the CAN FD frame specification:
*
* Bit Rate Switch - to indicate a second bitrate is/was used for the payload
* Error State Indicator - represents the error state of the transmitting node
*
* As the CANFD_ESI bit is internally generated by the transmitting CAN
* controller only the CANFD_BRS bit is relevant for real CAN controllers when
* building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
* sense for virtual CAN interfaces to test applications with echoed frames.
*/
If I understand this right, the ESI bit is only useful for testing on virtual CAN interaces. The BRS bit is pretty low-level, though, and this does not specify whether the hardware will automatically set it or unset it.

Why is does proc_create mode argument 0 correspond to 0444

I am a newbie to kernel programming and am trying to userstand procfs. I have googled several examples and they all use:
proc_create("hello",0,NULL,&proc_fops);
where the second argument is the file mode / permission. Per proc_fs.h:
static inline struct proc_dir_entry *proc_create(
const char *name, umode_t mode, struct proc_dir_entry *parent,
const struct file_operations *proc_fops)
the mode is umode_t type which as far as I can tell is resolved to unsigned short int.
In at least 3 examples, the accompanying comments and verbiage indicate substantially the same thing, that " the value zero you see there represents the permissions you want on the proc file, where zero represents the default value of file permissions of 0444. In other words, you could have just used tt he numeric value 0444 (for octal), or 0400 for more restrictive access, and so on. But using zero for a typical readable proc file is fairly normal."
I'm having trouble understanding what this means. I understand file permissions, chmod u+x , octal numbers, and I think I understand umask.
I'm just not clear on how 0 maps to 0444, and what would happen if I put 1 there instead of 0.
The answer seems to be only very little bit further. include/linux/proc_fs.h says:
static inline struct proc_dir_entry *proc_create(
const char *name, umode_t mode, struct proc_dir_entry *parent,
const struct file_operations *proc_fops)
{
return proc_create_data(name, mode, parent, proc_fops, NULL);
}
proc_create_data is defined in fs/proc/generic.c. And there it is:
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
struct proc_dir_entry *parent,
const struct file_operations *proc_fops,
void *data)
{
...
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO;
...
}
If mode is preventing everyone doing anything, set mode to 00444.
For completness, from include/linux/stat.h:
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
and from include/uapi/linux/stat.h:
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#define S_IRWXU 00700
#define S_IRUSR 00400
#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IRWXO 00007
#define S_IROTH 00004

Geting numbers of files in specific directory in Linux

Is there anyway to get the total number of files in a specific directory not iterating readdir(3)?
I mean only direct members of a specific directory.
It seems that the only way to get the number of files is calling readdir(3) repeatedly until it returns zero.
Is there any other way to get the number in O(1)? I need a solution that works in Linux.
Thanks.
scandir() example, requires dirent.h:
struct dirent **namelist;
int n=scandir(".", &namelist, 0, alphasort); // "." == current directory.
if (n < 0)
{
perror("scandir");
exit(1);
}
printf("files found = %d\n", n);
free(namelist);
I don't think it is possible in O(1).
Just think about inode structure. There's no clue for this.
But if it's OK to get number of files in a filesystem,
you can use statvfs(2).
#include <sys/vfs.h> /* or <sys/statfs.h> */
int statfs(const char *path, struct statfs *buf);
struct statfs {
__SWORD_TYPE f_type; /* type of file system (see below) */
__SWORD_TYPE f_bsize; /* optimal transfer block size */
fsblkcnt_t f_blocks; /* total data blocks in file system */
fsblkcnt_t f_bfree; /* free blocks in fs */
fsblkcnt_t f_bavail; /* free blocks available to
unprivileged user */
fsfilcnt_t f_files; /* total file nodes in file system */
fsfilcnt_t f_ffree; /* free file nodes in fs */
fsid_t f_fsid; /* file system id */
__SWORD_TYPE f_namelen; /* maximum length of filenames */
__SWORD_TYPE f_frsize; /* fragment size (since Linux 2.6) */
__SWORD_TYPE f_spare[5];
};
You can easily get number of files via f_files - f_ffree.
BTW, This is very interesting question. so I voted it up.
In shell script it's damn simple
ll directory_path | wc -l

Resources