Add macro %isu_package to generate ISU Package
[platform/upstream/rpm.git] / lib / rpmchroot.c
1 #include "system.h"
2 #include <stdlib.h>
3 #include <rpm/rpmstring.h>
4 #include <rpm/rpmlog.h>
5 #include "lib/rpmchroot.h"
6 #include "debug.h"
7
8 struct rootState_s {
9     char *rootDir;
10     int chrootDone;
11     int cwd;
12 };
13
14 /* Process global chroot state */
15 static struct rootState_s rootState = {
16    .rootDir = NULL,
17    .chrootDone = 0,
18    .cwd = -1,
19 }; 
20
21 int rpmChrootSet(const char *rootDir)
22 {
23     int rc = 0;
24
25     /* Setting same rootDir again is a no-op and not an error */
26     if (rootDir && rootState.rootDir && rstreq(rootDir, rootState.rootDir))
27         return 0;
28
29     /* Resetting only permitted in neutral state */
30     if (rootState.chrootDone != 0)
31         return -1;
32
33     rootState.rootDir = _free(rootState.rootDir);
34     if (rootState.cwd >= 0) {
35         close(rootState.cwd);
36         rootState.cwd = -1;
37     }
38
39     if (rootDir != NULL) {
40         rootState.rootDir = rstrdup(rootDir);
41         rootState.cwd = open(".", O_RDONLY);
42         if (rootState.cwd < 0) {
43             rpmlog(RPMLOG_ERR, _("Unable to open current directory: %m\n"));
44             rc = -1;
45         }
46     }
47
48     return rc;
49 }
50
51 int rpmChrootIn(void)
52 {
53     int rc = 0;
54
55     if (rootState.rootDir == NULL || rstreq(rootState.rootDir, "/"))
56         return 0;
57
58     if (rootState.cwd < 0) {
59         rpmlog(RPMLOG_ERR, _("%s: chroot directory not set\n"), __func__);
60         return -1;
61     }
62
63     /* "refcounted" entry to chroot */
64     if (rootState.chrootDone > 0) {
65         rootState.chrootDone++;
66     } else if (rootState.chrootDone == 0) {
67         if (chdir("/") == 0 && chroot(rootState.rootDir) == 0) {
68             rootState.chrootDone = 1;
69         } else {
70             rpmlog(RPMLOG_ERR, _("Unable to change root directory: %m\n"));
71             rc = -1;
72         }
73     }
74     return rc;
75 }
76
77 int rpmChrootOut(void)
78 {
79     int rc = 0;
80     if (rootState.rootDir == NULL || rstreq(rootState.rootDir, "/"))
81         return 0;
82
83     if (rootState.cwd < 0) {
84         rpmlog(RPMLOG_ERR, _("%s: chroot directory not set\n"), __func__);
85         return -1;
86     }
87
88     /* "refcounted" return from chroot */
89     if (rootState.chrootDone > 1) {
90         rootState.chrootDone--;
91     } else if (rootState.chrootDone == 1) {
92         if (chroot(".") == 0 && fchdir(rootState.cwd) == 0) {
93             rootState.chrootDone = 0;
94         } else {
95             rpmlog(RPMLOG_ERR, _("Unable to restore root directory: %m\n"));
96             rc = -1;
97         }
98     }
99     return rc;
100 }
101
102 int rpmChrootDone(void)
103 {
104     return (rootState.chrootDone > 0);
105 }