~ubuntu-branches/ubuntu/quantal/pm-utils/quantal-proposed

1 by Tim Dijkstra
Import upstream version 0.99.2
1
/*
2
 * mark a swap device as not usable for thaw
3
 *
4
 * Copyright 2006 Red Hat, Inc.
5
 *
6
 * Authors:
7
 *   Peter Jones <pjones@redhat.com>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of version 2 of the GNU General Public License as
11
 * published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 *
22
 */
23
24
#define _GNU_SOURCE 1
25
26
#include <sys/ioctl.h>
27
#include <sys/types.h>
28
#include <sys/stat.h>
29
#include <fcntl.h>
30
#include <unistd.h>
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdint.h>
34
35
/* XXX this is a total hack for bad system headers. */
36
typedef u_int32_t __u32;
37
#include <linux/pmu.h>
38
39
typedef u_int64_t sector_t;
40
41
/*
42
 * Here's what the disk looks like after a successful hibernate:
43
44
 00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
45
 *
46
 00000400  01 00 00 00 ff df 03 00  00 00 00 00 00 00 00 00  |................|
47
 00000410  00 00 00 00 00 00 00 00  00 00 00 00 73 77 61 70  |............swap|
48
 00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
49
 *
50
 00000fe0  00 00 00 00 01 00 00 00  00 00 00 00 53 57 41 50  |............SWAP|
51
 00000ff0  53 50 41 43 45 32 53 31  53 55 53 50 45 4e 44 00  |SPACE2S1SUSPEND.|
52
53
 * And here's what it looks like if you haven't hibernated to it:
54
55
 00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
56
 *
57
 00000400  01 00 00 00 ff df 03 00  00 00 00 00 00 00 00 00  |................|
58
 00000410  00 00 00 00 00 00 00 00  00 00 00 00 73 77 61 70  |............swap|
59
 00000420  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
60
 *
61
 00000ff0  00 00 00 00 00 00 53 57  41 50 53 50 41 43 45 32  |......SWAPSPACE2|
62
63
 *
64
 */
65
66
/* The signature offset is annoying.  The struct is:
67
 * struct swsusp_header {
68
 *     char reserved[PAGE_SIZE - 20 - sizeof(sector_t)];
69
 *     sector_t image;
70
 *     char orig_sig[10];
71
 *     char sig[10];
72
 * }
73
 */
74
off_t get_sig_offset(int orig)
75
{
76
    int pagesize = sysconf(_SC_PAGESIZE);
77
78
    return (off_t)((sizeof (char) * pagesize) - (orig ? 20 : 10));
79
}
80
81
static inline int
82
print_usage(FILE *output, int retval)
83
{
84
    fprintf(output, "usage: pm-reset-swap <device node>\n");
85
    return retval;
86
}
87
88
int check_resume_block(FILE *dev, off_t offset)
89
{
90
    char buf[11] = {0,};
91
    off_t location = offset + get_sig_offset(0);
92
93
    if (fseek(dev, location, SEEK_SET) < 0)
94
        return -1;
95
    if (fread(buf, sizeof (char), 10, dev) != 10)
96
        return -1;
97
1.1.1 by Martin Pitt
Import upstream version 1.1.0
98
    if (!strncmp(buf, "S1SUSPEND", 9) ||
99
            !strncmp(buf, "ULSUSPEND", 9))
1 by Tim Dijkstra
Import upstream version 0.99.2
100
        return 1;
101
102
    return 0;
103
}
104
105
int clear_resume_block(FILE *dev, off_t offset)
106
{
107
    char buf[21] = {0,};
108
    off_t location = offset + get_sig_offset(1);
109
110
    if (fseek(dev, location, SEEK_SET) < 0)
111
        return -1;
112
113
    if (fread(buf, sizeof (char), 20, dev) != 20)
114
        return -1;
115
116
    if (fseek(dev, location, SEEK_SET) < 0)
117
        return -1;
118
119
    memmove(buf+10, buf, 10);
120
    memset(buf, '\0', 10);
121
122
    if (fwrite(buf, sizeof (char), 20, dev) != 20)
123
        return -1;
124
125
    return 0;
126
}
127
128
int main(int argc, char *argv[])
129
{
130
    FILE *dev = NULL;
131
    int rc;
132
133
    if (argc != 2)
134
        return print_usage(stderr, 1);
135
136
    if (!strcmp(argv[1], "--help")) {
137
        return print_usage(stdout, 0);
138
    }
139
140
    if (!(dev = fopen(argv[1], "r+b"))) {
141
        fprintf(stderr, "Could not open \"%s\": %m\n", argv[1]);
142
        return 1;
143
    }
144
145
    rc = check_resume_block(dev, 0);
146
    if (rc < 0) {
147
        fprintf(stderr, "Could not check \"%s\" for swap signature: %m\n",
148
                argv[1]);
149
        fclose(dev);
150
        return 2;
151
    }
1.1.1 by Martin Pitt
Import upstream version 1.1.0
152
1 by Tim Dijkstra
Import upstream version 0.99.2
153
    if (rc == 1) {
154
        if (clear_resume_block(dev, 0)) {
155
            fprintf(stderr, "Could not clear swap signature on \"%s\": %m\n",
156
                    argv[1]);
157
            fclose(dev);
158
            return 1;
159
        }
160
    }
161
        
162
    fclose(dev);
163
    return 0;
164
}
165
166
/*
167
 * vim:ts=8:sw=4:sts=4:et
168
 */