⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk_info.c

📁 linux 系统控制硬盘旋转和停止的程序(spin down/up)
💻 C
字号:
/* * <disk_info.c> * * Copyright (C) 2000 Daniel Kobras * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *  * $Id: disk_info.c,v 1.15 2004/04/08 20:13:44 nold Exp $ * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "diskhelper.h"#include "disk_info.h"#include "part_info.h"#include "state.h"#include "util.h"#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include <sys/stat.h>#include <sys/sysmacros.h>	/* for major()/minor() macros */#include <sys/types.h>static disk_info_t prepend_entry(disk_info_t head){	disk_info_t di;	di = malloc(sizeof(struct disk_info_s));	if (!di)		return NULL;	di->next=head;	return di;}		static disk_info_t get_disk_entry(disk_info_t head, int major, int minor){	for (;head; head=head->next)		if (head->major==major && head->minor==minor)			break;	return head;}/* * Returns 1 if disk is a read/write mounted medium, 0 for read-only. * This check isn't too smart and currently only detects IDE CD-Roms. * If in doubt, we return 1 indication r/w which is the safe answer. */static int check_rw(disk_info_t di, char *name){	int dfd = -1, fd, ret = 1;	char buf[6], cdrom[] = "cdrom";	char *pos;		/* Currently we only know about IDE cdroms. */	if (di->major != IDE0_MAJOR && di->major != IDE1_MAJOR)		goto _out;		/* Kernel reports media type below /proc/ide/hd.../ even with	 * devfs installed. So we rely on devfs names instead.	 */	if ((pos=strrchr(name, (int) '/'))) {		if (!strcmp(pos+1, "cd"))			ret = 0;		goto _out;	}			fd = open(".", O_RDONLY);	if (chdir("/proc/ide") ||	    chdir(name) ||	    (fd = open("media", O_RDONLY)) == -1)		goto _out;		/* Careful here. The kernel (currently) returns "cdrom  ",	 * not "cdrom"! 	 */	if (read(fd, buf, 6) == 6 && !strncmp(buf, cdrom, 5))		ret = 0;	close(fd);_out:	if (dfd != -1)		fchdir(dfd);	else		chdir("/");	return ret;}	/* * Parse /proc/partitions to determine which kinds of disks are installed * in the system. */disk_info_t disk_info_init(void){	part_info_t part;	disk_info_t di=NULL;	int major, minor;	char *name;		part = part_info_init();	if (!part) {		ERR("Unable to open /proc/partitions");		return NULL;	}		while (part_info_disk_next(part)) {		major = part_info_get_major(part);		minor = part_info_get_minor(part);		/* Ignore meta-devices. */		if (IS_META(major, minor))			continue;		name = strdup(devname_get(part_info_get_name(part)));		di = prepend_entry(di);		DEBUG("Added entry for %s (%d, %d)", name, major, minor);		di->major=major;		di->minor=minor;		di->timeouts=NULL;		di->name=strdup(name);			di->is_rw=check_rw(di, name);			di->state=DISK_STATE_IGNORED;	}		part_info_release(part);	return di;}/*  * Return pointer to disk info structure associated with device <name>. */disk_info_t disk_info_get_byname(disk_info_t head, char *name){	int ret;	struct stat statbuf;	disk_info_t di;	ret = stat(name, &statbuf);	if (ret == -1) {		ERR("Unable to stat disk");		return NULL;	}	if (!S_ISBLK(statbuf.st_mode)) {		ERR("%s is not a valid block device", name);		return NULL;	}	di = get_disk_entry(head, major(statbuf.st_rdev), 	                          minor(statbuf.st_rdev));	if (!di) {		ERR("No partition entry for device (%d,%d)",			major(statbuf.st_rdev), minor(statbuf.st_rdev));		/* Some people tend to get the command line syntax wrong.		 * Try to be gentle and give a hint for names that look		 * like /dev/hda1 (instead of /dev/hda). Catches devfs		 * errors as well btw - those have .../part(.[0-9]) instead		 * of .../disc. */		if (strlen(name) && isdigit(name[strlen(name)-1]))			ERR("Are you trying to spin down a partition "			    "instead of the whole disk?");		return NULL;	}	free(di->name);	di->name=strdup(name);	return di;}void disk_info_mark_ro(disk_info_t di){	if (di)		di->is_rw=0;}/* * Initialize a disk drive (based on its device node <name>) for idle * monitoring with timeout as in <tohead> list. */void disk_info_setup(disk_info_t di, tolist_t tohead){	int timeout;		if (!di)		return;	di->spindown = spindown_setup(di->major, di->minor);		if (!di->spindown) {		ERR("Don't know how to spindown %s", di->name);		return;	}		di->timeouts = tohead;	timeout = timeout_get(tohead);	if (!NFD_TO_IS_VALID(timeout))		ERR("No valid timeout found for %s", di->name);	else if (NFD_TO_IS_REGULAR(timeout))		di->state = DISK_STATE_SPINNING;	DEBUG("Added disk %s, current timeout %d, state %d", 		di->name, timeout, di->state);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -