月度归档:2010年07月

替换掉linux下的rm脚本

前几天,稀里糊涂的在某一个终端下rm *,酿成了惨剧,在经过大量baidu/google加上自己的研究之后
终于决定替换掉rm这个命令,这个命令确实太邪恶了。

【分析】

首先,gnome下的回收站位置一般都是$HOME/.local/share/Trash/
其下有{expunged,files,info}三个文件夹
expundged   擦掉, 删掉, 除去,想必应该是已删除文件(但是实际测试过程中没发现用途)
files              删除的文件存储在这个地方(不列举删除目录下的文件)
info               记录删除文件的相关信息格式:文件名.trashinfo(不列举删除目录下的文件)
这个记录信息并不区分文件或者文件夹,只记录最顶层的文件(包括文件夹,文件夹也是一种文件)

文件名.trashinfo(系统默认使用的是local的内码来表示汉字,但是经测试直接用汉字也行)
这个文件跟gnome下的回收站邮件的“恢复”选项有关(没有这个文件无法右键选择恢复删除文件)
[Trash Info]
Path=/home/tangfu/%E4%B8%8B%E8%BD%BD/progit.zh.pdf.zip
DeletionDate=2010-07-22T17:05:41

非linux标准文件系统上的文件删除到回收站时,每个挂载的分区都会有一个类似Trash的文件夹,对于NTFS.分区根目录下有.Trash-500文件夹,其里面结构跟.local/share/Trash完全一致,fedora系统的Trash同样也管理这个Trash,因此不同分区上删除的文件会放到自己所在分区的Trash中,然后路径都是针对自己所在分区而言,例如ntfs的根分区就直接写上文件名即可,如果没有-r标记目录直接跳过

另外,即便每个分区有自己的Trash,但是仍然可以将所有的删除文件都放到根文件系统下当前用户的Trash中。

【脚本】

一下脚本参考了网上用mv代替rm的一位朋友的脚本。(作者:lang;Email: lang123@sky.com )

1.先处理脚本参数-r,-V|–version,-v,–help|-h
2.然后忽略直接处理文件,对于文件夹默认不能mv
3.默认不能动/,即便有权限

 

【安装方法:】
1.拷贝rm-substutie.sh到任意PATH变量定义了的路径下
写一个rm.sh到/etc/profile.d,内容alias rm=rm-substutie.sh.修改rm.sh的权限和所有者于该目录下所有脚本一致

优点:扩展性好,脚本不会影响到系统设置或者程序,系统的升级,同时很多直接调用/bin/rm的其他脚本并不会受到影响
缺点:无法使用sudo,由于sudo的secure_path=/sbin:/bin:/usr/sbin:/usr/bin,所以必须替换原有的rm程序名称,否则sudo模式下仍然使用的是/bin/rm程序来删除

2.将/bin/rm改名,将rm-substutie.sh改为rm放入/bin文件夹中

优点:无论使用何种模式调用rm,数据都能正确的进入回收站中
缺点:对于少数脚本来说,虽然这个替代脚本处理了部分rm的参数,但并非完全兼容,使用的/bin/rm这个替代脚本可能会出现问题

【推荐方式:】
由于现在的发行版中sudo使用得特别的多,推荐使用第二种方式安装,而且通常对rm使用得最多的参数也就是-r ,-f,-v,因此一般也不会出问题
当然对于不用sudo来执行越权命令的用户使用第一种方式更加

【注意:】
在普通用户下,回收站中的root权限文件是无法右键选择清空的(没权限嘛),这个只有自己写个简单脚本来删除

脚本下载链接
==============================
易盘
下载:
http://www.163pan.com/files/h0k000s0c.html
文件名称:
rm-scripts.7z
文件介绍:
linux下rm替换脚本
==============================

关于指针的再思考

指针有两个要素:
1.*指针的指示符,一个*指明变量类型为指针。
2.指针变量,即指针标识符所指示的变量

指针的本质含义:
1.指针指示符可以想象成一个箭头,从指针变量指向指针变量值所标记的位置
2.指针变量可以直接当做是地址,因为它的值就是地址

一个(或多个)* 加上 一个指针变量 <=> 一个(或多个)方向 + 一个地址 <=> 一个具体位置的值

特殊的二级指针:

void **plink;   按照定义来理解*plink指示plink为指针变量则plink值为地址,**plink则指示*plink值为地址
void *addr;

plink = (void **)addr;   <1>
plink = addr;    <2>
*plink = addr;    <3>

<1>和<2>得到的结果相同,都是将指针变量addr的值付给二级指针变量plink,但是后者会提示警告指针类型不兼容
<3>则是将addr值作为二级指针中间变量值

plink = (void **)addr;此时如果访问**plink很可能就段错误了,因为作为变量值的*addr作为地址通常都是非法的

我们知道链表的实现都是通过结构体指针来连接的,为什么呢?因为单独的指针变量如果指向了他的后继,那么它所对应的值由谁来指向呢.因此结构体中可以自定义各种数据来使链表有意义,普通意义上的链表都是结构体中包含结构体指针来连接下一个结构体,如此循环而成.

1.linux内核链表结构有所不同,它的链表结构就只包含前驱指针和后继指针,没有定义任何相关联的数据。这样的链表有意义么?
仔细看了之后觉得这样很好,我们不用定义一个固定数据结构的链表,而只需将链表指针作为任何结构体的数据成员插入进去就可将链表指针所在的结构体链接起来,而获取链表对应的数据成员只需用宏定位到后继或前驱链表指针所在结构体的首址处,即可获取结构体中所有的数据,灵活性大大增强

2.uCOS内存管理部分的链表结构又有所不同。addr指向了内存区的起始地址,那么怎么让他又能充当链表的角色呢,addr作为索引的起点自然不能采用指向某某指针之类的做法,它必须指向物理内存单元。将addr作为二级指针的起始地址,然后依次链接到各个内存块的起始地址在二级指针层面addr就建立起了单纯的链表结构,但是一级指针层面addr仍然指向具体的内存单元。到此,寻找下一个空闲的内存块或者内存控制块就可以先将addr强制转换成二级指针来进行索引,这样内存分区内的内存块以及各内存分区之间对应的内存控制块都可以链接起来了