quotactl 함수 사용시 질문입니다...
글쓴이: s25kt0 / 작성시간: 금, 2004/09/03 - 3:55오후
안녕하세요...
사용자 디스크 용량을 제한하기 위해 quota를 쓰는게 일반적인걸 알고 있는데 지금 진행하는 프로젝트 환경상 quota를 직접 구현해야 합니다.
여기저기 검색끝에 quotactl이라는 함수를 찾아냈는데, 제대로 먹히지가 않네요..
도움좀 부탁드리겠습니다..
아래는 테스트 코드입니다..
#include <sys/types.h> #include <sys/quota.h> #include <errno.h> #include <stdio.h> int copy_user_quota_limits(const char *block_device, uid_t from, uid_t to) { struct dqblk dq; if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), block_device, from, (caddr_t) & dq) == 0) { if (quotactl(QCMD(Q_SETQLIM, USRQUOTA), block_device, to, (caddr_t) & dq) == 0) { return (0); } else { } } else { printf("copy_user_quota_limits: Failed to get userquota for uid %ld : %s\n", from, strerror(errno)); } return 0; } main(int argc, char **argv) { copy_user_quota_limits("/dev/hda6", 508, 509); }
컴파일은 그냥 단순히 gcc quota_test.c 이렇게 했습니다.
에러로는
copy_user_quota_limits: Failed to get userquota for uid 508 : Invalid argument
Invalid argument라는 에러 스트링이 뜨더군요..
도움 부탁드립니다..
Forums:
[시스템콜] quotactl 함수 관련
s25kt0
혹 성공은 하셨나요
저도 한번 해볼려고 했는데 잘안된는데
누구 아시는분은 소스 있으시면 부탁 드립니다.
전 지금 프비에서 테스트 하고 있습니다.
고수님들의 많으 도움 부탁 드립니다.
quotactl 함수 사용법
// 작성자 choi byung uck
// mail skywork70@nate.com
우선 프비에서 테스트 해보았습니다.
처음 할때 문제가 있는것 같아서
시스템에서 제공하는 qutota.c "/usr/src/usr.sbin/quota
시스템에서 제공하는 edqutota.c "/usr/src/usr.sbin/edquota
컴파일 gcc
gcc -c q.c
gcc -o q.exe q.o
1. 유저 아이디로 uid 찾기 uid값이 int 형임
2. quotactl("/data", QCMD(Q_SETQUOTA,USRQUOTA), id,(void*)&qp);
- "/data" <- fstab quota 값 지정한 곳 mount 되어야합니다.
기본적으로 시스템 부팅시 마운트 됩니다.
- QCMD(Q_SETQUOTA,USRQUOTA)
man quotactl 하셔서 세부 사항에 대한 메뉴얼을 참고 하세요
기본적으로 짧은 영문 이기에 불편 하지 않을 겁니다.
- id
메인 함수에 유저아이디로 값찾는 함수가 있습니다.
메인 함수만 잘보시면 될듯 합니다.
- (void*)&qp
quota.h 함수에 정의 되어 있는것을 사용하여 정의 하면 됩니다.
유저명은 argc[] 로 받습니다.
#q.exe username
이렇게 하면 됩니다. argc[]값에 사용자의 쿼터를 넘겨서 작성하면 되겠지요
기타내용은 사용자분이 알아서 하시고
소스 데이타 문제가 발생하시거나 이보다 좋은 소스가 있으시면
알려 주세요
참고로 mysql에 접속하는 C프로그램도 있는데 그건 필요하시면
올려 드리겠습니다.
안쓰는 함수도 있으니 편집해서 사용 하세요
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <ufs/ufs/quota.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fstab.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "/usr/src/usr.sbin/edquota/pathnames.h"
const char *qfname = QUOTAFILENAME;
const char *qfextension[] = INITQFNAMES;
const char *quotagroup = QUOTAGROUP;
char tmpfil[] = _PATH_TMP;
struct quotause {
struct quotause *next;
long flags;
struct dqblk dqblk;
char fsname[MAXPATHLEN + 1];
char qfname[1]; /* actually longer */
};
#define FOUND 0x01
//static register struct quotause *qup;
static void showuid(u_long uid);
static void showgid(u_long gid);
struct quotause *getprivs(long, int, char *);
int hasquota(struct fstab *, int, char **);
void putprivs(long, int, struct quotause *);
int getentry(const char *, int);
int alldigits(const char *s);
int lflag;
int qflag;
int vflag;
main(int argc, char *argv[])
{
struct dqblk qp;
struct quotause *qup, *protoprivs, *curprivs;
int ngroups;
gid_t mygid, gidset[NGROUPS];
int i, ch, gflag = 0, uflag = 0;
long long lim;
long id;
u_int32_t *limp;
int val1;
int rtn_val;
int quotatype;
char buf[MAXLOGNAME];
char username[]="";
char *cp;
mygid =getgid();
quotatype = USRQUOTA;
printf("\n Return user id :: %s", getuid());
printf("\n Return group id :: %s", mygid);
showuid(getuid());
showgid(mygid);
limp = &qup->dqblk.dqb_bhardlimit;
if (limp != NULL) {
printf("\n limp Data Not NULL\n");
lim = strtoll(cp, NULL, 10);
if (lim < 0 || lim > UINT_MAX){
errx(1, "invalid limit value: ""%lld", lim);
*limp = (u_int32_t)lim;
}
}
if(argc == 1){
fprintf(stderr," Input user id \n");
exit(0);
}
fprintf(stderr,"[0] -> %s\n", argv[0]);
fprintf(stderr,"[1] -> %s\n", argv[1]);
sprintf(buf,argv[1]);
//****************************
// user id
//****************************
id = getentry(buf, quotatype);
val1 = 100;
// Define Qutoa Limite Value
qp.dqb_bsoftlimit = btodb(1 * 1024);
qp.dqb_bhardlimit = btodb(1 * 1024);
qp.dqb_curblocks = btodb(1024);
qp.dqb_isoftlimit = btodb(val1 * 1024);
qp.dqb_ihardlimit = btodb(val1 * 1024);
qp.dqb_btime = 0;
qp.dqb_itime = 0;
fprintf(stderr,"Rtn_val::%d\n", rtn_val);
if(id == -1)
{
fprintf(stderr,"\nUser Not Found\n");
}
printf("\n Get User ID = %d", id);
quotatype = Q_SYNC; //
quotatype = Q_SETQUOTA; // disk limite
quotatype = Q_SETUSE; // user set
rtn_val = quotactl("/data", QCMD(Q_SETQUOTA,USRQUOTA), id,(void*)&qp);
//putprivs(id,Q_SYNC,&qup->dqblk);
fprintf(stderr,"Rtn Value :: %d \n", rtn_val);
printf("\n Program Terminate \n");
}
void
putprivs(id, quotatype, quplist)
long id;
int quotatype;
struct quotause *quplist;
{
register struct quotause *qup;
int qcmd, fd;
qcmd = QCMD(Q_SETQUOTA, quotatype);
qcmd = QCMD(Q_SETQUOTA,USRQUOTA);
//strcpy(qup->fsname,"/data/q.txt");
//printf("\n quplist :: %s", qup->fsname);
for (qup = quplist; qup; qup = qup->next) {
printf("\n qup :: %s", qup->next);
if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0)
continue;
if ((fd = open(qup->fsname, O_WRONLY)) < 0) {
warn("%s", qup->qfname);
} else {
lseek(fd, (long)id * (long)sizeof (struct dqblk), 0);
if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
sizeof (struct dqblk)) {
warn("%s", qup->qfname);
}
close(fd);
}
}
}
int
getentry(name, quotatype)
const char *name;
int quotatype;
{
struct passwd *pw;
struct group *gr;
if (alldigits(name))
return (atoi(name));
switch(quotatype) {
case USRQUOTA:
if ((pw = getpwnam(name)))
return (pw->pw_uid);
warnx("%s: no such user", name);
break;
case GRPQUOTA:
if ((gr = getgrnam(name)))
return (gr->gr_gid);
warnx("%s: no such group", name);
break;
default:
warnx("%d: unknown quota type", quotatype);
break;
}
sleep(1);
return (-1);
}
int
alldigits(s)
register const char *s;
{
register int c;
c = *s++;
do {
if (!isdigit(c))
return (0);
} while ((c = *s++));
return (1);
}
static void
showuid(u_long uid)
{
struct passwd *pwd = getpwuid(uid);
const char *name;
if (pwd == NULL)
name = "(no account)";
else
name = pwd->pw_name;
printf("\n uid -> %s", pwd->pw_name);
printf("\n upasswd -> %s", pwd->pw_passwd);
printf("\n pw_uid -> %s", pwd->pw_uid);
printf("\n pw_dir -> %s", pwd->pw_dir);
printf("\n********** end print ***********\n");
//showquotas(USRQUOTA, uid, name);
}
static void
showgid(u_long gid)
{
struct group *grp = getgrgid(gid);
const char *name;
if (grp == NULL)
name = "(no entry)";
else
name = grp->gr_name;
printf("\n Group ID :: %s", name);
printf("\n ******* END *********\n");
//showquotas(GRPQUOTA, gid, name);
}
/*
* Collect the requested quota information.
*/
struct quotause *
getprivs(id, quotatype, fspath)
register long id;
int quotatype;
char *fspath;
{
register struct fstab *fs;
register struct quotause *qup, *quptail;
struct quotause *quphead;
int qcmd, qupsize, fd;
char *qfpathname;
static int warned = 0;
setfsent();
quphead = (struct quotause *)0;
qcmd = QCMD(Q_GETQUOTA, quotatype);
while ((fs = getfsent())) {
if (fspath && *fspath && strcmp(fspath, fs->fs_spec) &&
strcmp(fspath, fs->fs_file))
continue;
if (strcmp(fs->fs_vfstype, "ufs"))
continue;
if (!hasquota(fs, quotatype, &qfpathname))
continue;
qupsize = sizeof(*qup) + strlen(qfpathname);
if ((qup = (struct quotause *)malloc(qupsize)) == NULL)
errx(2, "out of memory");
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
if (errno == EOPNOTSUPP && !warned) {
warned++;
warnx("warning: quotas are not compiled into this kernel");
sleep(3);
}
if ((fd = open(qfpathname, O_RDONLY)) < 0) {
fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
if (fd < 0 && errno != ENOENT) {
warn("%s", qfpathname);
free(qup);
continue;
}
warnx("creating quota file %s", qfpathname);
sleep(3);
(void) fchown(fd, getuid(),
getentry(quotagroup, GRPQUOTA));
(void) fchmod(fd, 0640);
}
lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
case 0: /* EOF */
/*
* Convert implicit 0 quota (EOF)
* into an explicit one (zero'ed dqblk)
*/
bzero((caddr_t)&qup->dqblk,
sizeof(struct dqblk));
break;
case sizeof(struct dqblk): /* OK */
break;
default: /* ERROR */
warn("read error in %s", qfpathname);
close(fd);
free(qup);
continue;
}
close(fd);
}
strcpy(qup->qfname, qfpathname);
strcpy(qup->fsname, fs->fs_file);
if (quphead == NULL)
quphead = qup;
else
quptail->next = qup;
quptail = qup;
qup->next = 0;
}
endfsent();
return (quphead);
}
/*
* Check to see if a particular quota is to be enabled.
*/
int
hasquota(fs, type, qfnamep)
register struct fstab *fs;
int type;
char **qfnamep;
{
register char *opt;
char *cp;
static char initname, usrname[100], grpname[100];
static char buf[BUFSIZ];
if (!initname) {
sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
initname = 1;
}
strcpy(buf, fs->fs_mntops);
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
if ((cp = index(opt, '=')))
*cp++ = '\0';
if (type == USRQUOTA && strcmp(opt, usrname) == 0)
break;
if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
break;
}
if (!opt)
return (0);
if (cp) {
*qfnamep = cp;
return (1);
}
(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
*qfnamep = buf;
return (1);
}
댓글 달기