2009/12

获取C语言数据类型大小

一个简单的脚本,可以在命令行下获取C语言中数据类型的大小。在邮件列表的讨论中看到的这个主意,我用 Perl 重写了一下。

代码很简单,见下。分享一下,希望对你有用。
[perl]

!/usr/bin/perl -w

use strict;
use File::Temp qw/tempfile tempdir/;

die “Wrong usage.n” unless @ARGV == 1;
my $type=$ARGV[0];
my $dir = tempdir(CLEANUP => 1);
my ($obj, $src) = tempfile(“$dir/XXXXX”, SUFFIX => ‘.c’, UNLINK => 0);
open my $fd, “>$src” or die “can’t create file: $!”;
$src =~ s/.c$//g;
my $exe_file = $src;

print $fd <<eof;

include

include

include

include

include

include

include

include

include

include

include

include

include

int
main (void)
{
$type x;
printf (“%d\n”, sizeof x);
exit (0);
}
EOF
my $result = qx(gcc -o $exe_file $exe_file.c && $exe_file);
print $result;
[/perl]

Christmas gifts from Portugal!

Today I was surprised that I received a box of gifts from Ricardo and Ana for Christmas! Hooray!

I really really love all of them, they are nice and sweet! :) Thank you so much!! Merry Christmas!

Okay, below are they.

The box which contains everything:

Porto wine!! We already tried one bottle! So sweet! I like it…

A Christmas card:

And a little “sheep” made by Ana with hands… so cute!

And also there is a cap for which I don’t take a picture. I think I can wear it now since it’s cold in Beijing these days. ;)

Hmmm, I can still clearly remember which Christmas gifts I got from Ana last year. It is already one year past since I left Portugal! Time goes sooooo fast! I miss all the friends that I met in Portugal! Good old days!

Next year, we plan to go to Portugal to attend a friend’s wedding which is scheduled in July. I wish I could meet all the friends at that time. Go back to Europe, go back to Portugal, go back to Coimbra!

东北行计划

元旦计划去东北,主要是去哈尔滨。这将是头一次去东北,目前去过祖国最北的地方仍然是北京……

时间:
1月1号晚上北京出发,1月6号晚上回京。

具体计划:
1.1晚,卧铺-沈阳
1.2沈阳中街,故宫,大帅府
1.2晚,卧铺-齐齐哈尔
1.3齐齐哈尔观鹤(扎龙自然保护区,俗称鹤乡)
1.3下午/傍晚,火车-哈尔滨
1.3/4/5宿哈尔滨
4/5行程:索菲亚教堂,中央大街,松花江,太阳岛,兆麟公园,冰雪大世界
1.6早,硬座-长春,长春行程待定
1.6晚,飞机-首都机场

预计费用:
行,900¥;住,150¥;其它费用包括吃,景点门票,打的等等。总共预计,2000¥。

在哈尔滨住宿还未定,初步计划住哈工大附近。

希望去过上面几个地方的朋友不吝赐教攻略。同时征同行,虽然你可能并不在北京出发,虽然可能路线不完全一样。

P.S. 漠河离哈尔滨不是一般远啊,从 google map 上目测了一下,感觉和哈尔滨到大连差不多远,东北真辽阔啊!

symlink,chroot 和 mount

前两天在处理一个关于 selinux 的 bug 时遇到一个比较有意思的问题,顺着仔细往下想了想,发现更多相关的话题,遂整理成一篇文章记录一下。实际上我想到的这几个问题和 selinux 基本上毫无关系,先从简单的谈起,然后顺着我的思路一步步往下走。

最初的问题是,如果我在一个目录中建立了一个符号链接,那么我 chroot 进去之后会得到什么?这个问题比较简单,如果符号链接的目标文件路径在 chroot jail 里也存在,那么你就会得到 chroot jail 里面的那个文件;否则就无法访问到目标文件。这一点有个比较有趣的应用就是,你可以建立一个符号链接,让它在 chroot jail 里面和外面都有效,当你在 jail 外面时你就用外面那个,当你在 jail 里面时里面那个就会“立刻生效”。

接下来的一个问题是,要是我建立的是一个硬链接呢?这个也不难,硬链接会直接访问到目标文件,不存在目标文件存在不存在的问题。那么,如果一个 chroot jail 中有那么一个硬链接,那么你就可以逃出 jail 了?答案是否定的,因为硬链接是不允许建立在目录之上的!至少在 Linux 上如此。在 Linux 上,除了目录“.”“..”你是看不到其它任何硬链接的目录的,为什么?因为如果允许了对目录的硬链接,那么文件系统树状结构层次就会被打破,会出现环。你会说,软链接也不是一样出现环吗?是啊,可是我们对它可以选择 follow 还是不 follow,比如 find(1),默认的情况就是不去 follow 软链接。

呃,在继续向前走之前,这里还有另一个关于 chroot 的问题,那就是 chroot(2) 并不会自己去 chdir(2),也不会关闭任何在此之前打开的文件,无论其是在 jail 里还是 jail外!瞧瞧,Unix 的设计哲学运用得多么好,绝对不多做一件不属于自己的事!但这会带来问题,如果你忘记自己去 chdir(2) 的话你完全可以在 jail 之外通过“..”跳出 jail。这是意料之中的行为,Al Viro解释到:

“If you are within chroot jail and capable of chroot(), you can chdir to its root, then chroot() to subdirectory and you’ve got cwd outside of your new root. After that you can chdir all way out to original root. Again, this is standard behaviour. Changing it will not yield any security improvements, so kindly give that a rest.”
好了,继续向前走。硬链接有个天生的缺陷,就是无法跨文件系统,估计你也能隐约感觉到。想想如果我要 chroot 的是一个U盘目录,比如:/mnt/USB,那么我就无法在里面使用硬链接来链接到外面的文件了。为了解决这个问题,我们可以使用 Linux 上的 bind mount,也就是说把一个文件通过“挂载”的方式给“绑定”到一个地方,从而到达和硬链接一样的效果!但这个可以跨任何文件系统!我们完全可以chroot jail 里使用 bind mount 进来的文件。但是,它是有缺点的,相对于硬链接来说。一,它不会像硬链接那样“永久”存在,一重启就没有了,当然了,你可以修改 fstab,但这并不总是一个好办法;二,bind mount 需要 root 权限,即使两个文件的所有者都不是 root (内核邮件列表中有人提交过 unprivileged bind mounts 的补丁,不知道最后情况如何,至少我在 Fedora 上还是需要 root 权限的)。

从上面可以看出 mount 是个很有意思的东西,如果你觉得 bind mount 比较神奇,别慌,下面还有更神奇的呢。

mount 还提供一个 move 功能,可以帮助你把一个已经 mount 上来的东东移动到另一个地方去,免得你先 umount 再 mount。

还有呢,从 2.6. 15 之后mount 还提供了一个非常强大的功能,shared subtrees。这个稍微有些复杂,它的目的是这样的,比如我想在我的用户目录下克隆一个根目录的结构,通常我该怎么做呢?恩,cp -R,或者 rsync 一下。这么做有个明显的缺点:复制了东西,占用了更多硬盘空间。所以我们用 bind mount 比较合适,但是仅仅这么做还不完美:首先,我的用户目录本身也是在根目录下的,本身也会被 bind mount 进去;其次,如果后来我又在 /mnt 下挂载了新的东西呢?那在我的克隆目录中就看不到了。基于此,mount引入了个新玩意儿叫 shared subtrees,于是你可以这么做:

mount —bind /home/wangcong /home/wangcong
mount —make-unbindable /home/wangcong
mount —bind /mnt /mnt
mount —make-shared /mnt
如此一来,你就可以在 bind mount 上来的所有 /mnt 中看到新挂载的内容了。非常牛叉。

生活是最好的导演

我经常语重心长地给别人说,其实生活啊,才是最好的导演。这不,又发生了一件神奇的事情。
事情是这样的:

今天下班回家刚做完吃完饭,突然接到一个陌生电话,对方自报姓名,说是王简,问我是不是王聪。我一听,哦,原来是公司一起踢球的那哥们啊。解释一下,虽然经常和这哥们一起踢球,但因为不是同一个部门,所以不知道彼此号码;如果想知道也很简单,去公司内网查;所以上面的合情合理。

我问他什么事啊,他说代码遇到问题了,怎么怎么编译不过去,问我如何解决。我大体说了说思路,然后看他电话也说不清楚就问他现在是不是在公司,我过去看看,他说好。一路上我就在琢磨为啥这哥们遇到问题找我啊。

到了公司往那哥们的位置上一看,没人!!问旁边的同事,他们说他今天有事还提前下班回家了!我当时就震惊了,明明刚才说在公司的,而且还遇到代码问题了,怎么突然就没人了!

我冷静了一下,回到我的座位上拿出手机回拨那个号码,问问这哥们到底什么情况。一听电话我就傻了,是另一个人,我还在想他是谁时他倒是听出我来了,竟然是我一个高中同学?!我当时蒙了……

我问他到底是什么情况怎么这么离谱?他解释说他们公司有个叫王聪的,他旁边的一个同事有问题问那个王聪,然后看到他手机里有这个名字就拨了。巧合的是,这个打电话的人也叫王简(是不是同一个字不知道,反正读音一样),正好和我那个踢球的同事重名。更巧的是,我那个同事是东北人,口音很重,而我这个同学在大连工作,所以很可能他那个同事也是东北人,口音还差不多,至少我是没听出啥差别来。更更巧的是,我有那个高中同学的手机号啊,按理说能看到是不是他的手机打来的,可偏偏是他那个号欠费,用的另一个号码……

更更更巧的是,还好我今天晚上和美国那边开会,否则就白来一趟了……

瞧,生活导演了一部多么好的小电影啊!